trans-intrinsic.cc revision 1.1 1 1.1 mrg /* Intrinsic translation
2 1.1 mrg Copyright (C) 2002-2022 Free Software Foundation, Inc.
3 1.1 mrg Contributed by Paul Brook <paul (at) nowt.org>
4 1.1 mrg and Steven Bosscher <s.bosscher (at) student.tudelft.nl>
5 1.1 mrg
6 1.1 mrg This file is part of GCC.
7 1.1 mrg
8 1.1 mrg GCC is free software; you can redistribute it and/or modify it under
9 1.1 mrg the terms of the GNU General Public License as published by the Free
10 1.1 mrg Software Foundation; either version 3, or (at your option) any later
11 1.1 mrg version.
12 1.1 mrg
13 1.1 mrg GCC is distributed in the hope that it will be useful, but WITHOUT ANY
14 1.1 mrg WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 1.1 mrg FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16 1.1 mrg for more details.
17 1.1 mrg
18 1.1 mrg You should have received a copy of the GNU General Public License
19 1.1 mrg along with GCC; see the file COPYING3. If not see
20 1.1 mrg <http://www.gnu.org/licenses/>. */
21 1.1 mrg
22 1.1 mrg /* trans-intrinsic.cc-- generate GENERIC trees for calls to intrinsics. */
23 1.1 mrg
24 1.1 mrg #include "config.h"
25 1.1 mrg #include "system.h"
26 1.1 mrg #include "coretypes.h"
27 1.1 mrg #include "memmodel.h"
28 1.1 mrg #include "tm.h" /* For UNITS_PER_WORD. */
29 1.1 mrg #include "tree.h"
30 1.1 mrg #include "gfortran.h"
31 1.1 mrg #include "trans.h"
32 1.1 mrg #include "stringpool.h"
33 1.1 mrg #include "fold-const.h"
34 1.1 mrg #include "internal-fn.h"
35 1.1 mrg #include "tree-nested.h"
36 1.1 mrg #include "stor-layout.h"
37 1.1 mrg #include "toplev.h" /* For rest_of_decl_compilation. */
38 1.1 mrg #include "arith.h"
39 1.1 mrg #include "trans-const.h"
40 1.1 mrg #include "trans-types.h"
41 1.1 mrg #include "trans-array.h"
42 1.1 mrg #include "dependency.h" /* For CAF array alias analysis. */
43 1.1 mrg #include "attribs.h"
44 1.1 mrg #include "realmpfr.h"
45 1.1 mrg
46 1.1 mrg /* Only for gfc_trans_assign and gfc_trans_pointer_assign. */
47 1.1 mrg
48 1.1 mrg /* This maps Fortran intrinsic math functions to external library or GCC
49 1.1 mrg builtin functions. */
50 1.1 mrg typedef struct GTY(()) gfc_intrinsic_map_t {
51 1.1 mrg /* The explicit enum is required to work around inadequacies in the
52 1.1 mrg garbage collection/gengtype parsing mechanism. */
53 1.1 mrg enum gfc_isym_id id;
54 1.1 mrg
55 1.1 mrg /* Enum value from the "language-independent", aka C-centric, part
56 1.1 mrg of gcc, or END_BUILTINS of no such value set. */
57 1.1 mrg enum built_in_function float_built_in;
58 1.1 mrg enum built_in_function double_built_in;
59 1.1 mrg enum built_in_function long_double_built_in;
60 1.1 mrg enum built_in_function complex_float_built_in;
61 1.1 mrg enum built_in_function complex_double_built_in;
62 1.1 mrg enum built_in_function complex_long_double_built_in;
63 1.1 mrg
64 1.1 mrg /* True if the naming pattern is to prepend "c" for complex and
65 1.1 mrg append "f" for kind=4. False if the naming pattern is to
66 1.1 mrg prepend "_gfortran_" and append "[rc](4|8|10|16)". */
67 1.1 mrg bool libm_name;
68 1.1 mrg
69 1.1 mrg /* True if a complex version of the function exists. */
70 1.1 mrg bool complex_available;
71 1.1 mrg
72 1.1 mrg /* True if the function should be marked const. */
73 1.1 mrg bool is_constant;
74 1.1 mrg
75 1.1 mrg /* The base library name of this function. */
76 1.1 mrg const char *name;
77 1.1 mrg
78 1.1 mrg /* Cache decls created for the various operand types. */
79 1.1 mrg tree real4_decl;
80 1.1 mrg tree real8_decl;
81 1.1 mrg tree real10_decl;
82 1.1 mrg tree real16_decl;
83 1.1 mrg tree complex4_decl;
84 1.1 mrg tree complex8_decl;
85 1.1 mrg tree complex10_decl;
86 1.1 mrg tree complex16_decl;
87 1.1 mrg }
88 1.1 mrg gfc_intrinsic_map_t;
89 1.1 mrg
90 1.1 mrg /* ??? The NARGS==1 hack here is based on the fact that (c99 at least)
91 1.1 mrg defines complex variants of all of the entries in mathbuiltins.def
92 1.1 mrg except for atan2. */
93 1.1 mrg #define DEFINE_MATH_BUILTIN(ID, NAME, ARGTYPE) \
94 1.1 mrg { GFC_ISYM_ ## ID, BUILT_IN_ ## ID ## F, BUILT_IN_ ## ID, \
95 1.1 mrg BUILT_IN_ ## ID ## L, END_BUILTINS, END_BUILTINS, END_BUILTINS, \
96 1.1 mrg true, false, true, NAME, NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE, \
97 1.1 mrg NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE},
98 1.1 mrg
99 1.1 mrg #define DEFINE_MATH_BUILTIN_C(ID, NAME, ARGTYPE) \
100 1.1 mrg { GFC_ISYM_ ## ID, BUILT_IN_ ## ID ## F, BUILT_IN_ ## ID, \
101 1.1 mrg BUILT_IN_ ## ID ## L, BUILT_IN_C ## ID ## F, BUILT_IN_C ## ID, \
102 1.1 mrg BUILT_IN_C ## ID ## L, true, true, true, NAME, NULL_TREE, NULL_TREE, \
103 1.1 mrg NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE},
104 1.1 mrg
105 1.1 mrg #define LIB_FUNCTION(ID, NAME, HAVE_COMPLEX) \
106 1.1 mrg { GFC_ISYM_ ## ID, END_BUILTINS, END_BUILTINS, END_BUILTINS, \
107 1.1 mrg END_BUILTINS, END_BUILTINS, END_BUILTINS, \
108 1.1 mrg false, HAVE_COMPLEX, true, NAME, NULL_TREE, NULL_TREE, NULL_TREE, \
109 1.1 mrg NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE }
110 1.1 mrg
111 1.1 mrg #define OTHER_BUILTIN(ID, NAME, TYPE, CONST) \
112 1.1 mrg { GFC_ISYM_NONE, BUILT_IN_ ## ID ## F, BUILT_IN_ ## ID, \
113 1.1 mrg BUILT_IN_ ## ID ## L, END_BUILTINS, END_BUILTINS, END_BUILTINS, \
114 1.1 mrg true, false, CONST, NAME, NULL_TREE, NULL_TREE, \
115 1.1 mrg NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE},
116 1.1 mrg
117 1.1 mrg static GTY(()) gfc_intrinsic_map_t gfc_intrinsic_map[] =
118 1.1 mrg {
119 1.1 mrg /* Functions built into gcc itself (DEFINE_MATH_BUILTIN and
120 1.1 mrg DEFINE_MATH_BUILTIN_C), then the built-ins that don't correspond
121 1.1 mrg to any GFC_ISYM id directly, which use the OTHER_BUILTIN macro. */
122 1.1 mrg #include "mathbuiltins.def"
123 1.1 mrg
124 1.1 mrg /* Functions in libgfortran. */
125 1.1 mrg LIB_FUNCTION (ERFC_SCALED, "erfc_scaled", false),
126 1.1 mrg LIB_FUNCTION (SIND, "sind", false),
127 1.1 mrg LIB_FUNCTION (COSD, "cosd", false),
128 1.1 mrg LIB_FUNCTION (TAND, "tand", false),
129 1.1 mrg
130 1.1 mrg /* End the list. */
131 1.1 mrg LIB_FUNCTION (NONE, NULL, false)
132 1.1 mrg
133 1.1 mrg };
134 1.1 mrg #undef OTHER_BUILTIN
135 1.1 mrg #undef LIB_FUNCTION
136 1.1 mrg #undef DEFINE_MATH_BUILTIN
137 1.1 mrg #undef DEFINE_MATH_BUILTIN_C
138 1.1 mrg
139 1.1 mrg
140 1.1 mrg enum rounding_mode { RND_ROUND, RND_TRUNC, RND_CEIL, RND_FLOOR };
141 1.1 mrg
142 1.1 mrg
143 1.1 mrg /* Find the correct variant of a given builtin from its argument. */
144 1.1 mrg static tree
145 1.1 mrg builtin_decl_for_precision (enum built_in_function base_built_in,
146 1.1 mrg int precision)
147 1.1 mrg {
148 1.1 mrg enum built_in_function i = END_BUILTINS;
149 1.1 mrg
150 1.1 mrg gfc_intrinsic_map_t *m;
151 1.1 mrg for (m = gfc_intrinsic_map; m->double_built_in != base_built_in ; m++)
152 1.1 mrg ;
153 1.1 mrg
154 1.1 mrg if (precision == TYPE_PRECISION (float_type_node))
155 1.1 mrg i = m->float_built_in;
156 1.1 mrg else if (precision == TYPE_PRECISION (double_type_node))
157 1.1 mrg i = m->double_built_in;
158 1.1 mrg else if (precision == TYPE_PRECISION (long_double_type_node)
159 1.1 mrg && (!gfc_real16_is_float128
160 1.1 mrg || long_double_type_node != gfc_float128_type_node))
161 1.1 mrg i = m->long_double_built_in;
162 1.1 mrg else if (precision == TYPE_PRECISION (gfc_float128_type_node))
163 1.1 mrg {
164 1.1 mrg /* Special treatment, because it is not exactly a built-in, but
165 1.1 mrg a library function. */
166 1.1 mrg return m->real16_decl;
167 1.1 mrg }
168 1.1 mrg
169 1.1 mrg return (i == END_BUILTINS ? NULL_TREE : builtin_decl_explicit (i));
170 1.1 mrg }
171 1.1 mrg
172 1.1 mrg
173 1.1 mrg tree
174 1.1 mrg gfc_builtin_decl_for_float_kind (enum built_in_function double_built_in,
175 1.1 mrg int kind)
176 1.1 mrg {
177 1.1 mrg int i = gfc_validate_kind (BT_REAL, kind, false);
178 1.1 mrg
179 1.1 mrg if (gfc_real_kinds[i].c_float128)
180 1.1 mrg {
181 1.1 mrg /* For _Float128, the story is a bit different, because we return
182 1.1 mrg a decl to a library function rather than a built-in. */
183 1.1 mrg gfc_intrinsic_map_t *m;
184 1.1 mrg for (m = gfc_intrinsic_map; m->double_built_in != double_built_in ; m++)
185 1.1 mrg ;
186 1.1 mrg
187 1.1 mrg return m->real16_decl;
188 1.1 mrg }
189 1.1 mrg
190 1.1 mrg return builtin_decl_for_precision (double_built_in,
191 1.1 mrg gfc_real_kinds[i].mode_precision);
192 1.1 mrg }
193 1.1 mrg
194 1.1 mrg
195 1.1 mrg /* Evaluate the arguments to an intrinsic function. The value
196 1.1 mrg of NARGS may be less than the actual number of arguments in EXPR
197 1.1 mrg to allow optional "KIND" arguments that are not included in the
198 1.1 mrg generated code to be ignored. */
199 1.1 mrg
200 1.1 mrg static void
201 1.1 mrg gfc_conv_intrinsic_function_args (gfc_se *se, gfc_expr *expr,
202 1.1 mrg tree *argarray, int nargs)
203 1.1 mrg {
204 1.1 mrg gfc_actual_arglist *actual;
205 1.1 mrg gfc_expr *e;
206 1.1 mrg gfc_intrinsic_arg *formal;
207 1.1 mrg gfc_se argse;
208 1.1 mrg int curr_arg;
209 1.1 mrg
210 1.1 mrg formal = expr->value.function.isym->formal;
211 1.1 mrg actual = expr->value.function.actual;
212 1.1 mrg
213 1.1 mrg for (curr_arg = 0; curr_arg < nargs; curr_arg++,
214 1.1 mrg actual = actual->next,
215 1.1 mrg formal = formal ? formal->next : NULL)
216 1.1 mrg {
217 1.1 mrg gcc_assert (actual);
218 1.1 mrg e = actual->expr;
219 1.1 mrg /* Skip omitted optional arguments. */
220 1.1 mrg if (!e)
221 1.1 mrg {
222 1.1 mrg --curr_arg;
223 1.1 mrg continue;
224 1.1 mrg }
225 1.1 mrg
226 1.1 mrg /* Evaluate the parameter. This will substitute scalarized
227 1.1 mrg references automatically. */
228 1.1 mrg gfc_init_se (&argse, se);
229 1.1 mrg
230 1.1 mrg if (e->ts.type == BT_CHARACTER)
231 1.1 mrg {
232 1.1 mrg gfc_conv_expr (&argse, e);
233 1.1 mrg gfc_conv_string_parameter (&argse);
234 1.1 mrg argarray[curr_arg++] = argse.string_length;
235 1.1 mrg gcc_assert (curr_arg < nargs);
236 1.1 mrg }
237 1.1 mrg else
238 1.1 mrg gfc_conv_expr_val (&argse, e);
239 1.1 mrg
240 1.1 mrg /* If an optional argument is itself an optional dummy argument,
241 1.1 mrg check its presence and substitute a null if absent. */
242 1.1 mrg if (e->expr_type == EXPR_VARIABLE
243 1.1 mrg && e->symtree->n.sym->attr.optional
244 1.1 mrg && formal
245 1.1 mrg && formal->optional)
246 1.1 mrg gfc_conv_missing_dummy (&argse, e, formal->ts, 0);
247 1.1 mrg
248 1.1 mrg gfc_add_block_to_block (&se->pre, &argse.pre);
249 1.1 mrg gfc_add_block_to_block (&se->post, &argse.post);
250 1.1 mrg argarray[curr_arg] = argse.expr;
251 1.1 mrg }
252 1.1 mrg }
253 1.1 mrg
254 1.1 mrg /* Count the number of actual arguments to the intrinsic function EXPR
255 1.1 mrg including any "hidden" string length arguments. */
256 1.1 mrg
257 1.1 mrg static unsigned int
258 1.1 mrg gfc_intrinsic_argument_list_length (gfc_expr *expr)
259 1.1 mrg {
260 1.1 mrg int n = 0;
261 1.1 mrg gfc_actual_arglist *actual;
262 1.1 mrg
263 1.1 mrg for (actual = expr->value.function.actual; actual; actual = actual->next)
264 1.1 mrg {
265 1.1 mrg if (!actual->expr)
266 1.1 mrg continue;
267 1.1 mrg
268 1.1 mrg if (actual->expr->ts.type == BT_CHARACTER)
269 1.1 mrg n += 2;
270 1.1 mrg else
271 1.1 mrg n++;
272 1.1 mrg }
273 1.1 mrg
274 1.1 mrg return n;
275 1.1 mrg }
276 1.1 mrg
277 1.1 mrg
278 1.1 mrg /* Conversions between different types are output by the frontend as
279 1.1 mrg intrinsic functions. We implement these directly with inline code. */
280 1.1 mrg
281 1.1 mrg static void
282 1.1 mrg gfc_conv_intrinsic_conversion (gfc_se * se, gfc_expr * expr)
283 1.1 mrg {
284 1.1 mrg tree type;
285 1.1 mrg tree *args;
286 1.1 mrg int nargs;
287 1.1 mrg
288 1.1 mrg nargs = gfc_intrinsic_argument_list_length (expr);
289 1.1 mrg args = XALLOCAVEC (tree, nargs);
290 1.1 mrg
291 1.1 mrg /* Evaluate all the arguments passed. Whilst we're only interested in the
292 1.1 mrg first one here, there are other parts of the front-end that assume this
293 1.1 mrg and will trigger an ICE if it's not the case. */
294 1.1 mrg type = gfc_typenode_for_spec (&expr->ts);
295 1.1 mrg gcc_assert (expr->value.function.actual->expr);
296 1.1 mrg gfc_conv_intrinsic_function_args (se, expr, args, nargs);
297 1.1 mrg
298 1.1 mrg /* Conversion between character kinds involves a call to a library
299 1.1 mrg function. */
300 1.1 mrg if (expr->ts.type == BT_CHARACTER)
301 1.1 mrg {
302 1.1 mrg tree fndecl, var, addr, tmp;
303 1.1 mrg
304 1.1 mrg if (expr->ts.kind == 1
305 1.1 mrg && expr->value.function.actual->expr->ts.kind == 4)
306 1.1 mrg fndecl = gfor_fndecl_convert_char4_to_char1;
307 1.1 mrg else if (expr->ts.kind == 4
308 1.1 mrg && expr->value.function.actual->expr->ts.kind == 1)
309 1.1 mrg fndecl = gfor_fndecl_convert_char1_to_char4;
310 1.1 mrg else
311 1.1 mrg gcc_unreachable ();
312 1.1 mrg
313 1.1 mrg /* Create the variable storing the converted value. */
314 1.1 mrg type = gfc_get_pchar_type (expr->ts.kind);
315 1.1 mrg var = gfc_create_var (type, "str");
316 1.1 mrg addr = gfc_build_addr_expr (build_pointer_type (type), var);
317 1.1 mrg
318 1.1 mrg /* Call the library function that will perform the conversion. */
319 1.1 mrg gcc_assert (nargs >= 2);
320 1.1 mrg tmp = build_call_expr_loc (input_location,
321 1.1 mrg fndecl, 3, addr, args[0], args[1]);
322 1.1 mrg gfc_add_expr_to_block (&se->pre, tmp);
323 1.1 mrg
324 1.1 mrg /* Free the temporary afterwards. */
325 1.1 mrg tmp = gfc_call_free (var);
326 1.1 mrg gfc_add_expr_to_block (&se->post, tmp);
327 1.1 mrg
328 1.1 mrg se->expr = var;
329 1.1 mrg se->string_length = args[0];
330 1.1 mrg
331 1.1 mrg return;
332 1.1 mrg }
333 1.1 mrg
334 1.1 mrg /* Conversion from complex to non-complex involves taking the real
335 1.1 mrg component of the value. */
336 1.1 mrg if (TREE_CODE (TREE_TYPE (args[0])) == COMPLEX_TYPE
337 1.1 mrg && expr->ts.type != BT_COMPLEX)
338 1.1 mrg {
339 1.1 mrg tree artype;
340 1.1 mrg
341 1.1 mrg artype = TREE_TYPE (TREE_TYPE (args[0]));
342 1.1 mrg args[0] = fold_build1_loc (input_location, REALPART_EXPR, artype,
343 1.1 mrg args[0]);
344 1.1 mrg }
345 1.1 mrg
346 1.1 mrg se->expr = convert (type, args[0]);
347 1.1 mrg }
348 1.1 mrg
349 1.1 mrg /* This is needed because the gcc backend only implements
350 1.1 mrg FIX_TRUNC_EXPR, which is the same as INT() in Fortran.
351 1.1 mrg FLOOR(x) = INT(x) <= x ? INT(x) : INT(x) - 1
352 1.1 mrg Similarly for CEILING. */
353 1.1 mrg
354 1.1 mrg static tree
355 1.1 mrg build_fixbound_expr (stmtblock_t * pblock, tree arg, tree type, int up)
356 1.1 mrg {
357 1.1 mrg tree tmp;
358 1.1 mrg tree cond;
359 1.1 mrg tree argtype;
360 1.1 mrg tree intval;
361 1.1 mrg
362 1.1 mrg argtype = TREE_TYPE (arg);
363 1.1 mrg arg = gfc_evaluate_now (arg, pblock);
364 1.1 mrg
365 1.1 mrg intval = convert (type, arg);
366 1.1 mrg intval = gfc_evaluate_now (intval, pblock);
367 1.1 mrg
368 1.1 mrg tmp = convert (argtype, intval);
369 1.1 mrg cond = fold_build2_loc (input_location, up ? GE_EXPR : LE_EXPR,
370 1.1 mrg logical_type_node, tmp, arg);
371 1.1 mrg
372 1.1 mrg tmp = fold_build2_loc (input_location, up ? PLUS_EXPR : MINUS_EXPR, type,
373 1.1 mrg intval, build_int_cst (type, 1));
374 1.1 mrg tmp = fold_build3_loc (input_location, COND_EXPR, type, cond, intval, tmp);
375 1.1 mrg return tmp;
376 1.1 mrg }
377 1.1 mrg
378 1.1 mrg
379 1.1 mrg /* Round to nearest integer, away from zero. */
380 1.1 mrg
381 1.1 mrg static tree
382 1.1 mrg build_round_expr (tree arg, tree restype)
383 1.1 mrg {
384 1.1 mrg tree argtype;
385 1.1 mrg tree fn;
386 1.1 mrg int argprec, resprec;
387 1.1 mrg
388 1.1 mrg argtype = TREE_TYPE (arg);
389 1.1 mrg argprec = TYPE_PRECISION (argtype);
390 1.1 mrg resprec = TYPE_PRECISION (restype);
391 1.1 mrg
392 1.1 mrg /* Depending on the type of the result, choose the int intrinsic (iround,
393 1.1 mrg available only as a builtin, therefore cannot use it for _Float128), long
394 1.1 mrg int intrinsic (lround family) or long long intrinsic (llround). If we
395 1.1 mrg don't have an appropriate function that converts directly to the integer
396 1.1 mrg type (such as kind == 16), just use ROUND, and then convert the result to
397 1.1 mrg an integer. We might also need to convert the result afterwards. */
398 1.1 mrg if (resprec <= INT_TYPE_SIZE && argprec <= LONG_DOUBLE_TYPE_SIZE)
399 1.1 mrg fn = builtin_decl_for_precision (BUILT_IN_IROUND, argprec);
400 1.1 mrg else if (resprec <= LONG_TYPE_SIZE)
401 1.1 mrg fn = builtin_decl_for_precision (BUILT_IN_LROUND, argprec);
402 1.1 mrg else if (resprec <= LONG_LONG_TYPE_SIZE)
403 1.1 mrg fn = builtin_decl_for_precision (BUILT_IN_LLROUND, argprec);
404 1.1 mrg else if (resprec >= argprec)
405 1.1 mrg fn = builtin_decl_for_precision (BUILT_IN_ROUND, argprec);
406 1.1 mrg else
407 1.1 mrg gcc_unreachable ();
408 1.1 mrg
409 1.1 mrg return convert (restype, build_call_expr_loc (input_location,
410 1.1 mrg fn, 1, arg));
411 1.1 mrg }
412 1.1 mrg
413 1.1 mrg
414 1.1 mrg /* Convert a real to an integer using a specific rounding mode.
415 1.1 mrg Ideally we would just build the corresponding GENERIC node,
416 1.1 mrg however the RTL expander only actually supports FIX_TRUNC_EXPR. */
417 1.1 mrg
418 1.1 mrg static tree
419 1.1 mrg build_fix_expr (stmtblock_t * pblock, tree arg, tree type,
420 1.1 mrg enum rounding_mode op)
421 1.1 mrg {
422 1.1 mrg switch (op)
423 1.1 mrg {
424 1.1 mrg case RND_FLOOR:
425 1.1 mrg return build_fixbound_expr (pblock, arg, type, 0);
426 1.1 mrg
427 1.1 mrg case RND_CEIL:
428 1.1 mrg return build_fixbound_expr (pblock, arg, type, 1);
429 1.1 mrg
430 1.1 mrg case RND_ROUND:
431 1.1 mrg return build_round_expr (arg, type);
432 1.1 mrg
433 1.1 mrg case RND_TRUNC:
434 1.1 mrg return fold_build1_loc (input_location, FIX_TRUNC_EXPR, type, arg);
435 1.1 mrg
436 1.1 mrg default:
437 1.1 mrg gcc_unreachable ();
438 1.1 mrg }
439 1.1 mrg }
440 1.1 mrg
441 1.1 mrg
442 1.1 mrg /* Round a real value using the specified rounding mode.
443 1.1 mrg We use a temporary integer of that same kind size as the result.
444 1.1 mrg Values larger than those that can be represented by this kind are
445 1.1 mrg unchanged, as they will not be accurate enough to represent the
446 1.1 mrg rounding.
447 1.1 mrg huge = HUGE (KIND (a))
448 1.1 mrg aint (a) = ((a > huge) || (a < -huge)) ? a : (real)(int)a
449 1.1 mrg */
450 1.1 mrg
451 1.1 mrg static void
452 1.1 mrg gfc_conv_intrinsic_aint (gfc_se * se, gfc_expr * expr, enum rounding_mode op)
453 1.1 mrg {
454 1.1 mrg tree type;
455 1.1 mrg tree itype;
456 1.1 mrg tree arg[2];
457 1.1 mrg tree tmp;
458 1.1 mrg tree cond;
459 1.1 mrg tree decl;
460 1.1 mrg mpfr_t huge;
461 1.1 mrg int n, nargs;
462 1.1 mrg int kind;
463 1.1 mrg
464 1.1 mrg kind = expr->ts.kind;
465 1.1 mrg nargs = gfc_intrinsic_argument_list_length (expr);
466 1.1 mrg
467 1.1 mrg decl = NULL_TREE;
468 1.1 mrg /* We have builtin functions for some cases. */
469 1.1 mrg switch (op)
470 1.1 mrg {
471 1.1 mrg case RND_ROUND:
472 1.1 mrg decl = gfc_builtin_decl_for_float_kind (BUILT_IN_ROUND, kind);
473 1.1 mrg break;
474 1.1 mrg
475 1.1 mrg case RND_TRUNC:
476 1.1 mrg decl = gfc_builtin_decl_for_float_kind (BUILT_IN_TRUNC, kind);
477 1.1 mrg break;
478 1.1 mrg
479 1.1 mrg default:
480 1.1 mrg gcc_unreachable ();
481 1.1 mrg }
482 1.1 mrg
483 1.1 mrg /* Evaluate the argument. */
484 1.1 mrg gcc_assert (expr->value.function.actual->expr);
485 1.1 mrg gfc_conv_intrinsic_function_args (se, expr, arg, nargs);
486 1.1 mrg
487 1.1 mrg /* Use a builtin function if one exists. */
488 1.1 mrg if (decl != NULL_TREE)
489 1.1 mrg {
490 1.1 mrg se->expr = build_call_expr_loc (input_location, decl, 1, arg[0]);
491 1.1 mrg return;
492 1.1 mrg }
493 1.1 mrg
494 1.1 mrg /* This code is probably redundant, but we'll keep it lying around just
495 1.1 mrg in case. */
496 1.1 mrg type = gfc_typenode_for_spec (&expr->ts);
497 1.1 mrg arg[0] = gfc_evaluate_now (arg[0], &se->pre);
498 1.1 mrg
499 1.1 mrg /* Test if the value is too large to handle sensibly. */
500 1.1 mrg gfc_set_model_kind (kind);
501 1.1 mrg mpfr_init (huge);
502 1.1 mrg n = gfc_validate_kind (BT_INTEGER, kind, false);
503 1.1 mrg mpfr_set_z (huge, gfc_integer_kinds[n].huge, GFC_RND_MODE);
504 1.1 mrg tmp = gfc_conv_mpfr_to_tree (huge, kind, 0);
505 1.1 mrg cond = fold_build2_loc (input_location, LT_EXPR, logical_type_node, arg[0],
506 1.1 mrg tmp);
507 1.1 mrg
508 1.1 mrg mpfr_neg (huge, huge, GFC_RND_MODE);
509 1.1 mrg tmp = gfc_conv_mpfr_to_tree (huge, kind, 0);
510 1.1 mrg tmp = fold_build2_loc (input_location, GT_EXPR, logical_type_node, arg[0],
511 1.1 mrg tmp);
512 1.1 mrg cond = fold_build2_loc (input_location, TRUTH_AND_EXPR, logical_type_node,
513 1.1 mrg cond, tmp);
514 1.1 mrg itype = gfc_get_int_type (kind);
515 1.1 mrg
516 1.1 mrg tmp = build_fix_expr (&se->pre, arg[0], itype, op);
517 1.1 mrg tmp = convert (type, tmp);
518 1.1 mrg se->expr = fold_build3_loc (input_location, COND_EXPR, type, cond, tmp,
519 1.1 mrg arg[0]);
520 1.1 mrg mpfr_clear (huge);
521 1.1 mrg }
522 1.1 mrg
523 1.1 mrg
524 1.1 mrg /* Convert to an integer using the specified rounding mode. */
525 1.1 mrg
526 1.1 mrg static void
527 1.1 mrg gfc_conv_intrinsic_int (gfc_se * se, gfc_expr * expr, enum rounding_mode op)
528 1.1 mrg {
529 1.1 mrg tree type;
530 1.1 mrg tree *args;
531 1.1 mrg int nargs;
532 1.1 mrg
533 1.1 mrg nargs = gfc_intrinsic_argument_list_length (expr);
534 1.1 mrg args = XALLOCAVEC (tree, nargs);
535 1.1 mrg
536 1.1 mrg /* Evaluate the argument, we process all arguments even though we only
537 1.1 mrg use the first one for code generation purposes. */
538 1.1 mrg type = gfc_typenode_for_spec (&expr->ts);
539 1.1 mrg gcc_assert (expr->value.function.actual->expr);
540 1.1 mrg gfc_conv_intrinsic_function_args (se, expr, args, nargs);
541 1.1 mrg
542 1.1 mrg if (TREE_CODE (TREE_TYPE (args[0])) == INTEGER_TYPE)
543 1.1 mrg {
544 1.1 mrg /* Conversion to a different integer kind. */
545 1.1 mrg se->expr = convert (type, args[0]);
546 1.1 mrg }
547 1.1 mrg else
548 1.1 mrg {
549 1.1 mrg /* Conversion from complex to non-complex involves taking the real
550 1.1 mrg component of the value. */
551 1.1 mrg if (TREE_CODE (TREE_TYPE (args[0])) == COMPLEX_TYPE
552 1.1 mrg && expr->ts.type != BT_COMPLEX)
553 1.1 mrg {
554 1.1 mrg tree artype;
555 1.1 mrg
556 1.1 mrg artype = TREE_TYPE (TREE_TYPE (args[0]));
557 1.1 mrg args[0] = fold_build1_loc (input_location, REALPART_EXPR, artype,
558 1.1 mrg args[0]);
559 1.1 mrg }
560 1.1 mrg
561 1.1 mrg se->expr = build_fix_expr (&se->pre, args[0], type, op);
562 1.1 mrg }
563 1.1 mrg }
564 1.1 mrg
565 1.1 mrg
566 1.1 mrg /* Get the imaginary component of a value. */
567 1.1 mrg
568 1.1 mrg static void
569 1.1 mrg gfc_conv_intrinsic_imagpart (gfc_se * se, gfc_expr * expr)
570 1.1 mrg {
571 1.1 mrg tree arg;
572 1.1 mrg
573 1.1 mrg gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
574 1.1 mrg se->expr = fold_build1_loc (input_location, IMAGPART_EXPR,
575 1.1 mrg TREE_TYPE (TREE_TYPE (arg)), arg);
576 1.1 mrg }
577 1.1 mrg
578 1.1 mrg
579 1.1 mrg /* Get the complex conjugate of a value. */
580 1.1 mrg
581 1.1 mrg static void
582 1.1 mrg gfc_conv_intrinsic_conjg (gfc_se * se, gfc_expr * expr)
583 1.1 mrg {
584 1.1 mrg tree arg;
585 1.1 mrg
586 1.1 mrg gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
587 1.1 mrg se->expr = fold_build1_loc (input_location, CONJ_EXPR, TREE_TYPE (arg), arg);
588 1.1 mrg }
589 1.1 mrg
590 1.1 mrg
591 1.1 mrg
592 1.1 mrg static tree
593 1.1 mrg define_quad_builtin (const char *name, tree type, bool is_const)
594 1.1 mrg {
595 1.1 mrg tree fndecl;
596 1.1 mrg fndecl = build_decl (input_location, FUNCTION_DECL, get_identifier (name),
597 1.1 mrg type);
598 1.1 mrg
599 1.1 mrg /* Mark the decl as external. */
600 1.1 mrg DECL_EXTERNAL (fndecl) = 1;
601 1.1 mrg TREE_PUBLIC (fndecl) = 1;
602 1.1 mrg
603 1.1 mrg /* Mark it __attribute__((const)). */
604 1.1 mrg TREE_READONLY (fndecl) = is_const;
605 1.1 mrg
606 1.1 mrg rest_of_decl_compilation (fndecl, 1, 0);
607 1.1 mrg
608 1.1 mrg return fndecl;
609 1.1 mrg }
610 1.1 mrg
611 1.1 mrg /* Add SIMD attribute for FNDECL built-in if the built-in
612 1.1 mrg name is in VECTORIZED_BUILTINS. */
613 1.1 mrg
614 1.1 mrg static void
615 1.1 mrg add_simd_flag_for_built_in (tree fndecl)
616 1.1 mrg {
617 1.1 mrg if (gfc_vectorized_builtins == NULL
618 1.1 mrg || fndecl == NULL_TREE)
619 1.1 mrg return;
620 1.1 mrg
621 1.1 mrg const char *name = IDENTIFIER_POINTER (DECL_NAME (fndecl));
622 1.1 mrg int *clauses = gfc_vectorized_builtins->get (name);
623 1.1 mrg if (clauses)
624 1.1 mrg {
625 1.1 mrg for (unsigned i = 0; i < 3; i++)
626 1.1 mrg if (*clauses & (1 << i))
627 1.1 mrg {
628 1.1 mrg gfc_simd_clause simd_type = (gfc_simd_clause)*clauses;
629 1.1 mrg tree omp_clause = NULL_TREE;
630 1.1 mrg if (simd_type == SIMD_NONE)
631 1.1 mrg ; /* No SIMD clause. */
632 1.1 mrg else
633 1.1 mrg {
634 1.1 mrg omp_clause_code code
635 1.1 mrg = (simd_type == SIMD_INBRANCH
636 1.1 mrg ? OMP_CLAUSE_INBRANCH : OMP_CLAUSE_NOTINBRANCH);
637 1.1 mrg omp_clause = build_omp_clause (UNKNOWN_LOCATION, code);
638 1.1 mrg omp_clause = build_tree_list (NULL_TREE, omp_clause);
639 1.1 mrg }
640 1.1 mrg
641 1.1 mrg DECL_ATTRIBUTES (fndecl)
642 1.1 mrg = tree_cons (get_identifier ("omp declare simd"), omp_clause,
643 1.1 mrg DECL_ATTRIBUTES (fndecl));
644 1.1 mrg }
645 1.1 mrg }
646 1.1 mrg }
647 1.1 mrg
648 1.1 mrg /* Set SIMD attribute to all built-in functions that are mentioned
649 1.1 mrg in gfc_vectorized_builtins vector. */
650 1.1 mrg
651 1.1 mrg void
652 1.1 mrg gfc_adjust_builtins (void)
653 1.1 mrg {
654 1.1 mrg gfc_intrinsic_map_t *m;
655 1.1 mrg for (m = gfc_intrinsic_map;
656 1.1 mrg m->id != GFC_ISYM_NONE || m->double_built_in != END_BUILTINS; m++)
657 1.1 mrg {
658 1.1 mrg add_simd_flag_for_built_in (m->real4_decl);
659 1.1 mrg add_simd_flag_for_built_in (m->complex4_decl);
660 1.1 mrg add_simd_flag_for_built_in (m->real8_decl);
661 1.1 mrg add_simd_flag_for_built_in (m->complex8_decl);
662 1.1 mrg add_simd_flag_for_built_in (m->real10_decl);
663 1.1 mrg add_simd_flag_for_built_in (m->complex10_decl);
664 1.1 mrg add_simd_flag_for_built_in (m->real16_decl);
665 1.1 mrg add_simd_flag_for_built_in (m->complex16_decl);
666 1.1 mrg add_simd_flag_for_built_in (m->real16_decl);
667 1.1 mrg add_simd_flag_for_built_in (m->complex16_decl);
668 1.1 mrg }
669 1.1 mrg
670 1.1 mrg /* Release all strings. */
671 1.1 mrg if (gfc_vectorized_builtins != NULL)
672 1.1 mrg {
673 1.1 mrg for (hash_map<nofree_string_hash, int>::iterator it
674 1.1 mrg = gfc_vectorized_builtins->begin ();
675 1.1 mrg it != gfc_vectorized_builtins->end (); ++it)
676 1.1 mrg free (CONST_CAST (char *, (*it).first));
677 1.1 mrg
678 1.1 mrg delete gfc_vectorized_builtins;
679 1.1 mrg gfc_vectorized_builtins = NULL;
680 1.1 mrg }
681 1.1 mrg }
682 1.1 mrg
683 1.1 mrg /* Initialize function decls for library functions. The external functions
684 1.1 mrg are created as required. Builtin functions are added here. */
685 1.1 mrg
686 1.1 mrg void
687 1.1 mrg gfc_build_intrinsic_lib_fndecls (void)
688 1.1 mrg {
689 1.1 mrg gfc_intrinsic_map_t *m;
690 1.1 mrg tree quad_decls[END_BUILTINS + 1];
691 1.1 mrg
692 1.1 mrg if (gfc_real16_is_float128)
693 1.1 mrg {
694 1.1 mrg /* If we have soft-float types, we create the decls for their
695 1.1 mrg C99-like library functions. For now, we only handle _Float128
696 1.1 mrg q-suffixed functions. */
697 1.1 mrg
698 1.1 mrg tree type, complex_type, func_1, func_2, func_cabs, func_frexp;
699 1.1 mrg tree func_iround, func_lround, func_llround, func_scalbn, func_cpow;
700 1.1 mrg
701 1.1 mrg memset (quad_decls, 0, sizeof(tree) * (END_BUILTINS + 1));
702 1.1 mrg
703 1.1 mrg type = gfc_float128_type_node;
704 1.1 mrg complex_type = gfc_complex_float128_type_node;
705 1.1 mrg /* type (*) (type) */
706 1.1 mrg func_1 = build_function_type_list (type, type, NULL_TREE);
707 1.1 mrg /* int (*) (type) */
708 1.1 mrg func_iround = build_function_type_list (integer_type_node,
709 1.1 mrg type, NULL_TREE);
710 1.1 mrg /* long (*) (type) */
711 1.1 mrg func_lround = build_function_type_list (long_integer_type_node,
712 1.1 mrg type, NULL_TREE);
713 1.1 mrg /* long long (*) (type) */
714 1.1 mrg func_llround = build_function_type_list (long_long_integer_type_node,
715 1.1 mrg type, NULL_TREE);
716 1.1 mrg /* type (*) (type, type) */
717 1.1 mrg func_2 = build_function_type_list (type, type, type, NULL_TREE);
718 1.1 mrg /* type (*) (type, &int) */
719 1.1 mrg func_frexp
720 1.1 mrg = build_function_type_list (type,
721 1.1 mrg type,
722 1.1 mrg build_pointer_type (integer_type_node),
723 1.1 mrg NULL_TREE);
724 1.1 mrg /* type (*) (type, int) */
725 1.1 mrg func_scalbn = build_function_type_list (type,
726 1.1 mrg type, integer_type_node, NULL_TREE);
727 1.1 mrg /* type (*) (complex type) */
728 1.1 mrg func_cabs = build_function_type_list (type, complex_type, NULL_TREE);
729 1.1 mrg /* complex type (*) (complex type, complex type) */
730 1.1 mrg func_cpow
731 1.1 mrg = build_function_type_list (complex_type,
732 1.1 mrg complex_type, complex_type, NULL_TREE);
733 1.1 mrg
734 1.1 mrg #define DEFINE_MATH_BUILTIN(ID, NAME, ARGTYPE)
735 1.1 mrg #define DEFINE_MATH_BUILTIN_C(ID, NAME, ARGTYPE)
736 1.1 mrg #define LIB_FUNCTION(ID, NAME, HAVE_COMPLEX)
737 1.1 mrg
738 1.1 mrg /* Only these built-ins are actually needed here. These are used directly
739 1.1 mrg from the code, when calling builtin_decl_for_precision() or
740 1.1 mrg builtin_decl_for_float_type(). The others are all constructed by
741 1.1 mrg gfc_get_intrinsic_lib_fndecl(). */
742 1.1 mrg #define OTHER_BUILTIN(ID, NAME, TYPE, CONST) \
743 1.1 mrg quad_decls[BUILT_IN_ ## ID] = define_quad_builtin (NAME "q", func_ ## TYPE, CONST);
744 1.1 mrg
745 1.1 mrg #include "mathbuiltins.def"
746 1.1 mrg
747 1.1 mrg #undef OTHER_BUILTIN
748 1.1 mrg #undef LIB_FUNCTION
749 1.1 mrg #undef DEFINE_MATH_BUILTIN
750 1.1 mrg #undef DEFINE_MATH_BUILTIN_C
751 1.1 mrg
752 1.1 mrg /* There is one built-in we defined manually, because it gets called
753 1.1 mrg with builtin_decl_for_precision() or builtin_decl_for_float_type()
754 1.1 mrg even though it is not an OTHER_BUILTIN: it is SQRT. */
755 1.1 mrg quad_decls[BUILT_IN_SQRT] = define_quad_builtin ("sqrtq", func_1, true);
756 1.1 mrg
757 1.1 mrg }
758 1.1 mrg
759 1.1 mrg /* Add GCC builtin functions. */
760 1.1 mrg for (m = gfc_intrinsic_map;
761 1.1 mrg m->id != GFC_ISYM_NONE || m->double_built_in != END_BUILTINS; m++)
762 1.1 mrg {
763 1.1 mrg if (m->float_built_in != END_BUILTINS)
764 1.1 mrg m->real4_decl = builtin_decl_explicit (m->float_built_in);
765 1.1 mrg if (m->complex_float_built_in != END_BUILTINS)
766 1.1 mrg m->complex4_decl = builtin_decl_explicit (m->complex_float_built_in);
767 1.1 mrg if (m->double_built_in != END_BUILTINS)
768 1.1 mrg m->real8_decl = builtin_decl_explicit (m->double_built_in);
769 1.1 mrg if (m->complex_double_built_in != END_BUILTINS)
770 1.1 mrg m->complex8_decl = builtin_decl_explicit (m->complex_double_built_in);
771 1.1 mrg
772 1.1 mrg /* If real(kind=10) exists, it is always long double. */
773 1.1 mrg if (m->long_double_built_in != END_BUILTINS)
774 1.1 mrg m->real10_decl = builtin_decl_explicit (m->long_double_built_in);
775 1.1 mrg if (m->complex_long_double_built_in != END_BUILTINS)
776 1.1 mrg m->complex10_decl
777 1.1 mrg = builtin_decl_explicit (m->complex_long_double_built_in);
778 1.1 mrg
779 1.1 mrg if (!gfc_real16_is_float128)
780 1.1 mrg {
781 1.1 mrg if (m->long_double_built_in != END_BUILTINS)
782 1.1 mrg m->real16_decl = builtin_decl_explicit (m->long_double_built_in);
783 1.1 mrg if (m->complex_long_double_built_in != END_BUILTINS)
784 1.1 mrg m->complex16_decl
785 1.1 mrg = builtin_decl_explicit (m->complex_long_double_built_in);
786 1.1 mrg }
787 1.1 mrg else if (quad_decls[m->double_built_in] != NULL_TREE)
788 1.1 mrg {
789 1.1 mrg /* Quad-precision function calls are constructed when first
790 1.1 mrg needed by builtin_decl_for_precision(), except for those
791 1.1 mrg that will be used directly (define by OTHER_BUILTIN). */
792 1.1 mrg m->real16_decl = quad_decls[m->double_built_in];
793 1.1 mrg }
794 1.1 mrg else if (quad_decls[m->complex_double_built_in] != NULL_TREE)
795 1.1 mrg {
796 1.1 mrg /* Same thing for the complex ones. */
797 1.1 mrg m->complex16_decl = quad_decls[m->double_built_in];
798 1.1 mrg }
799 1.1 mrg }
800 1.1 mrg }
801 1.1 mrg
802 1.1 mrg
803 1.1 mrg /* Create a fndecl for a simple intrinsic library function. */
804 1.1 mrg
805 1.1 mrg static tree
806 1.1 mrg gfc_get_intrinsic_lib_fndecl (gfc_intrinsic_map_t * m, gfc_expr * expr)
807 1.1 mrg {
808 1.1 mrg tree type;
809 1.1 mrg vec<tree, va_gc> *argtypes;
810 1.1 mrg tree fndecl;
811 1.1 mrg gfc_actual_arglist *actual;
812 1.1 mrg tree *pdecl;
813 1.1 mrg gfc_typespec *ts;
814 1.1 mrg char name[GFC_MAX_SYMBOL_LEN + 3];
815 1.1 mrg
816 1.1 mrg ts = &expr->ts;
817 1.1 mrg if (ts->type == BT_REAL)
818 1.1 mrg {
819 1.1 mrg switch (ts->kind)
820 1.1 mrg {
821 1.1 mrg case 4:
822 1.1 mrg pdecl = &m->real4_decl;
823 1.1 mrg break;
824 1.1 mrg case 8:
825 1.1 mrg pdecl = &m->real8_decl;
826 1.1 mrg break;
827 1.1 mrg case 10:
828 1.1 mrg pdecl = &m->real10_decl;
829 1.1 mrg break;
830 1.1 mrg case 16:
831 1.1 mrg pdecl = &m->real16_decl;
832 1.1 mrg break;
833 1.1 mrg default:
834 1.1 mrg gcc_unreachable ();
835 1.1 mrg }
836 1.1 mrg }
837 1.1 mrg else if (ts->type == BT_COMPLEX)
838 1.1 mrg {
839 1.1 mrg gcc_assert (m->complex_available);
840 1.1 mrg
841 1.1 mrg switch (ts->kind)
842 1.1 mrg {
843 1.1 mrg case 4:
844 1.1 mrg pdecl = &m->complex4_decl;
845 1.1 mrg break;
846 1.1 mrg case 8:
847 1.1 mrg pdecl = &m->complex8_decl;
848 1.1 mrg break;
849 1.1 mrg case 10:
850 1.1 mrg pdecl = &m->complex10_decl;
851 1.1 mrg break;
852 1.1 mrg case 16:
853 1.1 mrg pdecl = &m->complex16_decl;
854 1.1 mrg break;
855 1.1 mrg default:
856 1.1 mrg gcc_unreachable ();
857 1.1 mrg }
858 1.1 mrg }
859 1.1 mrg else
860 1.1 mrg gcc_unreachable ();
861 1.1 mrg
862 1.1 mrg if (*pdecl)
863 1.1 mrg return *pdecl;
864 1.1 mrg
865 1.1 mrg if (m->libm_name)
866 1.1 mrg {
867 1.1 mrg int n = gfc_validate_kind (BT_REAL, ts->kind, false);
868 1.1 mrg if (gfc_real_kinds[n].c_float)
869 1.1 mrg snprintf (name, sizeof (name), "%s%s%s",
870 1.1 mrg ts->type == BT_COMPLEX ? "c" : "", m->name, "f");
871 1.1 mrg else if (gfc_real_kinds[n].c_double)
872 1.1 mrg snprintf (name, sizeof (name), "%s%s",
873 1.1 mrg ts->type == BT_COMPLEX ? "c" : "", m->name);
874 1.1 mrg else if (gfc_real_kinds[n].c_long_double)
875 1.1 mrg snprintf (name, sizeof (name), "%s%s%s",
876 1.1 mrg ts->type == BT_COMPLEX ? "c" : "", m->name, "l");
877 1.1 mrg else if (gfc_real_kinds[n].c_float128)
878 1.1 mrg snprintf (name, sizeof (name), "%s%s%s",
879 1.1 mrg ts->type == BT_COMPLEX ? "c" : "", m->name, "q");
880 1.1 mrg else
881 1.1 mrg gcc_unreachable ();
882 1.1 mrg }
883 1.1 mrg else
884 1.1 mrg {
885 1.1 mrg snprintf (name, sizeof (name), PREFIX ("%s_%c%d"), m->name,
886 1.1 mrg ts->type == BT_COMPLEX ? 'c' : 'r',
887 1.1 mrg gfc_type_abi_kind (ts));
888 1.1 mrg }
889 1.1 mrg
890 1.1 mrg argtypes = NULL;
891 1.1 mrg for (actual = expr->value.function.actual; actual; actual = actual->next)
892 1.1 mrg {
893 1.1 mrg type = gfc_typenode_for_spec (&actual->expr->ts);
894 1.1 mrg vec_safe_push (argtypes, type);
895 1.1 mrg }
896 1.1 mrg type = build_function_type_vec (gfc_typenode_for_spec (ts), argtypes);
897 1.1 mrg fndecl = build_decl (input_location,
898 1.1 mrg FUNCTION_DECL, get_identifier (name), type);
899 1.1 mrg
900 1.1 mrg /* Mark the decl as external. */
901 1.1 mrg DECL_EXTERNAL (fndecl) = 1;
902 1.1 mrg TREE_PUBLIC (fndecl) = 1;
903 1.1 mrg
904 1.1 mrg /* Mark it __attribute__((const)), if possible. */
905 1.1 mrg TREE_READONLY (fndecl) = m->is_constant;
906 1.1 mrg
907 1.1 mrg rest_of_decl_compilation (fndecl, 1, 0);
908 1.1 mrg
909 1.1 mrg (*pdecl) = fndecl;
910 1.1 mrg return fndecl;
911 1.1 mrg }
912 1.1 mrg
913 1.1 mrg
914 1.1 mrg /* Convert an intrinsic function into an external or builtin call. */
915 1.1 mrg
916 1.1 mrg static void
917 1.1 mrg gfc_conv_intrinsic_lib_function (gfc_se * se, gfc_expr * expr)
918 1.1 mrg {
919 1.1 mrg gfc_intrinsic_map_t *m;
920 1.1 mrg tree fndecl;
921 1.1 mrg tree rettype;
922 1.1 mrg tree *args;
923 1.1 mrg unsigned int num_args;
924 1.1 mrg gfc_isym_id id;
925 1.1 mrg
926 1.1 mrg id = expr->value.function.isym->id;
927 1.1 mrg /* Find the entry for this function. */
928 1.1 mrg for (m = gfc_intrinsic_map;
929 1.1 mrg m->id != GFC_ISYM_NONE || m->double_built_in != END_BUILTINS; m++)
930 1.1 mrg {
931 1.1 mrg if (id == m->id)
932 1.1 mrg break;
933 1.1 mrg }
934 1.1 mrg
935 1.1 mrg if (m->id == GFC_ISYM_NONE)
936 1.1 mrg {
937 1.1 mrg gfc_internal_error ("Intrinsic function %qs (%d) not recognized",
938 1.1 mrg expr->value.function.name, id);
939 1.1 mrg }
940 1.1 mrg
941 1.1 mrg /* Get the decl and generate the call. */
942 1.1 mrg num_args = gfc_intrinsic_argument_list_length (expr);
943 1.1 mrg args = XALLOCAVEC (tree, num_args);
944 1.1 mrg
945 1.1 mrg gfc_conv_intrinsic_function_args (se, expr, args, num_args);
946 1.1 mrg fndecl = gfc_get_intrinsic_lib_fndecl (m, expr);
947 1.1 mrg rettype = TREE_TYPE (TREE_TYPE (fndecl));
948 1.1 mrg
949 1.1 mrg fndecl = build_addr (fndecl);
950 1.1 mrg se->expr = build_call_array_loc (input_location, rettype, fndecl, num_args, args);
951 1.1 mrg }
952 1.1 mrg
953 1.1 mrg
954 1.1 mrg /* If bounds-checking is enabled, create code to verify at runtime that the
955 1.1 mrg string lengths for both expressions are the same (needed for e.g. MERGE).
956 1.1 mrg If bounds-checking is not enabled, does nothing. */
957 1.1 mrg
958 1.1 mrg void
959 1.1 mrg gfc_trans_same_strlen_check (const char* intr_name, locus* where,
960 1.1 mrg tree a, tree b, stmtblock_t* target)
961 1.1 mrg {
962 1.1 mrg tree cond;
963 1.1 mrg tree name;
964 1.1 mrg
965 1.1 mrg /* If bounds-checking is disabled, do nothing. */
966 1.1 mrg if (!(gfc_option.rtcheck & GFC_RTCHECK_BOUNDS))
967 1.1 mrg return;
968 1.1 mrg
969 1.1 mrg /* Compare the two string lengths. */
970 1.1 mrg cond = fold_build2_loc (input_location, NE_EXPR, logical_type_node, a, b);
971 1.1 mrg
972 1.1 mrg /* Output the runtime-check. */
973 1.1 mrg name = gfc_build_cstring_const (intr_name);
974 1.1 mrg name = gfc_build_addr_expr (pchar_type_node, name);
975 1.1 mrg gfc_trans_runtime_check (true, false, cond, target, where,
976 1.1 mrg "Unequal character lengths (%ld/%ld) in %s",
977 1.1 mrg fold_convert (long_integer_type_node, a),
978 1.1 mrg fold_convert (long_integer_type_node, b), name);
979 1.1 mrg }
980 1.1 mrg
981 1.1 mrg
982 1.1 mrg /* The EXPONENT(X) intrinsic function is translated into
983 1.1 mrg int ret;
984 1.1 mrg return isfinite(X) ? (frexp (X, &ret) , ret) : huge
985 1.1 mrg so that if X is a NaN or infinity, the result is HUGE(0).
986 1.1 mrg */
987 1.1 mrg
988 1.1 mrg static void
989 1.1 mrg gfc_conv_intrinsic_exponent (gfc_se *se, gfc_expr *expr)
990 1.1 mrg {
991 1.1 mrg tree arg, type, res, tmp, frexp, cond, huge;
992 1.1 mrg int i;
993 1.1 mrg
994 1.1 mrg frexp = gfc_builtin_decl_for_float_kind (BUILT_IN_FREXP,
995 1.1 mrg expr->value.function.actual->expr->ts.kind);
996 1.1 mrg
997 1.1 mrg gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
998 1.1 mrg arg = gfc_evaluate_now (arg, &se->pre);
999 1.1 mrg
1000 1.1 mrg i = gfc_validate_kind (BT_INTEGER, gfc_c_int_kind, false);
1001 1.1 mrg huge = gfc_conv_mpz_to_tree (gfc_integer_kinds[i].huge, gfc_c_int_kind);
1002 1.1 mrg cond = build_call_expr_loc (input_location,
1003 1.1 mrg builtin_decl_explicit (BUILT_IN_ISFINITE),
1004 1.1 mrg 1, arg);
1005 1.1 mrg
1006 1.1 mrg res = gfc_create_var (integer_type_node, NULL);
1007 1.1 mrg tmp = build_call_expr_loc (input_location, frexp, 2, arg,
1008 1.1 mrg gfc_build_addr_expr (NULL_TREE, res));
1009 1.1 mrg tmp = fold_build2_loc (input_location, COMPOUND_EXPR, integer_type_node,
1010 1.1 mrg tmp, res);
1011 1.1 mrg se->expr = fold_build3_loc (input_location, COND_EXPR, integer_type_node,
1012 1.1 mrg cond, tmp, huge);
1013 1.1 mrg
1014 1.1 mrg type = gfc_typenode_for_spec (&expr->ts);
1015 1.1 mrg se->expr = fold_convert (type, se->expr);
1016 1.1 mrg }
1017 1.1 mrg
1018 1.1 mrg
1019 1.1 mrg /* Fill in the following structure
1020 1.1 mrg struct caf_vector_t {
1021 1.1 mrg size_t nvec; // size of the vector
1022 1.1 mrg union {
1023 1.1 mrg struct {
1024 1.1 mrg void *vector;
1025 1.1 mrg int kind;
1026 1.1 mrg } v;
1027 1.1 mrg struct {
1028 1.1 mrg ptrdiff_t lower_bound;
1029 1.1 mrg ptrdiff_t upper_bound;
1030 1.1 mrg ptrdiff_t stride;
1031 1.1 mrg } triplet;
1032 1.1 mrg } u;
1033 1.1 mrg } */
1034 1.1 mrg
1035 1.1 mrg static void
1036 1.1 mrg conv_caf_vector_subscript_elem (stmtblock_t *block, int i, tree desc,
1037 1.1 mrg tree lower, tree upper, tree stride,
1038 1.1 mrg tree vector, int kind, tree nvec)
1039 1.1 mrg {
1040 1.1 mrg tree field, type, tmp;
1041 1.1 mrg
1042 1.1 mrg desc = gfc_build_array_ref (desc, gfc_rank_cst[i], NULL_TREE);
1043 1.1 mrg type = TREE_TYPE (desc);
1044 1.1 mrg
1045 1.1 mrg field = gfc_advance_chain (TYPE_FIELDS (type), 0);
1046 1.1 mrg tmp = fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (field),
1047 1.1 mrg desc, field, NULL_TREE);
1048 1.1 mrg gfc_add_modify (block, tmp, fold_convert (TREE_TYPE (field), nvec));
1049 1.1 mrg
1050 1.1 mrg /* Access union. */
1051 1.1 mrg field = gfc_advance_chain (TYPE_FIELDS (type), 1);
1052 1.1 mrg desc = fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (field),
1053 1.1 mrg desc, field, NULL_TREE);
1054 1.1 mrg type = TREE_TYPE (desc);
1055 1.1 mrg
1056 1.1 mrg /* Access the inner struct. */
1057 1.1 mrg field = gfc_advance_chain (TYPE_FIELDS (type), vector != NULL_TREE ? 0 : 1);
1058 1.1 mrg desc = fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (field),
1059 1.1 mrg desc, field, NULL_TREE);
1060 1.1 mrg type = TREE_TYPE (desc);
1061 1.1 mrg
1062 1.1 mrg if (vector != NULL_TREE)
1063 1.1 mrg {
1064 1.1 mrg /* Set vector and kind. */
1065 1.1 mrg field = gfc_advance_chain (TYPE_FIELDS (type), 0);
1066 1.1 mrg tmp = fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (field),
1067 1.1 mrg desc, field, NULL_TREE);
1068 1.1 mrg gfc_add_modify (block, tmp, fold_convert (TREE_TYPE (field), vector));
1069 1.1 mrg field = gfc_advance_chain (TYPE_FIELDS (type), 1);
1070 1.1 mrg tmp = fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (field),
1071 1.1 mrg desc, field, NULL_TREE);
1072 1.1 mrg gfc_add_modify (block, tmp, build_int_cst (integer_type_node, kind));
1073 1.1 mrg }
1074 1.1 mrg else
1075 1.1 mrg {
1076 1.1 mrg /* Set dim.lower/upper/stride. */
1077 1.1 mrg field = gfc_advance_chain (TYPE_FIELDS (type), 0);
1078 1.1 mrg tmp = fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (field),
1079 1.1 mrg desc, field, NULL_TREE);
1080 1.1 mrg gfc_add_modify (block, tmp, fold_convert (TREE_TYPE (field), lower));
1081 1.1 mrg
1082 1.1 mrg field = gfc_advance_chain (TYPE_FIELDS (type), 1);
1083 1.1 mrg tmp = fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (field),
1084 1.1 mrg desc, field, NULL_TREE);
1085 1.1 mrg gfc_add_modify (block, tmp, fold_convert (TREE_TYPE (field), upper));
1086 1.1 mrg
1087 1.1 mrg field = gfc_advance_chain (TYPE_FIELDS (type), 2);
1088 1.1 mrg tmp = fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (field),
1089 1.1 mrg desc, field, NULL_TREE);
1090 1.1 mrg gfc_add_modify (block, tmp, fold_convert (TREE_TYPE (field), stride));
1091 1.1 mrg }
1092 1.1 mrg }
1093 1.1 mrg
1094 1.1 mrg
1095 1.1 mrg static tree
1096 1.1 mrg conv_caf_vector_subscript (stmtblock_t *block, tree desc, gfc_array_ref *ar)
1097 1.1 mrg {
1098 1.1 mrg gfc_se argse;
1099 1.1 mrg tree var, lower, upper = NULL_TREE, stride = NULL_TREE, vector, nvec;
1100 1.1 mrg tree lbound, ubound, tmp;
1101 1.1 mrg int i;
1102 1.1 mrg
1103 1.1 mrg var = gfc_create_var (gfc_get_caf_vector_type (ar->dimen), "vector");
1104 1.1 mrg
1105 1.1 mrg for (i = 0; i < ar->dimen; i++)
1106 1.1 mrg switch (ar->dimen_type[i])
1107 1.1 mrg {
1108 1.1 mrg case DIMEN_RANGE:
1109 1.1 mrg if (ar->end[i])
1110 1.1 mrg {
1111 1.1 mrg gfc_init_se (&argse, NULL);
1112 1.1 mrg gfc_conv_expr (&argse, ar->end[i]);
1113 1.1 mrg gfc_add_block_to_block (block, &argse.pre);
1114 1.1 mrg upper = gfc_evaluate_now (argse.expr, block);
1115 1.1 mrg }
1116 1.1 mrg else
1117 1.1 mrg upper = gfc_conv_descriptor_ubound_get (desc, gfc_rank_cst[i]);
1118 1.1 mrg if (ar->stride[i])
1119 1.1 mrg {
1120 1.1 mrg gfc_init_se (&argse, NULL);
1121 1.1 mrg gfc_conv_expr (&argse, ar->stride[i]);
1122 1.1 mrg gfc_add_block_to_block (block, &argse.pre);
1123 1.1 mrg stride = gfc_evaluate_now (argse.expr, block);
1124 1.1 mrg }
1125 1.1 mrg else
1126 1.1 mrg stride = gfc_index_one_node;
1127 1.1 mrg
1128 1.1 mrg /* Fall through. */
1129 1.1 mrg case DIMEN_ELEMENT:
1130 1.1 mrg if (ar->start[i])
1131 1.1 mrg {
1132 1.1 mrg gfc_init_se (&argse, NULL);
1133 1.1 mrg gfc_conv_expr (&argse, ar->start[i]);
1134 1.1 mrg gfc_add_block_to_block (block, &argse.pre);
1135 1.1 mrg lower = gfc_evaluate_now (argse.expr, block);
1136 1.1 mrg }
1137 1.1 mrg else
1138 1.1 mrg lower = gfc_conv_descriptor_lbound_get (desc, gfc_rank_cst[i]);
1139 1.1 mrg if (ar->dimen_type[i] == DIMEN_ELEMENT)
1140 1.1 mrg {
1141 1.1 mrg upper = lower;
1142 1.1 mrg stride = gfc_index_one_node;
1143 1.1 mrg }
1144 1.1 mrg vector = NULL_TREE;
1145 1.1 mrg nvec = size_zero_node;
1146 1.1 mrg conv_caf_vector_subscript_elem (block, i, var, lower, upper, stride,
1147 1.1 mrg vector, 0, nvec);
1148 1.1 mrg break;
1149 1.1 mrg
1150 1.1 mrg case DIMEN_VECTOR:
1151 1.1 mrg gfc_init_se (&argse, NULL);
1152 1.1 mrg argse.descriptor_only = 1;
1153 1.1 mrg gfc_conv_expr_descriptor (&argse, ar->start[i]);
1154 1.1 mrg gfc_add_block_to_block (block, &argse.pre);
1155 1.1 mrg vector = argse.expr;
1156 1.1 mrg lbound = gfc_conv_descriptor_lbound_get (vector, gfc_rank_cst[0]);
1157 1.1 mrg ubound = gfc_conv_descriptor_ubound_get (vector, gfc_rank_cst[0]);
1158 1.1 mrg nvec = gfc_conv_array_extent_dim (lbound, ubound, NULL);
1159 1.1 mrg tmp = gfc_conv_descriptor_stride_get (vector, gfc_rank_cst[0]);
1160 1.1 mrg nvec = fold_build2_loc (input_location, TRUNC_DIV_EXPR,
1161 1.1 mrg TREE_TYPE (nvec), nvec, tmp);
1162 1.1 mrg lower = gfc_index_zero_node;
1163 1.1 mrg upper = gfc_index_zero_node;
1164 1.1 mrg stride = gfc_index_zero_node;
1165 1.1 mrg vector = gfc_conv_descriptor_data_get (vector);
1166 1.1 mrg conv_caf_vector_subscript_elem (block, i, var, lower, upper, stride,
1167 1.1 mrg vector, ar->start[i]->ts.kind, nvec);
1168 1.1 mrg break;
1169 1.1 mrg default:
1170 1.1 mrg gcc_unreachable();
1171 1.1 mrg }
1172 1.1 mrg return gfc_build_addr_expr (NULL_TREE, var);
1173 1.1 mrg }
1174 1.1 mrg
1175 1.1 mrg
1176 1.1 mrg static tree
1177 1.1 mrg compute_component_offset (tree field, tree type)
1178 1.1 mrg {
1179 1.1 mrg tree tmp;
1180 1.1 mrg if (DECL_FIELD_BIT_OFFSET (field) != NULL_TREE
1181 1.1 mrg && !integer_zerop (DECL_FIELD_BIT_OFFSET (field)))
1182 1.1 mrg {
1183 1.1 mrg tmp = fold_build2 (TRUNC_DIV_EXPR, type,
1184 1.1 mrg DECL_FIELD_BIT_OFFSET (field),
1185 1.1 mrg bitsize_unit_node);
1186 1.1 mrg return fold_build2 (PLUS_EXPR, type, DECL_FIELD_OFFSET (field), tmp);
1187 1.1 mrg }
1188 1.1 mrg else
1189 1.1 mrg return DECL_FIELD_OFFSET (field);
1190 1.1 mrg }
1191 1.1 mrg
1192 1.1 mrg
1193 1.1 mrg static tree
1194 1.1 mrg conv_expr_ref_to_caf_ref (stmtblock_t *block, gfc_expr *expr)
1195 1.1 mrg {
1196 1.1 mrg gfc_ref *ref = expr->ref, *last_comp_ref;
1197 1.1 mrg tree caf_ref = NULL_TREE, prev_caf_ref = NULL_TREE, reference_type, tmp, tmp2,
1198 1.1 mrg field, last_type, inner_struct, mode, mode_rhs, dim_array, dim, dim_type,
1199 1.1 mrg start, end, stride, vector, nvec;
1200 1.1 mrg gfc_se se;
1201 1.1 mrg bool ref_static_array = false;
1202 1.1 mrg tree last_component_ref_tree = NULL_TREE;
1203 1.1 mrg int i, last_type_n;
1204 1.1 mrg
1205 1.1 mrg if (expr->symtree)
1206 1.1 mrg {
1207 1.1 mrg last_component_ref_tree = expr->symtree->n.sym->backend_decl;
1208 1.1 mrg ref_static_array = !expr->symtree->n.sym->attr.allocatable
1209 1.1 mrg && !expr->symtree->n.sym->attr.pointer;
1210 1.1 mrg }
1211 1.1 mrg
1212 1.1 mrg /* Prevent uninit-warning. */
1213 1.1 mrg reference_type = NULL_TREE;
1214 1.1 mrg
1215 1.1 mrg /* Skip refs upto the first coarray-ref. */
1216 1.1 mrg last_comp_ref = NULL;
1217 1.1 mrg while (ref && (ref->type != REF_ARRAY || ref->u.ar.codimen == 0))
1218 1.1 mrg {
1219 1.1 mrg /* Remember the type of components skipped. */
1220 1.1 mrg if (ref->type == REF_COMPONENT)
1221 1.1 mrg last_comp_ref = ref;
1222 1.1 mrg ref = ref->next;
1223 1.1 mrg }
1224 1.1 mrg /* When a component was skipped, get the type information of the last
1225 1.1 mrg component ref, else get the type from the symbol. */
1226 1.1 mrg if (last_comp_ref)
1227 1.1 mrg {
1228 1.1 mrg last_type = gfc_typenode_for_spec (&last_comp_ref->u.c.component->ts);
1229 1.1 mrg last_type_n = last_comp_ref->u.c.component->ts.type;
1230 1.1 mrg }
1231 1.1 mrg else
1232 1.1 mrg {
1233 1.1 mrg last_type = gfc_typenode_for_spec (&expr->symtree->n.sym->ts);
1234 1.1 mrg last_type_n = expr->symtree->n.sym->ts.type;
1235 1.1 mrg }
1236 1.1 mrg
1237 1.1 mrg while (ref)
1238 1.1 mrg {
1239 1.1 mrg if (ref->type == REF_ARRAY && ref->u.ar.codimen > 0
1240 1.1 mrg && ref->u.ar.dimen == 0)
1241 1.1 mrg {
1242 1.1 mrg /* Skip pure coindexes. */
1243 1.1 mrg ref = ref->next;
1244 1.1 mrg continue;
1245 1.1 mrg }
1246 1.1 mrg tmp = gfc_create_var (gfc_get_caf_reference_type (), "caf_ref");
1247 1.1 mrg reference_type = TREE_TYPE (tmp);
1248 1.1 mrg
1249 1.1 mrg if (caf_ref == NULL_TREE)
1250 1.1 mrg caf_ref = tmp;
1251 1.1 mrg
1252 1.1 mrg /* Construct the chain of refs. */
1253 1.1 mrg if (prev_caf_ref != NULL_TREE)
1254 1.1 mrg {
1255 1.1 mrg field = gfc_advance_chain (TYPE_FIELDS (reference_type), 0);
1256 1.1 mrg tmp2 = fold_build3_loc (input_location, COMPONENT_REF,
1257 1.1 mrg TREE_TYPE (field), prev_caf_ref, field,
1258 1.1 mrg NULL_TREE);
1259 1.1 mrg gfc_add_modify (block, tmp2, gfc_build_addr_expr (TREE_TYPE (field),
1260 1.1 mrg tmp));
1261 1.1 mrg }
1262 1.1 mrg prev_caf_ref = tmp;
1263 1.1 mrg
1264 1.1 mrg switch (ref->type)
1265 1.1 mrg {
1266 1.1 mrg case REF_COMPONENT:
1267 1.1 mrg last_type = gfc_typenode_for_spec (&ref->u.c.component->ts);
1268 1.1 mrg last_type_n = ref->u.c.component->ts.type;
1269 1.1 mrg /* Set the type of the ref. */
1270 1.1 mrg field = gfc_advance_chain (TYPE_FIELDS (reference_type), 1);
1271 1.1 mrg tmp = fold_build3_loc (input_location, COMPONENT_REF,
1272 1.1 mrg TREE_TYPE (field), prev_caf_ref, field,
1273 1.1 mrg NULL_TREE);
1274 1.1 mrg gfc_add_modify (block, tmp, build_int_cst (integer_type_node,
1275 1.1 mrg GFC_CAF_REF_COMPONENT));
1276 1.1 mrg
1277 1.1 mrg /* Ref the c in union u. */
1278 1.1 mrg field = gfc_advance_chain (TYPE_FIELDS (reference_type), 3);
1279 1.1 mrg tmp = fold_build3_loc (input_location, COMPONENT_REF,
1280 1.1 mrg TREE_TYPE (field), prev_caf_ref, field,
1281 1.1 mrg NULL_TREE);
1282 1.1 mrg field = gfc_advance_chain (TYPE_FIELDS (TREE_TYPE (field)), 0);
1283 1.1 mrg inner_struct = fold_build3_loc (input_location, COMPONENT_REF,
1284 1.1 mrg TREE_TYPE (field), tmp, field,
1285 1.1 mrg NULL_TREE);
1286 1.1 mrg
1287 1.1 mrg /* Set the offset. */
1288 1.1 mrg field = gfc_advance_chain (TYPE_FIELDS (TREE_TYPE (inner_struct)), 0);
1289 1.1 mrg tmp = fold_build3_loc (input_location, COMPONENT_REF,
1290 1.1 mrg TREE_TYPE (field), inner_struct, field,
1291 1.1 mrg NULL_TREE);
1292 1.1 mrg /* Computing the offset is somewhat harder. The bit_offset has to be
1293 1.1 mrg taken into account. When the bit_offset in the field_decl is non-
1294 1.1 mrg null, divide it by the bitsize_unit and add it to the regular
1295 1.1 mrg offset. */
1296 1.1 mrg tmp2 = compute_component_offset (ref->u.c.component->backend_decl,
1297 1.1 mrg TREE_TYPE (tmp));
1298 1.1 mrg gfc_add_modify (block, tmp, fold_convert (TREE_TYPE (tmp), tmp2));
1299 1.1 mrg
1300 1.1 mrg /* Set caf_token_offset. */
1301 1.1 mrg field = gfc_advance_chain (TYPE_FIELDS (TREE_TYPE (inner_struct)), 1);
1302 1.1 mrg tmp = fold_build3_loc (input_location, COMPONENT_REF,
1303 1.1 mrg TREE_TYPE (field), inner_struct, field,
1304 1.1 mrg NULL_TREE);
1305 1.1 mrg if ((ref->u.c.component->attr.allocatable
1306 1.1 mrg || ref->u.c.component->attr.pointer)
1307 1.1 mrg && ref->u.c.component->attr.dimension)
1308 1.1 mrg {
1309 1.1 mrg tree arr_desc_token_offset;
1310 1.1 mrg /* Get the token field from the descriptor. */
1311 1.1 mrg arr_desc_token_offset = TREE_OPERAND (
1312 1.1 mrg gfc_conv_descriptor_token (ref->u.c.component->backend_decl), 1);
1313 1.1 mrg arr_desc_token_offset
1314 1.1 mrg = compute_component_offset (arr_desc_token_offset,
1315 1.1 mrg TREE_TYPE (tmp));
1316 1.1 mrg tmp2 = fold_build2_loc (input_location, PLUS_EXPR,
1317 1.1 mrg TREE_TYPE (tmp2), tmp2,
1318 1.1 mrg arr_desc_token_offset);
1319 1.1 mrg }
1320 1.1 mrg else if (ref->u.c.component->caf_token)
1321 1.1 mrg tmp2 = compute_component_offset (ref->u.c.component->caf_token,
1322 1.1 mrg TREE_TYPE (tmp));
1323 1.1 mrg else
1324 1.1 mrg tmp2 = integer_zero_node;
1325 1.1 mrg gfc_add_modify (block, tmp, fold_convert (TREE_TYPE (tmp), tmp2));
1326 1.1 mrg
1327 1.1 mrg /* Remember whether this ref was to a non-allocatable/non-pointer
1328 1.1 mrg component so the next array ref can be tailored correctly. */
1329 1.1 mrg ref_static_array = !ref->u.c.component->attr.allocatable
1330 1.1 mrg && !ref->u.c.component->attr.pointer;
1331 1.1 mrg last_component_ref_tree = ref_static_array
1332 1.1 mrg ? ref->u.c.component->backend_decl : NULL_TREE;
1333 1.1 mrg break;
1334 1.1 mrg case REF_ARRAY:
1335 1.1 mrg if (ref_static_array && ref->u.ar.as->type == AS_DEFERRED)
1336 1.1 mrg ref_static_array = false;
1337 1.1 mrg /* Set the type of the ref. */
1338 1.1 mrg field = gfc_advance_chain (TYPE_FIELDS (reference_type), 1);
1339 1.1 mrg tmp = fold_build3_loc (input_location, COMPONENT_REF,
1340 1.1 mrg TREE_TYPE (field), prev_caf_ref, field,
1341 1.1 mrg NULL_TREE);
1342 1.1 mrg gfc_add_modify (block, tmp, build_int_cst (integer_type_node,
1343 1.1 mrg ref_static_array
1344 1.1 mrg ? GFC_CAF_REF_STATIC_ARRAY
1345 1.1 mrg : GFC_CAF_REF_ARRAY));
1346 1.1 mrg
1347 1.1 mrg /* Ref the a in union u. */
1348 1.1 mrg field = gfc_advance_chain (TYPE_FIELDS (reference_type), 3);
1349 1.1 mrg tmp = fold_build3_loc (input_location, COMPONENT_REF,
1350 1.1 mrg TREE_TYPE (field), prev_caf_ref, field,
1351 1.1 mrg NULL_TREE);
1352 1.1 mrg field = gfc_advance_chain (TYPE_FIELDS (TREE_TYPE (field)), 1);
1353 1.1 mrg inner_struct = fold_build3_loc (input_location, COMPONENT_REF,
1354 1.1 mrg TREE_TYPE (field), tmp, field,
1355 1.1 mrg NULL_TREE);
1356 1.1 mrg
1357 1.1 mrg /* Set the static_array_type in a for static arrays. */
1358 1.1 mrg if (ref_static_array)
1359 1.1 mrg {
1360 1.1 mrg field = gfc_advance_chain (TYPE_FIELDS (TREE_TYPE (inner_struct)),
1361 1.1 mrg 1);
1362 1.1 mrg tmp = fold_build3_loc (input_location, COMPONENT_REF,
1363 1.1 mrg TREE_TYPE (field), inner_struct, field,
1364 1.1 mrg NULL_TREE);
1365 1.1 mrg gfc_add_modify (block, tmp, build_int_cst (TREE_TYPE (tmp),
1366 1.1 mrg last_type_n));
1367 1.1 mrg }
1368 1.1 mrg /* Ref the mode in the inner_struct. */
1369 1.1 mrg field = gfc_advance_chain (TYPE_FIELDS (TREE_TYPE (inner_struct)), 0);
1370 1.1 mrg mode = fold_build3_loc (input_location, COMPONENT_REF,
1371 1.1 mrg TREE_TYPE (field), inner_struct, field,
1372 1.1 mrg NULL_TREE);
1373 1.1 mrg /* Ref the dim in the inner_struct. */
1374 1.1 mrg field = gfc_advance_chain (TYPE_FIELDS (TREE_TYPE (inner_struct)), 2);
1375 1.1 mrg dim_array = fold_build3_loc (input_location, COMPONENT_REF,
1376 1.1 mrg TREE_TYPE (field), inner_struct, field,
1377 1.1 mrg NULL_TREE);
1378 1.1 mrg for (i = 0; i < ref->u.ar.dimen; ++i)
1379 1.1 mrg {
1380 1.1 mrg /* Ref dim i. */
1381 1.1 mrg dim = gfc_build_array_ref (dim_array, gfc_rank_cst[i], NULL_TREE);
1382 1.1 mrg dim_type = TREE_TYPE (dim);
1383 1.1 mrg mode_rhs = start = end = stride = NULL_TREE;
1384 1.1 mrg switch (ref->u.ar.dimen_type[i])
1385 1.1 mrg {
1386 1.1 mrg case DIMEN_RANGE:
1387 1.1 mrg if (ref->u.ar.end[i])
1388 1.1 mrg {
1389 1.1 mrg gfc_init_se (&se, NULL);
1390 1.1 mrg gfc_conv_expr (&se, ref->u.ar.end[i]);
1391 1.1 mrg gfc_add_block_to_block (block, &se.pre);
1392 1.1 mrg if (ref_static_array)
1393 1.1 mrg {
1394 1.1 mrg /* Make the index zero-based, when reffing a static
1395 1.1 mrg array. */
1396 1.1 mrg end = se.expr;
1397 1.1 mrg gfc_init_se (&se, NULL);
1398 1.1 mrg gfc_conv_expr (&se, ref->u.ar.as->lower[i]);
1399 1.1 mrg gfc_add_block_to_block (block, &se.pre);
1400 1.1 mrg se.expr = fold_build2 (MINUS_EXPR,
1401 1.1 mrg gfc_array_index_type,
1402 1.1 mrg end, fold_convert (
1403 1.1 mrg gfc_array_index_type,
1404 1.1 mrg se.expr));
1405 1.1 mrg }
1406 1.1 mrg end = gfc_evaluate_now (fold_convert (
1407 1.1 mrg gfc_array_index_type,
1408 1.1 mrg se.expr),
1409 1.1 mrg block);
1410 1.1 mrg }
1411 1.1 mrg else if (ref_static_array)
1412 1.1 mrg end = fold_build2 (MINUS_EXPR,
1413 1.1 mrg gfc_array_index_type,
1414 1.1 mrg gfc_conv_array_ubound (
1415 1.1 mrg last_component_ref_tree, i),
1416 1.1 mrg gfc_conv_array_lbound (
1417 1.1 mrg last_component_ref_tree, i));
1418 1.1 mrg else
1419 1.1 mrg {
1420 1.1 mrg end = NULL_TREE;
1421 1.1 mrg mode_rhs = build_int_cst (unsigned_char_type_node,
1422 1.1 mrg GFC_CAF_ARR_REF_OPEN_END);
1423 1.1 mrg }
1424 1.1 mrg if (ref->u.ar.stride[i])
1425 1.1 mrg {
1426 1.1 mrg gfc_init_se (&se, NULL);
1427 1.1 mrg gfc_conv_expr (&se, ref->u.ar.stride[i]);
1428 1.1 mrg gfc_add_block_to_block (block, &se.pre);
1429 1.1 mrg stride = gfc_evaluate_now (fold_convert (
1430 1.1 mrg gfc_array_index_type,
1431 1.1 mrg se.expr),
1432 1.1 mrg block);
1433 1.1 mrg if (ref_static_array)
1434 1.1 mrg {
1435 1.1 mrg /* Make the index zero-based, when reffing a static
1436 1.1 mrg array. */
1437 1.1 mrg stride = fold_build2 (MULT_EXPR,
1438 1.1 mrg gfc_array_index_type,
1439 1.1 mrg gfc_conv_array_stride (
1440 1.1 mrg last_component_ref_tree,
1441 1.1 mrg i),
1442 1.1 mrg stride);
1443 1.1 mrg gcc_assert (end != NULL_TREE);
1444 1.1 mrg /* Multiply with the product of array's stride and
1445 1.1 mrg the step of the ref to a virtual upper bound.
1446 1.1 mrg We cannot compute the actual upper bound here or
1447 1.1 mrg the caflib would compute the extend
1448 1.1 mrg incorrectly. */
1449 1.1 mrg end = fold_build2 (MULT_EXPR, gfc_array_index_type,
1450 1.1 mrg end, gfc_conv_array_stride (
1451 1.1 mrg last_component_ref_tree,
1452 1.1 mrg i));
1453 1.1 mrg end = gfc_evaluate_now (end, block);
1454 1.1 mrg stride = gfc_evaluate_now (stride, block);
1455 1.1 mrg }
1456 1.1 mrg }
1457 1.1 mrg else if (ref_static_array)
1458 1.1 mrg {
1459 1.1 mrg stride = gfc_conv_array_stride (last_component_ref_tree,
1460 1.1 mrg i);
1461 1.1 mrg end = fold_build2 (MULT_EXPR, gfc_array_index_type,
1462 1.1 mrg end, stride);
1463 1.1 mrg end = gfc_evaluate_now (end, block);
1464 1.1 mrg }
1465 1.1 mrg else
1466 1.1 mrg /* Always set a ref stride of one to make caflib's
1467 1.1 mrg handling easier. */
1468 1.1 mrg stride = gfc_index_one_node;
1469 1.1 mrg
1470 1.1 mrg /* Fall through. */
1471 1.1 mrg case DIMEN_ELEMENT:
1472 1.1 mrg if (ref->u.ar.start[i])
1473 1.1 mrg {
1474 1.1 mrg gfc_init_se (&se, NULL);
1475 1.1 mrg gfc_conv_expr (&se, ref->u.ar.start[i]);
1476 1.1 mrg gfc_add_block_to_block (block, &se.pre);
1477 1.1 mrg if (ref_static_array)
1478 1.1 mrg {
1479 1.1 mrg /* Make the index zero-based, when reffing a static
1480 1.1 mrg array. */
1481 1.1 mrg start = fold_convert (gfc_array_index_type, se.expr);
1482 1.1 mrg gfc_init_se (&se, NULL);
1483 1.1 mrg gfc_conv_expr (&se, ref->u.ar.as->lower[i]);
1484 1.1 mrg gfc_add_block_to_block (block, &se.pre);
1485 1.1 mrg se.expr = fold_build2 (MINUS_EXPR,
1486 1.1 mrg gfc_array_index_type,
1487 1.1 mrg start, fold_convert (
1488 1.1 mrg gfc_array_index_type,
1489 1.1 mrg se.expr));
1490 1.1 mrg /* Multiply with the stride. */
1491 1.1 mrg se.expr = fold_build2 (MULT_EXPR,
1492 1.1 mrg gfc_array_index_type,
1493 1.1 mrg se.expr,
1494 1.1 mrg gfc_conv_array_stride (
1495 1.1 mrg last_component_ref_tree,
1496 1.1 mrg i));
1497 1.1 mrg }
1498 1.1 mrg start = gfc_evaluate_now (fold_convert (
1499 1.1 mrg gfc_array_index_type,
1500 1.1 mrg se.expr),
1501 1.1 mrg block);
1502 1.1 mrg if (mode_rhs == NULL_TREE)
1503 1.1 mrg mode_rhs = build_int_cst (unsigned_char_type_node,
1504 1.1 mrg ref->u.ar.dimen_type[i]
1505 1.1 mrg == DIMEN_ELEMENT
1506 1.1 mrg ? GFC_CAF_ARR_REF_SINGLE
1507 1.1 mrg : GFC_CAF_ARR_REF_RANGE);
1508 1.1 mrg }
1509 1.1 mrg else if (ref_static_array)
1510 1.1 mrg {
1511 1.1 mrg start = integer_zero_node;
1512 1.1 mrg mode_rhs = build_int_cst (unsigned_char_type_node,
1513 1.1 mrg ref->u.ar.start[i] == NULL
1514 1.1 mrg ? GFC_CAF_ARR_REF_FULL
1515 1.1 mrg : GFC_CAF_ARR_REF_RANGE);
1516 1.1 mrg }
1517 1.1 mrg else if (end == NULL_TREE)
1518 1.1 mrg mode_rhs = build_int_cst (unsigned_char_type_node,
1519 1.1 mrg GFC_CAF_ARR_REF_FULL);
1520 1.1 mrg else
1521 1.1 mrg mode_rhs = build_int_cst (unsigned_char_type_node,
1522 1.1 mrg GFC_CAF_ARR_REF_OPEN_START);
1523 1.1 mrg
1524 1.1 mrg /* Ref the s in dim. */
1525 1.1 mrg field = gfc_advance_chain (TYPE_FIELDS (dim_type), 0);
1526 1.1 mrg tmp = fold_build3_loc (input_location, COMPONENT_REF,
1527 1.1 mrg TREE_TYPE (field), dim, field,
1528 1.1 mrg NULL_TREE);
1529 1.1 mrg
1530 1.1 mrg /* Set start in s. */
1531 1.1 mrg if (start != NULL_TREE)
1532 1.1 mrg {
1533 1.1 mrg field = gfc_advance_chain (TYPE_FIELDS (TREE_TYPE (tmp)),
1534 1.1 mrg 0);
1535 1.1 mrg tmp2 = fold_build3_loc (input_location, COMPONENT_REF,
1536 1.1 mrg TREE_TYPE (field), tmp, field,
1537 1.1 mrg NULL_TREE);
1538 1.1 mrg gfc_add_modify (block, tmp2,
1539 1.1 mrg fold_convert (TREE_TYPE (tmp2), start));
1540 1.1 mrg }
1541 1.1 mrg
1542 1.1 mrg /* Set end in s. */
1543 1.1 mrg if (end != NULL_TREE)
1544 1.1 mrg {
1545 1.1 mrg field = gfc_advance_chain (TYPE_FIELDS (TREE_TYPE (tmp)),
1546 1.1 mrg 1);
1547 1.1 mrg tmp2 = fold_build3_loc (input_location, COMPONENT_REF,
1548 1.1 mrg TREE_TYPE (field), tmp, field,
1549 1.1 mrg NULL_TREE);
1550 1.1 mrg gfc_add_modify (block, tmp2,
1551 1.1 mrg fold_convert (TREE_TYPE (tmp2), end));
1552 1.1 mrg }
1553 1.1 mrg
1554 1.1 mrg /* Set end in s. */
1555 1.1 mrg if (stride != NULL_TREE)
1556 1.1 mrg {
1557 1.1 mrg field = gfc_advance_chain (TYPE_FIELDS (TREE_TYPE (tmp)),
1558 1.1 mrg 2);
1559 1.1 mrg tmp2 = fold_build3_loc (input_location, COMPONENT_REF,
1560 1.1 mrg TREE_TYPE (field), tmp, field,
1561 1.1 mrg NULL_TREE);
1562 1.1 mrg gfc_add_modify (block, tmp2,
1563 1.1 mrg fold_convert (TREE_TYPE (tmp2), stride));
1564 1.1 mrg }
1565 1.1 mrg break;
1566 1.1 mrg case DIMEN_VECTOR:
1567 1.1 mrg /* TODO: In case of static array. */
1568 1.1 mrg gcc_assert (!ref_static_array);
1569 1.1 mrg mode_rhs = build_int_cst (unsigned_char_type_node,
1570 1.1 mrg GFC_CAF_ARR_REF_VECTOR);
1571 1.1 mrg gfc_init_se (&se, NULL);
1572 1.1 mrg se.descriptor_only = 1;
1573 1.1 mrg gfc_conv_expr_descriptor (&se, ref->u.ar.start[i]);
1574 1.1 mrg gfc_add_block_to_block (block, &se.pre);
1575 1.1 mrg vector = se.expr;
1576 1.1 mrg tmp = gfc_conv_descriptor_lbound_get (vector,
1577 1.1 mrg gfc_rank_cst[0]);
1578 1.1 mrg tmp2 = gfc_conv_descriptor_ubound_get (vector,
1579 1.1 mrg gfc_rank_cst[0]);
1580 1.1 mrg nvec = gfc_conv_array_extent_dim (tmp, tmp2, NULL);
1581 1.1 mrg tmp = gfc_conv_descriptor_stride_get (vector,
1582 1.1 mrg gfc_rank_cst[0]);
1583 1.1 mrg nvec = fold_build2_loc (input_location, TRUNC_DIV_EXPR,
1584 1.1 mrg TREE_TYPE (nvec), nvec, tmp);
1585 1.1 mrg vector = gfc_conv_descriptor_data_get (vector);
1586 1.1 mrg
1587 1.1 mrg /* Ref the v in dim. */
1588 1.1 mrg field = gfc_advance_chain (TYPE_FIELDS (dim_type), 1);
1589 1.1 mrg tmp = fold_build3_loc (input_location, COMPONENT_REF,
1590 1.1 mrg TREE_TYPE (field), dim, field,
1591 1.1 mrg NULL_TREE);
1592 1.1 mrg
1593 1.1 mrg /* Set vector in v. */
1594 1.1 mrg field = gfc_advance_chain (TYPE_FIELDS (TREE_TYPE (tmp)), 0);
1595 1.1 mrg tmp2 = fold_build3_loc (input_location, COMPONENT_REF,
1596 1.1 mrg TREE_TYPE (field), tmp, field,
1597 1.1 mrg NULL_TREE);
1598 1.1 mrg gfc_add_modify (block, tmp2, fold_convert (TREE_TYPE (tmp2),
1599 1.1 mrg vector));
1600 1.1 mrg
1601 1.1 mrg /* Set nvec in v. */
1602 1.1 mrg field = gfc_advance_chain (TYPE_FIELDS (TREE_TYPE (tmp)), 1);
1603 1.1 mrg tmp2 = fold_build3_loc (input_location, COMPONENT_REF,
1604 1.1 mrg TREE_TYPE (field), tmp, field,
1605 1.1 mrg NULL_TREE);
1606 1.1 mrg gfc_add_modify (block, tmp2, fold_convert (TREE_TYPE (tmp2),
1607 1.1 mrg nvec));
1608 1.1 mrg
1609 1.1 mrg /* Set kind in v. */
1610 1.1 mrg field = gfc_advance_chain (TYPE_FIELDS (TREE_TYPE (tmp)), 2);
1611 1.1 mrg tmp2 = fold_build3_loc (input_location, COMPONENT_REF,
1612 1.1 mrg TREE_TYPE (field), tmp, field,
1613 1.1 mrg NULL_TREE);
1614 1.1 mrg gfc_add_modify (block, tmp2, build_int_cst (integer_type_node,
1615 1.1 mrg ref->u.ar.start[i]->ts.kind));
1616 1.1 mrg break;
1617 1.1 mrg default:
1618 1.1 mrg gcc_unreachable ();
1619 1.1 mrg }
1620 1.1 mrg /* Set the mode for dim i. */
1621 1.1 mrg tmp = gfc_build_array_ref (mode, gfc_rank_cst[i], NULL_TREE);
1622 1.1 mrg gfc_add_modify (block, tmp, fold_convert (TREE_TYPE (tmp),
1623 1.1 mrg mode_rhs));
1624 1.1 mrg }
1625 1.1 mrg
1626 1.1 mrg /* Set the mode for dim i+1 to GFC_ARR_REF_NONE. */
1627 1.1 mrg if (i < GFC_MAX_DIMENSIONS)
1628 1.1 mrg {
1629 1.1 mrg tmp = gfc_build_array_ref (mode, gfc_rank_cst[i], NULL_TREE);
1630 1.1 mrg gfc_add_modify (block, tmp,
1631 1.1 mrg build_int_cst (unsigned_char_type_node,
1632 1.1 mrg GFC_CAF_ARR_REF_NONE));
1633 1.1 mrg }
1634 1.1 mrg break;
1635 1.1 mrg default:
1636 1.1 mrg gcc_unreachable ();
1637 1.1 mrg }
1638 1.1 mrg
1639 1.1 mrg /* Set the size of the current type. */
1640 1.1 mrg field = gfc_advance_chain (TYPE_FIELDS (reference_type), 2);
1641 1.1 mrg tmp = fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (field),
1642 1.1 mrg prev_caf_ref, field, NULL_TREE);
1643 1.1 mrg gfc_add_modify (block, tmp, fold_convert (TREE_TYPE (field),
1644 1.1 mrg TYPE_SIZE_UNIT (last_type)));
1645 1.1 mrg
1646 1.1 mrg ref = ref->next;
1647 1.1 mrg }
1648 1.1 mrg
1649 1.1 mrg if (prev_caf_ref != NULL_TREE)
1650 1.1 mrg {
1651 1.1 mrg field = gfc_advance_chain (TYPE_FIELDS (reference_type), 0);
1652 1.1 mrg tmp = fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (field),
1653 1.1 mrg prev_caf_ref, field, NULL_TREE);
1654 1.1 mrg gfc_add_modify (block, tmp, fold_convert (TREE_TYPE (field),
1655 1.1 mrg null_pointer_node));
1656 1.1 mrg }
1657 1.1 mrg return caf_ref != NULL_TREE ? gfc_build_addr_expr (NULL_TREE, caf_ref)
1658 1.1 mrg : NULL_TREE;
1659 1.1 mrg }
1660 1.1 mrg
1661 1.1 mrg /* Get data from a remote coarray. */
1662 1.1 mrg
1663 1.1 mrg static void
1664 1.1 mrg gfc_conv_intrinsic_caf_get (gfc_se *se, gfc_expr *expr, tree lhs, tree lhs_kind,
1665 1.1 mrg tree may_require_tmp, bool may_realloc,
1666 1.1 mrg symbol_attribute *caf_attr)
1667 1.1 mrg {
1668 1.1 mrg gfc_expr *array_expr, *tmp_stat;
1669 1.1 mrg gfc_se argse;
1670 1.1 mrg tree caf_decl, token, offset, image_index, tmp;
1671 1.1 mrg tree res_var, dst_var, type, kind, vec, stat;
1672 1.1 mrg tree caf_reference;
1673 1.1 mrg symbol_attribute caf_attr_store;
1674 1.1 mrg
1675 1.1 mrg gcc_assert (flag_coarray == GFC_FCOARRAY_LIB);
1676 1.1 mrg
1677 1.1 mrg if (se->ss && se->ss->info->useflags)
1678 1.1 mrg {
1679 1.1 mrg /* Access the previously obtained result. */
1680 1.1 mrg gfc_conv_tmp_array_ref (se);
1681 1.1 mrg return;
1682 1.1 mrg }
1683 1.1 mrg
1684 1.1 mrg /* If lhs is set, the CAF_GET intrinsic has already been stripped. */
1685 1.1 mrg array_expr = (lhs == NULL_TREE) ? expr->value.function.actual->expr : expr;
1686 1.1 mrg type = gfc_typenode_for_spec (&array_expr->ts);
1687 1.1 mrg
1688 1.1 mrg if (caf_attr == NULL)
1689 1.1 mrg {
1690 1.1 mrg caf_attr_store = gfc_caf_attr (array_expr);
1691 1.1 mrg caf_attr = &caf_attr_store;
1692 1.1 mrg }
1693 1.1 mrg
1694 1.1 mrg res_var = lhs;
1695 1.1 mrg dst_var = lhs;
1696 1.1 mrg
1697 1.1 mrg vec = null_pointer_node;
1698 1.1 mrg tmp_stat = gfc_find_stat_co (expr);
1699 1.1 mrg
1700 1.1 mrg if (tmp_stat)
1701 1.1 mrg {
1702 1.1 mrg gfc_se stat_se;
1703 1.1 mrg gfc_init_se (&stat_se, NULL);
1704 1.1 mrg gfc_conv_expr_reference (&stat_se, tmp_stat);
1705 1.1 mrg stat = stat_se.expr;
1706 1.1 mrg gfc_add_block_to_block (&se->pre, &stat_se.pre);
1707 1.1 mrg gfc_add_block_to_block (&se->post, &stat_se.post);
1708 1.1 mrg }
1709 1.1 mrg else
1710 1.1 mrg stat = null_pointer_node;
1711 1.1 mrg
1712 1.1 mrg /* Only use the new get_by_ref () where it is necessary. I.e., when the lhs
1713 1.1 mrg is reallocatable or the right-hand side has allocatable components. */
1714 1.1 mrg if (caf_attr->alloc_comp || caf_attr->pointer_comp || may_realloc)
1715 1.1 mrg {
1716 1.1 mrg /* Get using caf_get_by_ref. */
1717 1.1 mrg caf_reference = conv_expr_ref_to_caf_ref (&se->pre, array_expr);
1718 1.1 mrg
1719 1.1 mrg if (caf_reference != NULL_TREE)
1720 1.1 mrg {
1721 1.1 mrg if (lhs == NULL_TREE)
1722 1.1 mrg {
1723 1.1 mrg if (array_expr->ts.type == BT_CHARACTER)
1724 1.1 mrg gfc_init_se (&argse, NULL);
1725 1.1 mrg if (array_expr->rank == 0)
1726 1.1 mrg {
1727 1.1 mrg symbol_attribute attr;
1728 1.1 mrg gfc_clear_attr (&attr);
1729 1.1 mrg if (array_expr->ts.type == BT_CHARACTER)
1730 1.1 mrg {
1731 1.1 mrg res_var = gfc_conv_string_tmp (se,
1732 1.1 mrg build_pointer_type (type),
1733 1.1 mrg array_expr->ts.u.cl->backend_decl);
1734 1.1 mrg argse.string_length = array_expr->ts.u.cl->backend_decl;
1735 1.1 mrg }
1736 1.1 mrg else
1737 1.1 mrg res_var = gfc_create_var (type, "caf_res");
1738 1.1 mrg dst_var = gfc_conv_scalar_to_descriptor (se, res_var, attr);
1739 1.1 mrg dst_var = gfc_build_addr_expr (NULL_TREE, dst_var);
1740 1.1 mrg }
1741 1.1 mrg else
1742 1.1 mrg {
1743 1.1 mrg /* Create temporary. */
1744 1.1 mrg if (array_expr->ts.type == BT_CHARACTER)
1745 1.1 mrg gfc_conv_expr_descriptor (&argse, array_expr);
1746 1.1 mrg may_realloc = gfc_trans_create_temp_array (&se->pre,
1747 1.1 mrg &se->post,
1748 1.1 mrg se->ss, type,
1749 1.1 mrg NULL_TREE, false,
1750 1.1 mrg false, false,
1751 1.1 mrg &array_expr->where)
1752 1.1 mrg == NULL_TREE;
1753 1.1 mrg res_var = se->ss->info->data.array.descriptor;
1754 1.1 mrg dst_var = gfc_build_addr_expr (NULL_TREE, res_var);
1755 1.1 mrg if (may_realloc)
1756 1.1 mrg {
1757 1.1 mrg tmp = gfc_conv_descriptor_data_get (res_var);
1758 1.1 mrg tmp = gfc_deallocate_with_status (tmp, NULL_TREE,
1759 1.1 mrg NULL_TREE, NULL_TREE,
1760 1.1 mrg NULL_TREE, true,
1761 1.1 mrg NULL,
1762 1.1 mrg GFC_CAF_COARRAY_NOCOARRAY);
1763 1.1 mrg gfc_add_expr_to_block (&se->post, tmp);
1764 1.1 mrg }
1765 1.1 mrg }
1766 1.1 mrg }
1767 1.1 mrg
1768 1.1 mrg kind = build_int_cst (integer_type_node, expr->ts.kind);
1769 1.1 mrg if (lhs_kind == NULL_TREE)
1770 1.1 mrg lhs_kind = kind;
1771 1.1 mrg
1772 1.1 mrg caf_decl = gfc_get_tree_for_caf_expr (array_expr);
1773 1.1 mrg if (TREE_CODE (TREE_TYPE (caf_decl)) == REFERENCE_TYPE)
1774 1.1 mrg caf_decl = build_fold_indirect_ref_loc (input_location, caf_decl);
1775 1.1 mrg image_index = gfc_caf_get_image_index (&se->pre, array_expr,
1776 1.1 mrg caf_decl);
1777 1.1 mrg gfc_get_caf_token_offset (se, &token, NULL, caf_decl, NULL,
1778 1.1 mrg array_expr);
1779 1.1 mrg
1780 1.1 mrg /* No overlap possible as we have generated a temporary. */
1781 1.1 mrg if (lhs == NULL_TREE)
1782 1.1 mrg may_require_tmp = boolean_false_node;
1783 1.1 mrg
1784 1.1 mrg /* It guarantees memory consistency within the same segment. */
1785 1.1 mrg tmp = gfc_build_string_const (strlen ("memory") + 1, "memory");
1786 1.1 mrg tmp = build5_loc (input_location, ASM_EXPR, void_type_node,
1787 1.1 mrg gfc_build_string_const (1, ""), NULL_TREE,
1788 1.1 mrg NULL_TREE, tree_cons (NULL_TREE, tmp, NULL_TREE),
1789 1.1 mrg NULL_TREE);
1790 1.1 mrg ASM_VOLATILE_P (tmp) = 1;
1791 1.1 mrg gfc_add_expr_to_block (&se->pre, tmp);
1792 1.1 mrg
1793 1.1 mrg tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_get_by_ref,
1794 1.1 mrg 10, token, image_index, dst_var,
1795 1.1 mrg caf_reference, lhs_kind, kind,
1796 1.1 mrg may_require_tmp,
1797 1.1 mrg may_realloc ? boolean_true_node :
1798 1.1 mrg boolean_false_node,
1799 1.1 mrg stat, build_int_cst (integer_type_node,
1800 1.1 mrg array_expr->ts.type));
1801 1.1 mrg
1802 1.1 mrg gfc_add_expr_to_block (&se->pre, tmp);
1803 1.1 mrg
1804 1.1 mrg if (se->ss)
1805 1.1 mrg gfc_advance_se_ss_chain (se);
1806 1.1 mrg
1807 1.1 mrg se->expr = res_var;
1808 1.1 mrg if (array_expr->ts.type == BT_CHARACTER)
1809 1.1 mrg se->string_length = argse.string_length;
1810 1.1 mrg
1811 1.1 mrg return;
1812 1.1 mrg }
1813 1.1 mrg }
1814 1.1 mrg
1815 1.1 mrg gfc_init_se (&argse, NULL);
1816 1.1 mrg if (array_expr->rank == 0)
1817 1.1 mrg {
1818 1.1 mrg symbol_attribute attr;
1819 1.1 mrg
1820 1.1 mrg gfc_clear_attr (&attr);
1821 1.1 mrg gfc_conv_expr (&argse, array_expr);
1822 1.1 mrg
1823 1.1 mrg if (lhs == NULL_TREE)
1824 1.1 mrg {
1825 1.1 mrg gfc_clear_attr (&attr);
1826 1.1 mrg if (array_expr->ts.type == BT_CHARACTER)
1827 1.1 mrg res_var = gfc_conv_string_tmp (se, build_pointer_type (type),
1828 1.1 mrg argse.string_length);
1829 1.1 mrg else
1830 1.1 mrg res_var = gfc_create_var (type, "caf_res");
1831 1.1 mrg dst_var = gfc_conv_scalar_to_descriptor (&argse, res_var, attr);
1832 1.1 mrg dst_var = gfc_build_addr_expr (NULL_TREE, dst_var);
1833 1.1 mrg }
1834 1.1 mrg argse.expr = gfc_conv_scalar_to_descriptor (&argse, argse.expr, attr);
1835 1.1 mrg argse.expr = gfc_build_addr_expr (NULL_TREE, argse.expr);
1836 1.1 mrg }
1837 1.1 mrg else
1838 1.1 mrg {
1839 1.1 mrg /* If has_vector, pass descriptor for whole array and the
1840 1.1 mrg vector bounds separately. */
1841 1.1 mrg gfc_array_ref *ar, ar2;
1842 1.1 mrg bool has_vector = false;
1843 1.1 mrg
1844 1.1 mrg if (gfc_is_coindexed (expr) && gfc_has_vector_subscript (expr))
1845 1.1 mrg {
1846 1.1 mrg has_vector = true;
1847 1.1 mrg ar = gfc_find_array_ref (expr);
1848 1.1 mrg ar2 = *ar;
1849 1.1 mrg memset (ar, '\0', sizeof (*ar));
1850 1.1 mrg ar->as = ar2.as;
1851 1.1 mrg ar->type = AR_FULL;
1852 1.1 mrg }
1853 1.1 mrg // TODO: Check whether argse.want_coarray = 1 can help with the below.
1854 1.1 mrg gfc_conv_expr_descriptor (&argse, array_expr);
1855 1.1 mrg /* Using gfc_conv_expr_descriptor, we only get the descriptor, but that
1856 1.1 mrg has the wrong type if component references are done. */
1857 1.1 mrg gfc_add_modify (&argse.pre, gfc_conv_descriptor_dtype (argse.expr),
1858 1.1 mrg gfc_get_dtype_rank_type (has_vector ? ar2.dimen
1859 1.1 mrg : array_expr->rank,
1860 1.1 mrg type));
1861 1.1 mrg if (has_vector)
1862 1.1 mrg {
1863 1.1 mrg vec = conv_caf_vector_subscript (&argse.pre, argse.expr, &ar2);
1864 1.1 mrg *ar = ar2;
1865 1.1 mrg }
1866 1.1 mrg
1867 1.1 mrg if (lhs == NULL_TREE)
1868 1.1 mrg {
1869 1.1 mrg /* Create temporary. */
1870 1.1 mrg for (int n = 0; n < se->ss->loop->dimen; n++)
1871 1.1 mrg if (se->loop->to[n] == NULL_TREE)
1872 1.1 mrg {
1873 1.1 mrg se->loop->from[n] = gfc_conv_descriptor_lbound_get (argse.expr,
1874 1.1 mrg gfc_rank_cst[n]);
1875 1.1 mrg se->loop->to[n] = gfc_conv_descriptor_ubound_get (argse.expr,
1876 1.1 mrg gfc_rank_cst[n]);
1877 1.1 mrg }
1878 1.1 mrg gfc_trans_create_temp_array (&argse.pre, &argse.post, se->ss, type,
1879 1.1 mrg NULL_TREE, false, true, false,
1880 1.1 mrg &array_expr->where);
1881 1.1 mrg res_var = se->ss->info->data.array.descriptor;
1882 1.1 mrg dst_var = gfc_build_addr_expr (NULL_TREE, res_var);
1883 1.1 mrg }
1884 1.1 mrg argse.expr = gfc_build_addr_expr (NULL_TREE, argse.expr);
1885 1.1 mrg }
1886 1.1 mrg
1887 1.1 mrg kind = build_int_cst (integer_type_node, expr->ts.kind);
1888 1.1 mrg if (lhs_kind == NULL_TREE)
1889 1.1 mrg lhs_kind = kind;
1890 1.1 mrg
1891 1.1 mrg gfc_add_block_to_block (&se->pre, &argse.pre);
1892 1.1 mrg gfc_add_block_to_block (&se->post, &argse.post);
1893 1.1 mrg
1894 1.1 mrg caf_decl = gfc_get_tree_for_caf_expr (array_expr);
1895 1.1 mrg if (TREE_CODE (TREE_TYPE (caf_decl)) == REFERENCE_TYPE)
1896 1.1 mrg caf_decl = build_fold_indirect_ref_loc (input_location, caf_decl);
1897 1.1 mrg image_index = gfc_caf_get_image_index (&se->pre, array_expr, caf_decl);
1898 1.1 mrg gfc_get_caf_token_offset (se, &token, &offset, caf_decl, argse.expr,
1899 1.1 mrg array_expr);
1900 1.1 mrg
1901 1.1 mrg /* No overlap possible as we have generated a temporary. */
1902 1.1 mrg if (lhs == NULL_TREE)
1903 1.1 mrg may_require_tmp = boolean_false_node;
1904 1.1 mrg
1905 1.1 mrg /* It guarantees memory consistency within the same segment. */
1906 1.1 mrg tmp = gfc_build_string_const (strlen ("memory") + 1, "memory");
1907 1.1 mrg tmp = build5_loc (input_location, ASM_EXPR, void_type_node,
1908 1.1 mrg gfc_build_string_const (1, ""), NULL_TREE, NULL_TREE,
1909 1.1 mrg tree_cons (NULL_TREE, tmp, NULL_TREE), NULL_TREE);
1910 1.1 mrg ASM_VOLATILE_P (tmp) = 1;
1911 1.1 mrg gfc_add_expr_to_block (&se->pre, tmp);
1912 1.1 mrg
1913 1.1 mrg tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_get, 10,
1914 1.1 mrg token, offset, image_index, argse.expr, vec,
1915 1.1 mrg dst_var, kind, lhs_kind, may_require_tmp, stat);
1916 1.1 mrg
1917 1.1 mrg gfc_add_expr_to_block (&se->pre, tmp);
1918 1.1 mrg
1919 1.1 mrg if (se->ss)
1920 1.1 mrg gfc_advance_se_ss_chain (se);
1921 1.1 mrg
1922 1.1 mrg se->expr = res_var;
1923 1.1 mrg if (array_expr->ts.type == BT_CHARACTER)
1924 1.1 mrg se->string_length = argse.string_length;
1925 1.1 mrg }
1926 1.1 mrg
1927 1.1 mrg
1928 1.1 mrg /* Send data to a remote coarray. */
1929 1.1 mrg
1930 1.1 mrg static tree
1931 1.1 mrg conv_caf_send (gfc_code *code) {
1932 1.1 mrg gfc_expr *lhs_expr, *rhs_expr, *tmp_stat, *tmp_team;
1933 1.1 mrg gfc_se lhs_se, rhs_se;
1934 1.1 mrg stmtblock_t block;
1935 1.1 mrg tree caf_decl, token, offset, image_index, tmp, lhs_kind, rhs_kind;
1936 1.1 mrg tree may_require_tmp, src_stat, dst_stat, dst_team;
1937 1.1 mrg tree lhs_type = NULL_TREE;
1938 1.1 mrg tree vec = null_pointer_node, rhs_vec = null_pointer_node;
1939 1.1 mrg symbol_attribute lhs_caf_attr, rhs_caf_attr;
1940 1.1 mrg
1941 1.1 mrg gcc_assert (flag_coarray == GFC_FCOARRAY_LIB);
1942 1.1 mrg
1943 1.1 mrg lhs_expr = code->ext.actual->expr;
1944 1.1 mrg rhs_expr = code->ext.actual->next->expr;
1945 1.1 mrg may_require_tmp = gfc_check_dependency (lhs_expr, rhs_expr, true) == 0
1946 1.1 mrg ? boolean_false_node : boolean_true_node;
1947 1.1 mrg gfc_init_block (&block);
1948 1.1 mrg
1949 1.1 mrg lhs_caf_attr = gfc_caf_attr (lhs_expr);
1950 1.1 mrg rhs_caf_attr = gfc_caf_attr (rhs_expr);
1951 1.1 mrg src_stat = dst_stat = null_pointer_node;
1952 1.1 mrg dst_team = null_pointer_node;
1953 1.1 mrg
1954 1.1 mrg /* LHS. */
1955 1.1 mrg gfc_init_se (&lhs_se, NULL);
1956 1.1 mrg if (lhs_expr->rank == 0)
1957 1.1 mrg {
1958 1.1 mrg if (lhs_expr->ts.type == BT_CHARACTER && lhs_expr->ts.deferred)
1959 1.1 mrg {
1960 1.1 mrg lhs_se.expr = gfc_get_tree_for_caf_expr (lhs_expr);
1961 1.1 mrg lhs_se.expr = gfc_build_addr_expr (NULL_TREE, lhs_se.expr);
1962 1.1 mrg }
1963 1.1 mrg else
1964 1.1 mrg {
1965 1.1 mrg symbol_attribute attr;
1966 1.1 mrg gfc_clear_attr (&attr);
1967 1.1 mrg gfc_conv_expr (&lhs_se, lhs_expr);
1968 1.1 mrg lhs_type = TREE_TYPE (lhs_se.expr);
1969 1.1 mrg lhs_se.expr = gfc_conv_scalar_to_descriptor (&lhs_se, lhs_se.expr,
1970 1.1 mrg attr);
1971 1.1 mrg lhs_se.expr = gfc_build_addr_expr (NULL_TREE, lhs_se.expr);
1972 1.1 mrg }
1973 1.1 mrg }
1974 1.1 mrg else if ((lhs_caf_attr.alloc_comp || lhs_caf_attr.pointer_comp)
1975 1.1 mrg && lhs_caf_attr.codimension)
1976 1.1 mrg {
1977 1.1 mrg lhs_se.want_pointer = 1;
1978 1.1 mrg gfc_conv_expr_descriptor (&lhs_se, lhs_expr);
1979 1.1 mrg /* Using gfc_conv_expr_descriptor, we only get the descriptor, but that
1980 1.1 mrg has the wrong type if component references are done. */
1981 1.1 mrg lhs_type = gfc_typenode_for_spec (&lhs_expr->ts);
1982 1.1 mrg tmp = build_fold_indirect_ref_loc (input_location, lhs_se.expr);
1983 1.1 mrg gfc_add_modify (&lhs_se.pre, gfc_conv_descriptor_dtype (tmp),
1984 1.1 mrg gfc_get_dtype_rank_type (
1985 1.1 mrg gfc_has_vector_subscript (lhs_expr)
1986 1.1 mrg ? gfc_find_array_ref (lhs_expr)->dimen
1987 1.1 mrg : lhs_expr->rank,
1988 1.1 mrg lhs_type));
1989 1.1 mrg }
1990 1.1 mrg else
1991 1.1 mrg {
1992 1.1 mrg bool has_vector = gfc_has_vector_subscript (lhs_expr);
1993 1.1 mrg
1994 1.1 mrg if (gfc_is_coindexed (lhs_expr) || !has_vector)
1995 1.1 mrg {
1996 1.1 mrg /* If has_vector, pass descriptor for whole array and the
1997 1.1 mrg vector bounds separately. */
1998 1.1 mrg gfc_array_ref *ar, ar2;
1999 1.1 mrg bool has_tmp_lhs_array = false;
2000 1.1 mrg if (has_vector)
2001 1.1 mrg {
2002 1.1 mrg has_tmp_lhs_array = true;
2003 1.1 mrg ar = gfc_find_array_ref (lhs_expr);
2004 1.1 mrg ar2 = *ar;
2005 1.1 mrg memset (ar, '\0', sizeof (*ar));
2006 1.1 mrg ar->as = ar2.as;
2007 1.1 mrg ar->type = AR_FULL;
2008 1.1 mrg }
2009 1.1 mrg lhs_se.want_pointer = 1;
2010 1.1 mrg gfc_conv_expr_descriptor (&lhs_se, lhs_expr);
2011 1.1 mrg /* Using gfc_conv_expr_descriptor, we only get the descriptor, but
2012 1.1 mrg that has the wrong type if component references are done. */
2013 1.1 mrg lhs_type = gfc_typenode_for_spec (&lhs_expr->ts);
2014 1.1 mrg tmp = build_fold_indirect_ref_loc (input_location, lhs_se.expr);
2015 1.1 mrg gfc_add_modify (&lhs_se.pre, gfc_conv_descriptor_dtype (tmp),
2016 1.1 mrg gfc_get_dtype_rank_type (has_vector ? ar2.dimen
2017 1.1 mrg : lhs_expr->rank,
2018 1.1 mrg lhs_type));
2019 1.1 mrg if (has_tmp_lhs_array)
2020 1.1 mrg {
2021 1.1 mrg vec = conv_caf_vector_subscript (&block, lhs_se.expr, &ar2);
2022 1.1 mrg *ar = ar2;
2023 1.1 mrg }
2024 1.1 mrg }
2025 1.1 mrg else
2026 1.1 mrg {
2027 1.1 mrg /* Special casing for arr1 ([...]) = arr2[...], i.e. caf_get to
2028 1.1 mrg indexed array expression. This is rewritten to:
2029 1.1 mrg
2030 1.1 mrg tmp_array = arr2[...]
2031 1.1 mrg arr1 ([...]) = tmp_array
2032 1.1 mrg
2033 1.1 mrg because using the standard gfc_conv_expr (lhs_expr) did the
2034 1.1 mrg assignment with lhs and rhs exchanged. */
2035 1.1 mrg
2036 1.1 mrg gfc_ss *lss_for_tmparray, *lss_real;
2037 1.1 mrg gfc_loopinfo loop;
2038 1.1 mrg gfc_se se;
2039 1.1 mrg stmtblock_t body;
2040 1.1 mrg tree tmparr_desc, src;
2041 1.1 mrg tree index = gfc_index_zero_node;
2042 1.1 mrg tree stride = gfc_index_zero_node;
2043 1.1 mrg int n;
2044 1.1 mrg
2045 1.1 mrg /* Walk both sides of the assignment, once to get the shape of the
2046 1.1 mrg temporary array to create right. */
2047 1.1 mrg lss_for_tmparray = gfc_walk_expr (lhs_expr);
2048 1.1 mrg /* And a second time to be able to create an assignment of the
2049 1.1 mrg temporary to the lhs_expr. gfc_trans_create_temp_array replaces
2050 1.1 mrg the tree in the descriptor with the one for the temporary
2051 1.1 mrg array. */
2052 1.1 mrg lss_real = gfc_walk_expr (lhs_expr);
2053 1.1 mrg gfc_init_loopinfo (&loop);
2054 1.1 mrg gfc_add_ss_to_loop (&loop, lss_for_tmparray);
2055 1.1 mrg gfc_add_ss_to_loop (&loop, lss_real);
2056 1.1 mrg gfc_conv_ss_startstride (&loop);
2057 1.1 mrg gfc_conv_loop_setup (&loop, &lhs_expr->where);
2058 1.1 mrg lhs_type = gfc_typenode_for_spec (&lhs_expr->ts);
2059 1.1 mrg gfc_trans_create_temp_array (&lhs_se.pre, &lhs_se.post,
2060 1.1 mrg lss_for_tmparray, lhs_type, NULL_TREE,
2061 1.1 mrg false, true, false,
2062 1.1 mrg &lhs_expr->where);
2063 1.1 mrg tmparr_desc = lss_for_tmparray->info->data.array.descriptor;
2064 1.1 mrg gfc_start_scalarized_body (&loop, &body);
2065 1.1 mrg gfc_init_se (&se, NULL);
2066 1.1 mrg gfc_copy_loopinfo_to_se (&se, &loop);
2067 1.1 mrg se.ss = lss_real;
2068 1.1 mrg gfc_conv_expr (&se, lhs_expr);
2069 1.1 mrg gfc_add_block_to_block (&body, &se.pre);
2070 1.1 mrg
2071 1.1 mrg /* Walk over all indexes of the loop. */
2072 1.1 mrg for (n = loop.dimen - 1; n > 0; --n)
2073 1.1 mrg {
2074 1.1 mrg tmp = loop.loopvar[n];
2075 1.1 mrg tmp = fold_build2_loc (input_location, MINUS_EXPR,
2076 1.1 mrg gfc_array_index_type, tmp, loop.from[n]);
2077 1.1 mrg tmp = fold_build2_loc (input_location, PLUS_EXPR,
2078 1.1 mrg gfc_array_index_type, tmp, index);
2079 1.1 mrg
2080 1.1 mrg stride = fold_build2_loc (input_location, MINUS_EXPR,
2081 1.1 mrg gfc_array_index_type,
2082 1.1 mrg loop.to[n - 1], loop.from[n - 1]);
2083 1.1 mrg stride = fold_build2_loc (input_location, PLUS_EXPR,
2084 1.1 mrg gfc_array_index_type,
2085 1.1 mrg stride, gfc_index_one_node);
2086 1.1 mrg
2087 1.1 mrg index = fold_build2_loc (input_location, MULT_EXPR,
2088 1.1 mrg gfc_array_index_type, tmp, stride);
2089 1.1 mrg }
2090 1.1 mrg
2091 1.1 mrg index = fold_build2_loc (input_location, MINUS_EXPR,
2092 1.1 mrg gfc_array_index_type,
2093 1.1 mrg index, loop.from[0]);
2094 1.1 mrg
2095 1.1 mrg index = fold_build2_loc (input_location, PLUS_EXPR,
2096 1.1 mrg gfc_array_index_type,
2097 1.1 mrg loop.loopvar[0], index);
2098 1.1 mrg
2099 1.1 mrg src = build_fold_indirect_ref (gfc_conv_array_data (tmparr_desc));
2100 1.1 mrg src = gfc_build_array_ref (src, index, NULL);
2101 1.1 mrg /* Now create the assignment of lhs_expr = tmp_array. */
2102 1.1 mrg gfc_add_modify (&body, se.expr, src);
2103 1.1 mrg gfc_add_block_to_block (&body, &se.post);
2104 1.1 mrg lhs_se.expr = gfc_build_addr_expr (NULL_TREE, tmparr_desc);
2105 1.1 mrg gfc_trans_scalarizing_loops (&loop, &body);
2106 1.1 mrg gfc_add_block_to_block (&loop.pre, &loop.post);
2107 1.1 mrg gfc_add_expr_to_block (&lhs_se.post, gfc_finish_block (&loop.pre));
2108 1.1 mrg gfc_free_ss (lss_for_tmparray);
2109 1.1 mrg gfc_free_ss (lss_real);
2110 1.1 mrg }
2111 1.1 mrg }
2112 1.1 mrg
2113 1.1 mrg lhs_kind = build_int_cst (integer_type_node, lhs_expr->ts.kind);
2114 1.1 mrg
2115 1.1 mrg /* Special case: RHS is a coarray but LHS is not; this code path avoids a
2116 1.1 mrg temporary and a loop. */
2117 1.1 mrg if (!gfc_is_coindexed (lhs_expr)
2118 1.1 mrg && (!lhs_caf_attr.codimension
2119 1.1 mrg || !(lhs_expr->rank > 0
2120 1.1 mrg && (lhs_caf_attr.allocatable || lhs_caf_attr.pointer))))
2121 1.1 mrg {
2122 1.1 mrg bool lhs_may_realloc = lhs_expr->rank > 0 && lhs_caf_attr.allocatable;
2123 1.1 mrg gcc_assert (gfc_is_coindexed (rhs_expr));
2124 1.1 mrg gfc_init_se (&rhs_se, NULL);
2125 1.1 mrg if (lhs_expr->rank == 0 && lhs_caf_attr.allocatable)
2126 1.1 mrg {
2127 1.1 mrg gfc_se scal_se;
2128 1.1 mrg gfc_init_se (&scal_se, NULL);
2129 1.1 mrg scal_se.want_pointer = 1;
2130 1.1 mrg gfc_conv_expr (&scal_se, lhs_expr);
2131 1.1 mrg /* Ensure scalar on lhs is allocated. */
2132 1.1 mrg gfc_add_block_to_block (&block, &scal_se.pre);
2133 1.1 mrg
2134 1.1 mrg gfc_allocate_using_malloc (&scal_se.pre, scal_se.expr,
2135 1.1 mrg TYPE_SIZE_UNIT (
2136 1.1 mrg gfc_typenode_for_spec (&lhs_expr->ts)),
2137 1.1 mrg NULL_TREE);
2138 1.1 mrg tmp = fold_build2 (EQ_EXPR, logical_type_node, scal_se.expr,
2139 1.1 mrg null_pointer_node);
2140 1.1 mrg tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node,
2141 1.1 mrg tmp, gfc_finish_block (&scal_se.pre),
2142 1.1 mrg build_empty_stmt (input_location));
2143 1.1 mrg gfc_add_expr_to_block (&block, tmp);
2144 1.1 mrg }
2145 1.1 mrg else
2146 1.1 mrg lhs_may_realloc = lhs_may_realloc
2147 1.1 mrg && gfc_full_array_ref_p (lhs_expr->ref, NULL);
2148 1.1 mrg gfc_add_block_to_block (&block, &lhs_se.pre);
2149 1.1 mrg gfc_conv_intrinsic_caf_get (&rhs_se, rhs_expr, lhs_se.expr, lhs_kind,
2150 1.1 mrg may_require_tmp, lhs_may_realloc,
2151 1.1 mrg &rhs_caf_attr);
2152 1.1 mrg gfc_add_block_to_block (&block, &rhs_se.pre);
2153 1.1 mrg gfc_add_block_to_block (&block, &rhs_se.post);
2154 1.1 mrg gfc_add_block_to_block (&block, &lhs_se.post);
2155 1.1 mrg return gfc_finish_block (&block);
2156 1.1 mrg }
2157 1.1 mrg
2158 1.1 mrg gfc_add_block_to_block (&block, &lhs_se.pre);
2159 1.1 mrg
2160 1.1 mrg /* Obtain token, offset and image index for the LHS. */
2161 1.1 mrg caf_decl = gfc_get_tree_for_caf_expr (lhs_expr);
2162 1.1 mrg if (TREE_CODE (TREE_TYPE (caf_decl)) == REFERENCE_TYPE)
2163 1.1 mrg caf_decl = build_fold_indirect_ref_loc (input_location, caf_decl);
2164 1.1 mrg image_index = gfc_caf_get_image_index (&block, lhs_expr, caf_decl);
2165 1.1 mrg tmp = lhs_se.expr;
2166 1.1 mrg if (lhs_caf_attr.alloc_comp)
2167 1.1 mrg gfc_get_caf_token_offset (&lhs_se, &token, NULL, caf_decl, NULL_TREE,
2168 1.1 mrg NULL);
2169 1.1 mrg else
2170 1.1 mrg gfc_get_caf_token_offset (&lhs_se, &token, &offset, caf_decl, tmp,
2171 1.1 mrg lhs_expr);
2172 1.1 mrg lhs_se.expr = tmp;
2173 1.1 mrg
2174 1.1 mrg /* RHS. */
2175 1.1 mrg gfc_init_se (&rhs_se, NULL);
2176 1.1 mrg if (rhs_expr->expr_type == EXPR_FUNCTION && rhs_expr->value.function.isym
2177 1.1 mrg && rhs_expr->value.function.isym->id == GFC_ISYM_CONVERSION)
2178 1.1 mrg rhs_expr = rhs_expr->value.function.actual->expr;
2179 1.1 mrg if (rhs_expr->rank == 0)
2180 1.1 mrg {
2181 1.1 mrg symbol_attribute attr;
2182 1.1 mrg gfc_clear_attr (&attr);
2183 1.1 mrg gfc_conv_expr (&rhs_se, rhs_expr);
2184 1.1 mrg rhs_se.expr = gfc_conv_scalar_to_descriptor (&rhs_se, rhs_se.expr, attr);
2185 1.1 mrg rhs_se.expr = gfc_build_addr_expr (NULL_TREE, rhs_se.expr);
2186 1.1 mrg }
2187 1.1 mrg else if ((rhs_caf_attr.alloc_comp || rhs_caf_attr.pointer_comp)
2188 1.1 mrg && rhs_caf_attr.codimension)
2189 1.1 mrg {
2190 1.1 mrg tree tmp2;
2191 1.1 mrg rhs_se.want_pointer = 1;
2192 1.1 mrg gfc_conv_expr_descriptor (&rhs_se, rhs_expr);
2193 1.1 mrg /* Using gfc_conv_expr_descriptor, we only get the descriptor, but that
2194 1.1 mrg has the wrong type if component references are done. */
2195 1.1 mrg tmp2 = gfc_typenode_for_spec (&rhs_expr->ts);
2196 1.1 mrg tmp = build_fold_indirect_ref_loc (input_location, rhs_se.expr);
2197 1.1 mrg gfc_add_modify (&rhs_se.pre, gfc_conv_descriptor_dtype (tmp),
2198 1.1 mrg gfc_get_dtype_rank_type (
2199 1.1 mrg gfc_has_vector_subscript (rhs_expr)
2200 1.1 mrg ? gfc_find_array_ref (rhs_expr)->dimen
2201 1.1 mrg : rhs_expr->rank,
2202 1.1 mrg tmp2));
2203 1.1 mrg }
2204 1.1 mrg else
2205 1.1 mrg {
2206 1.1 mrg /* If has_vector, pass descriptor for whole array and the
2207 1.1 mrg vector bounds separately. */
2208 1.1 mrg gfc_array_ref *ar, ar2;
2209 1.1 mrg bool has_vector = false;
2210 1.1 mrg tree tmp2;
2211 1.1 mrg
2212 1.1 mrg if (gfc_is_coindexed (rhs_expr) && gfc_has_vector_subscript (rhs_expr))
2213 1.1 mrg {
2214 1.1 mrg has_vector = true;
2215 1.1 mrg ar = gfc_find_array_ref (rhs_expr);
2216 1.1 mrg ar2 = *ar;
2217 1.1 mrg memset (ar, '\0', sizeof (*ar));
2218 1.1 mrg ar->as = ar2.as;
2219 1.1 mrg ar->type = AR_FULL;
2220 1.1 mrg }
2221 1.1 mrg rhs_se.want_pointer = 1;
2222 1.1 mrg gfc_conv_expr_descriptor (&rhs_se, rhs_expr);
2223 1.1 mrg /* Using gfc_conv_expr_descriptor, we only get the descriptor, but that
2224 1.1 mrg has the wrong type if component references are done. */
2225 1.1 mrg tmp = build_fold_indirect_ref_loc (input_location, rhs_se.expr);
2226 1.1 mrg tmp2 = gfc_typenode_for_spec (&rhs_expr->ts);
2227 1.1 mrg gfc_add_modify (&rhs_se.pre, gfc_conv_descriptor_dtype (tmp),
2228 1.1 mrg gfc_get_dtype_rank_type (has_vector ? ar2.dimen
2229 1.1 mrg : rhs_expr->rank,
2230 1.1 mrg tmp2));
2231 1.1 mrg if (has_vector)
2232 1.1 mrg {
2233 1.1 mrg rhs_vec = conv_caf_vector_subscript (&block, rhs_se.expr, &ar2);
2234 1.1 mrg *ar = ar2;
2235 1.1 mrg }
2236 1.1 mrg }
2237 1.1 mrg
2238 1.1 mrg gfc_add_block_to_block (&block, &rhs_se.pre);
2239 1.1 mrg
2240 1.1 mrg rhs_kind = build_int_cst (integer_type_node, rhs_expr->ts.kind);
2241 1.1 mrg
2242 1.1 mrg tmp_stat = gfc_find_stat_co (lhs_expr);
2243 1.1 mrg
2244 1.1 mrg if (tmp_stat)
2245 1.1 mrg {
2246 1.1 mrg gfc_se stat_se;
2247 1.1 mrg gfc_init_se (&stat_se, NULL);
2248 1.1 mrg gfc_conv_expr_reference (&stat_se, tmp_stat);
2249 1.1 mrg dst_stat = stat_se.expr;
2250 1.1 mrg gfc_add_block_to_block (&block, &stat_se.pre);
2251 1.1 mrg gfc_add_block_to_block (&block, &stat_se.post);
2252 1.1 mrg }
2253 1.1 mrg
2254 1.1 mrg tmp_team = gfc_find_team_co (lhs_expr);
2255 1.1 mrg
2256 1.1 mrg if (tmp_team)
2257 1.1 mrg {
2258 1.1 mrg gfc_se team_se;
2259 1.1 mrg gfc_init_se (&team_se, NULL);
2260 1.1 mrg gfc_conv_expr_reference (&team_se, tmp_team);
2261 1.1 mrg dst_team = team_se.expr;
2262 1.1 mrg gfc_add_block_to_block (&block, &team_se.pre);
2263 1.1 mrg gfc_add_block_to_block (&block, &team_se.post);
2264 1.1 mrg }
2265 1.1 mrg
2266 1.1 mrg if (!gfc_is_coindexed (rhs_expr))
2267 1.1 mrg {
2268 1.1 mrg if (lhs_caf_attr.alloc_comp || lhs_caf_attr.pointer_comp)
2269 1.1 mrg {
2270 1.1 mrg tree reference, dst_realloc;
2271 1.1 mrg reference = conv_expr_ref_to_caf_ref (&block, lhs_expr);
2272 1.1 mrg dst_realloc = lhs_caf_attr.allocatable ? boolean_true_node
2273 1.1 mrg : boolean_false_node;
2274 1.1 mrg tmp = build_call_expr_loc (input_location,
2275 1.1 mrg gfor_fndecl_caf_send_by_ref,
2276 1.1 mrg 10, token, image_index, rhs_se.expr,
2277 1.1 mrg reference, lhs_kind, rhs_kind,
2278 1.1 mrg may_require_tmp, dst_realloc, src_stat,
2279 1.1 mrg build_int_cst (integer_type_node,
2280 1.1 mrg lhs_expr->ts.type));
2281 1.1 mrg }
2282 1.1 mrg else
2283 1.1 mrg tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_send, 11,
2284 1.1 mrg token, offset, image_index, lhs_se.expr, vec,
2285 1.1 mrg rhs_se.expr, lhs_kind, rhs_kind,
2286 1.1 mrg may_require_tmp, src_stat, dst_team);
2287 1.1 mrg }
2288 1.1 mrg else
2289 1.1 mrg {
2290 1.1 mrg tree rhs_token, rhs_offset, rhs_image_index;
2291 1.1 mrg
2292 1.1 mrg /* It guarantees memory consistency within the same segment. */
2293 1.1 mrg tmp = gfc_build_string_const (strlen ("memory") + 1, "memory");
2294 1.1 mrg tmp = build5_loc (input_location, ASM_EXPR, void_type_node,
2295 1.1 mrg gfc_build_string_const (1, ""), NULL_TREE, NULL_TREE,
2296 1.1 mrg tree_cons (NULL_TREE, tmp, NULL_TREE), NULL_TREE);
2297 1.1 mrg ASM_VOLATILE_P (tmp) = 1;
2298 1.1 mrg gfc_add_expr_to_block (&block, tmp);
2299 1.1 mrg
2300 1.1 mrg caf_decl = gfc_get_tree_for_caf_expr (rhs_expr);
2301 1.1 mrg if (TREE_CODE (TREE_TYPE (caf_decl)) == REFERENCE_TYPE)
2302 1.1 mrg caf_decl = build_fold_indirect_ref_loc (input_location, caf_decl);
2303 1.1 mrg rhs_image_index = gfc_caf_get_image_index (&block, rhs_expr, caf_decl);
2304 1.1 mrg tmp = rhs_se.expr;
2305 1.1 mrg if (rhs_caf_attr.alloc_comp || rhs_caf_attr.pointer_comp)
2306 1.1 mrg {
2307 1.1 mrg tmp_stat = gfc_find_stat_co (lhs_expr);
2308 1.1 mrg
2309 1.1 mrg if (tmp_stat)
2310 1.1 mrg {
2311 1.1 mrg gfc_se stat_se;
2312 1.1 mrg gfc_init_se (&stat_se, NULL);
2313 1.1 mrg gfc_conv_expr_reference (&stat_se, tmp_stat);
2314 1.1 mrg src_stat = stat_se.expr;
2315 1.1 mrg gfc_add_block_to_block (&block, &stat_se.pre);
2316 1.1 mrg gfc_add_block_to_block (&block, &stat_se.post);
2317 1.1 mrg }
2318 1.1 mrg
2319 1.1 mrg gfc_get_caf_token_offset (&rhs_se, &rhs_token, NULL, caf_decl,
2320 1.1 mrg NULL_TREE, NULL);
2321 1.1 mrg tree lhs_reference, rhs_reference;
2322 1.1 mrg lhs_reference = conv_expr_ref_to_caf_ref (&block, lhs_expr);
2323 1.1 mrg rhs_reference = conv_expr_ref_to_caf_ref (&block, rhs_expr);
2324 1.1 mrg tmp = build_call_expr_loc (input_location,
2325 1.1 mrg gfor_fndecl_caf_sendget_by_ref, 13,
2326 1.1 mrg token, image_index, lhs_reference,
2327 1.1 mrg rhs_token, rhs_image_index, rhs_reference,
2328 1.1 mrg lhs_kind, rhs_kind, may_require_tmp,
2329 1.1 mrg dst_stat, src_stat,
2330 1.1 mrg build_int_cst (integer_type_node,
2331 1.1 mrg lhs_expr->ts.type),
2332 1.1 mrg build_int_cst (integer_type_node,
2333 1.1 mrg rhs_expr->ts.type));
2334 1.1 mrg }
2335 1.1 mrg else
2336 1.1 mrg {
2337 1.1 mrg gfc_get_caf_token_offset (&rhs_se, &rhs_token, &rhs_offset, caf_decl,
2338 1.1 mrg tmp, rhs_expr);
2339 1.1 mrg tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_sendget,
2340 1.1 mrg 14, token, offset, image_index,
2341 1.1 mrg lhs_se.expr, vec, rhs_token, rhs_offset,
2342 1.1 mrg rhs_image_index, tmp, rhs_vec, lhs_kind,
2343 1.1 mrg rhs_kind, may_require_tmp, src_stat);
2344 1.1 mrg }
2345 1.1 mrg }
2346 1.1 mrg gfc_add_expr_to_block (&block, tmp);
2347 1.1 mrg gfc_add_block_to_block (&block, &lhs_se.post);
2348 1.1 mrg gfc_add_block_to_block (&block, &rhs_se.post);
2349 1.1 mrg
2350 1.1 mrg /* It guarantees memory consistency within the same segment. */
2351 1.1 mrg tmp = gfc_build_string_const (strlen ("memory") + 1, "memory");
2352 1.1 mrg tmp = build5_loc (input_location, ASM_EXPR, void_type_node,
2353 1.1 mrg gfc_build_string_const (1, ""), NULL_TREE, NULL_TREE,
2354 1.1 mrg tree_cons (NULL_TREE, tmp, NULL_TREE), NULL_TREE);
2355 1.1 mrg ASM_VOLATILE_P (tmp) = 1;
2356 1.1 mrg gfc_add_expr_to_block (&block, tmp);
2357 1.1 mrg
2358 1.1 mrg return gfc_finish_block (&block);
2359 1.1 mrg }
2360 1.1 mrg
2361 1.1 mrg
2362 1.1 mrg static void
2363 1.1 mrg trans_this_image (gfc_se * se, gfc_expr *expr)
2364 1.1 mrg {
2365 1.1 mrg stmtblock_t loop;
2366 1.1 mrg tree type, desc, dim_arg, cond, tmp, m, loop_var, exit_label, min_var,
2367 1.1 mrg lbound, ubound, extent, ml;
2368 1.1 mrg gfc_se argse;
2369 1.1 mrg int rank, corank;
2370 1.1 mrg gfc_expr *distance = expr->value.function.actual->next->next->expr;
2371 1.1 mrg
2372 1.1 mrg if (expr->value.function.actual->expr
2373 1.1 mrg && !gfc_is_coarray (expr->value.function.actual->expr))
2374 1.1 mrg distance = expr->value.function.actual->expr;
2375 1.1 mrg
2376 1.1 mrg /* The case -fcoarray=single is handled elsewhere. */
2377 1.1 mrg gcc_assert (flag_coarray != GFC_FCOARRAY_SINGLE);
2378 1.1 mrg
2379 1.1 mrg /* Argument-free version: THIS_IMAGE(). */
2380 1.1 mrg if (distance || expr->value.function.actual->expr == NULL)
2381 1.1 mrg {
2382 1.1 mrg if (distance)
2383 1.1 mrg {
2384 1.1 mrg gfc_init_se (&argse, NULL);
2385 1.1 mrg gfc_conv_expr_val (&argse, distance);
2386 1.1 mrg gfc_add_block_to_block (&se->pre, &argse.pre);
2387 1.1 mrg gfc_add_block_to_block (&se->post, &argse.post);
2388 1.1 mrg tmp = fold_convert (integer_type_node, argse.expr);
2389 1.1 mrg }
2390 1.1 mrg else
2391 1.1 mrg tmp = integer_zero_node;
2392 1.1 mrg tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_this_image, 1,
2393 1.1 mrg tmp);
2394 1.1 mrg se->expr = fold_convert (gfc_get_int_type (gfc_default_integer_kind),
2395 1.1 mrg tmp);
2396 1.1 mrg return;
2397 1.1 mrg }
2398 1.1 mrg
2399 1.1 mrg /* Coarray-argument version: THIS_IMAGE(coarray [, dim]). */
2400 1.1 mrg
2401 1.1 mrg type = gfc_get_int_type (gfc_default_integer_kind);
2402 1.1 mrg corank = gfc_get_corank (expr->value.function.actual->expr);
2403 1.1 mrg rank = expr->value.function.actual->expr->rank;
2404 1.1 mrg
2405 1.1 mrg /* Obtain the descriptor of the COARRAY. */
2406 1.1 mrg gfc_init_se (&argse, NULL);
2407 1.1 mrg argse.want_coarray = 1;
2408 1.1 mrg gfc_conv_expr_descriptor (&argse, expr->value.function.actual->expr);
2409 1.1 mrg gfc_add_block_to_block (&se->pre, &argse.pre);
2410 1.1 mrg gfc_add_block_to_block (&se->post, &argse.post);
2411 1.1 mrg desc = argse.expr;
2412 1.1 mrg
2413 1.1 mrg if (se->ss)
2414 1.1 mrg {
2415 1.1 mrg /* Create an implicit second parameter from the loop variable. */
2416 1.1 mrg gcc_assert (!expr->value.function.actual->next->expr);
2417 1.1 mrg gcc_assert (corank > 0);
2418 1.1 mrg gcc_assert (se->loop->dimen == 1);
2419 1.1 mrg gcc_assert (se->ss->info->expr == expr);
2420 1.1 mrg
2421 1.1 mrg dim_arg = se->loop->loopvar[0];
2422 1.1 mrg dim_arg = fold_build2_loc (input_location, PLUS_EXPR,
2423 1.1 mrg gfc_array_index_type, dim_arg,
2424 1.1 mrg build_int_cst (TREE_TYPE (dim_arg), 1));
2425 1.1 mrg gfc_advance_se_ss_chain (se);
2426 1.1 mrg }
2427 1.1 mrg else
2428 1.1 mrg {
2429 1.1 mrg /* Use the passed DIM= argument. */
2430 1.1 mrg gcc_assert (expr->value.function.actual->next->expr);
2431 1.1 mrg gfc_init_se (&argse, NULL);
2432 1.1 mrg gfc_conv_expr_type (&argse, expr->value.function.actual->next->expr,
2433 1.1 mrg gfc_array_index_type);
2434 1.1 mrg gfc_add_block_to_block (&se->pre, &argse.pre);
2435 1.1 mrg dim_arg = argse.expr;
2436 1.1 mrg
2437 1.1 mrg if (INTEGER_CST_P (dim_arg))
2438 1.1 mrg {
2439 1.1 mrg if (wi::ltu_p (wi::to_wide (dim_arg), 1)
2440 1.1 mrg || wi::gtu_p (wi::to_wide (dim_arg),
2441 1.1 mrg GFC_TYPE_ARRAY_CORANK (TREE_TYPE (desc))))
2442 1.1 mrg gfc_error ("%<dim%> argument of %s intrinsic at %L is not a valid "
2443 1.1 mrg "dimension index", expr->value.function.isym->name,
2444 1.1 mrg &expr->where);
2445 1.1 mrg }
2446 1.1 mrg else if (gfc_option.rtcheck & GFC_RTCHECK_BOUNDS)
2447 1.1 mrg {
2448 1.1 mrg dim_arg = gfc_evaluate_now (dim_arg, &se->pre);
2449 1.1 mrg cond = fold_build2_loc (input_location, LT_EXPR, logical_type_node,
2450 1.1 mrg dim_arg,
2451 1.1 mrg build_int_cst (TREE_TYPE (dim_arg), 1));
2452 1.1 mrg tmp = gfc_rank_cst[GFC_TYPE_ARRAY_CORANK (TREE_TYPE (desc))];
2453 1.1 mrg tmp = fold_build2_loc (input_location, GT_EXPR, logical_type_node,
2454 1.1 mrg dim_arg, tmp);
2455 1.1 mrg cond = fold_build2_loc (input_location, TRUTH_ORIF_EXPR,
2456 1.1 mrg logical_type_node, cond, tmp);
2457 1.1 mrg gfc_trans_runtime_check (true, false, cond, &se->pre, &expr->where,
2458 1.1 mrg gfc_msg_fault);
2459 1.1 mrg }
2460 1.1 mrg }
2461 1.1 mrg
2462 1.1 mrg /* Used algorithm; cf. Fortran 2008, C.10. Note, due to the scalarizer,
2463 1.1 mrg one always has a dim_arg argument.
2464 1.1 mrg
2465 1.1 mrg m = this_image() - 1
2466 1.1 mrg if (corank == 1)
2467 1.1 mrg {
2468 1.1 mrg sub(1) = m + lcobound(corank)
2469 1.1 mrg return;
2470 1.1 mrg }
2471 1.1 mrg i = rank
2472 1.1 mrg min_var = min (rank + corank - 2, rank + dim_arg - 1)
2473 1.1 mrg for (;;)
2474 1.1 mrg {
2475 1.1 mrg extent = gfc_extent(i)
2476 1.1 mrg ml = m
2477 1.1 mrg m = m/extent
2478 1.1 mrg if (i >= min_var)
2479 1.1 mrg goto exit_label
2480 1.1 mrg i++
2481 1.1 mrg }
2482 1.1 mrg exit_label:
2483 1.1 mrg sub(dim_arg) = (dim_arg < corank) ? ml - m*extent + lcobound(dim_arg)
2484 1.1 mrg : m + lcobound(corank)
2485 1.1 mrg */
2486 1.1 mrg
2487 1.1 mrg /* this_image () - 1. */
2488 1.1 mrg tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_this_image, 1,
2489 1.1 mrg integer_zero_node);
2490 1.1 mrg tmp = fold_build2_loc (input_location, MINUS_EXPR, type,
2491 1.1 mrg fold_convert (type, tmp), build_int_cst (type, 1));
2492 1.1 mrg if (corank == 1)
2493 1.1 mrg {
2494 1.1 mrg /* sub(1) = m + lcobound(corank). */
2495 1.1 mrg lbound = gfc_conv_descriptor_lbound_get (desc,
2496 1.1 mrg build_int_cst (TREE_TYPE (gfc_array_index_type),
2497 1.1 mrg corank+rank-1));
2498 1.1 mrg lbound = fold_convert (type, lbound);
2499 1.1 mrg tmp = fold_build2_loc (input_location, PLUS_EXPR, type, tmp, lbound);
2500 1.1 mrg
2501 1.1 mrg se->expr = tmp;
2502 1.1 mrg return;
2503 1.1 mrg }
2504 1.1 mrg
2505 1.1 mrg m = gfc_create_var (type, NULL);
2506 1.1 mrg ml = gfc_create_var (type, NULL);
2507 1.1 mrg loop_var = gfc_create_var (integer_type_node, NULL);
2508 1.1 mrg min_var = gfc_create_var (integer_type_node, NULL);
2509 1.1 mrg
2510 1.1 mrg /* m = this_image () - 1. */
2511 1.1 mrg gfc_add_modify (&se->pre, m, tmp);
2512 1.1 mrg
2513 1.1 mrg /* min_var = min (rank + corank-2, rank + dim_arg - 1). */
2514 1.1 mrg tmp = fold_build2_loc (input_location, PLUS_EXPR, integer_type_node,
2515 1.1 mrg fold_convert (integer_type_node, dim_arg),
2516 1.1 mrg build_int_cst (integer_type_node, rank - 1));
2517 1.1 mrg tmp = fold_build2_loc (input_location, MIN_EXPR, integer_type_node,
2518 1.1 mrg build_int_cst (integer_type_node, rank + corank - 2),
2519 1.1 mrg tmp);
2520 1.1 mrg gfc_add_modify (&se->pre, min_var, tmp);
2521 1.1 mrg
2522 1.1 mrg /* i = rank. */
2523 1.1 mrg tmp = build_int_cst (integer_type_node, rank);
2524 1.1 mrg gfc_add_modify (&se->pre, loop_var, tmp);
2525 1.1 mrg
2526 1.1 mrg exit_label = gfc_build_label_decl (NULL_TREE);
2527 1.1 mrg TREE_USED (exit_label) = 1;
2528 1.1 mrg
2529 1.1 mrg /* Loop body. */
2530 1.1 mrg gfc_init_block (&loop);
2531 1.1 mrg
2532 1.1 mrg /* ml = m. */
2533 1.1 mrg gfc_add_modify (&loop, ml, m);
2534 1.1 mrg
2535 1.1 mrg /* extent = ... */
2536 1.1 mrg lbound = gfc_conv_descriptor_lbound_get (desc, loop_var);
2537 1.1 mrg ubound = gfc_conv_descriptor_ubound_get (desc, loop_var);
2538 1.1 mrg extent = gfc_conv_array_extent_dim (lbound, ubound, NULL);
2539 1.1 mrg extent = fold_convert (type, extent);
2540 1.1 mrg
2541 1.1 mrg /* m = m/extent. */
2542 1.1 mrg gfc_add_modify (&loop, m,
2543 1.1 mrg fold_build2_loc (input_location, TRUNC_DIV_EXPR, type,
2544 1.1 mrg m, extent));
2545 1.1 mrg
2546 1.1 mrg /* Exit condition: if (i >= min_var) goto exit_label. */
2547 1.1 mrg cond = fold_build2_loc (input_location, GE_EXPR, logical_type_node, loop_var,
2548 1.1 mrg min_var);
2549 1.1 mrg tmp = build1_v (GOTO_EXPR, exit_label);
2550 1.1 mrg tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node, cond, tmp,
2551 1.1 mrg build_empty_stmt (input_location));
2552 1.1 mrg gfc_add_expr_to_block (&loop, tmp);
2553 1.1 mrg
2554 1.1 mrg /* Increment loop variable: i++. */
2555 1.1 mrg gfc_add_modify (&loop, loop_var,
2556 1.1 mrg fold_build2_loc (input_location, PLUS_EXPR, integer_type_node,
2557 1.1 mrg loop_var,
2558 1.1 mrg build_int_cst (integer_type_node, 1)));
2559 1.1 mrg
2560 1.1 mrg /* Making the loop... actually loop! */
2561 1.1 mrg tmp = gfc_finish_block (&loop);
2562 1.1 mrg tmp = build1_v (LOOP_EXPR, tmp);
2563 1.1 mrg gfc_add_expr_to_block (&se->pre, tmp);
2564 1.1 mrg
2565 1.1 mrg /* The exit label. */
2566 1.1 mrg tmp = build1_v (LABEL_EXPR, exit_label);
2567 1.1 mrg gfc_add_expr_to_block (&se->pre, tmp);
2568 1.1 mrg
2569 1.1 mrg /* sub(co_dim) = (co_dim < corank) ? ml - m*extent + lcobound(dim_arg)
2570 1.1 mrg : m + lcobound(corank) */
2571 1.1 mrg
2572 1.1 mrg cond = fold_build2_loc (input_location, LT_EXPR, logical_type_node, dim_arg,
2573 1.1 mrg build_int_cst (TREE_TYPE (dim_arg), corank));
2574 1.1 mrg
2575 1.1 mrg lbound = gfc_conv_descriptor_lbound_get (desc,
2576 1.1 mrg fold_build2_loc (input_location, PLUS_EXPR,
2577 1.1 mrg gfc_array_index_type, dim_arg,
2578 1.1 mrg build_int_cst (TREE_TYPE (dim_arg), rank-1)));
2579 1.1 mrg lbound = fold_convert (type, lbound);
2580 1.1 mrg
2581 1.1 mrg tmp = fold_build2_loc (input_location, MINUS_EXPR, type, ml,
2582 1.1 mrg fold_build2_loc (input_location, MULT_EXPR, type,
2583 1.1 mrg m, extent));
2584 1.1 mrg tmp = fold_build2_loc (input_location, PLUS_EXPR, type, tmp, lbound);
2585 1.1 mrg
2586 1.1 mrg se->expr = fold_build3_loc (input_location, COND_EXPR, type, cond, tmp,
2587 1.1 mrg fold_build2_loc (input_location, PLUS_EXPR, type,
2588 1.1 mrg m, lbound));
2589 1.1 mrg }
2590 1.1 mrg
2591 1.1 mrg
2592 1.1 mrg /* Convert a call to image_status. */
2593 1.1 mrg
2594 1.1 mrg static void
2595 1.1 mrg conv_intrinsic_image_status (gfc_se *se, gfc_expr *expr)
2596 1.1 mrg {
2597 1.1 mrg unsigned int num_args;
2598 1.1 mrg tree *args, tmp;
2599 1.1 mrg
2600 1.1 mrg num_args = gfc_intrinsic_argument_list_length (expr);
2601 1.1 mrg args = XALLOCAVEC (tree, num_args);
2602 1.1 mrg gfc_conv_intrinsic_function_args (se, expr, args, num_args);
2603 1.1 mrg /* In args[0] the number of the image the status is desired for has to be
2604 1.1 mrg given. */
2605 1.1 mrg
2606 1.1 mrg if (flag_coarray == GFC_FCOARRAY_SINGLE)
2607 1.1 mrg {
2608 1.1 mrg tree arg;
2609 1.1 mrg arg = gfc_evaluate_now (args[0], &se->pre);
2610 1.1 mrg tmp = fold_build2_loc (input_location, EQ_EXPR, logical_type_node,
2611 1.1 mrg fold_convert (integer_type_node, arg),
2612 1.1 mrg integer_one_node);
2613 1.1 mrg tmp = fold_build3_loc (input_location, COND_EXPR, integer_type_node,
2614 1.1 mrg tmp, integer_zero_node,
2615 1.1 mrg build_int_cst (integer_type_node,
2616 1.1 mrg GFC_STAT_STOPPED_IMAGE));
2617 1.1 mrg }
2618 1.1 mrg else if (flag_coarray == GFC_FCOARRAY_LIB)
2619 1.1 mrg tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_image_status, 2,
2620 1.1 mrg args[0], build_int_cst (integer_type_node, -1));
2621 1.1 mrg else
2622 1.1 mrg gcc_unreachable ();
2623 1.1 mrg
2624 1.1 mrg se->expr = fold_convert (gfc_get_int_type (gfc_default_integer_kind), tmp);
2625 1.1 mrg }
2626 1.1 mrg
2627 1.1 mrg static void
2628 1.1 mrg conv_intrinsic_team_number (gfc_se *se, gfc_expr *expr)
2629 1.1 mrg {
2630 1.1 mrg unsigned int num_args;
2631 1.1 mrg
2632 1.1 mrg tree *args, tmp;
2633 1.1 mrg
2634 1.1 mrg num_args = gfc_intrinsic_argument_list_length (expr);
2635 1.1 mrg args = XALLOCAVEC (tree, num_args);
2636 1.1 mrg gfc_conv_intrinsic_function_args (se, expr, args, num_args);
2637 1.1 mrg
2638 1.1 mrg if (flag_coarray ==
2639 1.1 mrg GFC_FCOARRAY_SINGLE && expr->value.function.actual->expr)
2640 1.1 mrg {
2641 1.1 mrg tree arg;
2642 1.1 mrg
2643 1.1 mrg arg = gfc_evaluate_now (args[0], &se->pre);
2644 1.1 mrg tmp = fold_build2_loc (input_location, EQ_EXPR, logical_type_node,
2645 1.1 mrg fold_convert (integer_type_node, arg),
2646 1.1 mrg integer_one_node);
2647 1.1 mrg tmp = fold_build3_loc (input_location, COND_EXPR, integer_type_node,
2648 1.1 mrg tmp, integer_zero_node,
2649 1.1 mrg build_int_cst (integer_type_node,
2650 1.1 mrg GFC_STAT_STOPPED_IMAGE));
2651 1.1 mrg }
2652 1.1 mrg else if (flag_coarray == GFC_FCOARRAY_SINGLE)
2653 1.1 mrg {
2654 1.1 mrg // the value -1 represents that no team has been created yet
2655 1.1 mrg tmp = build_int_cst (integer_type_node, -1);
2656 1.1 mrg }
2657 1.1 mrg else if (flag_coarray == GFC_FCOARRAY_LIB && expr->value.function.actual->expr)
2658 1.1 mrg tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_team_number, 1,
2659 1.1 mrg args[0], build_int_cst (integer_type_node, -1));
2660 1.1 mrg else if (flag_coarray == GFC_FCOARRAY_LIB)
2661 1.1 mrg tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_team_number, 1,
2662 1.1 mrg integer_zero_node, build_int_cst (integer_type_node, -1));
2663 1.1 mrg else
2664 1.1 mrg gcc_unreachable ();
2665 1.1 mrg
2666 1.1 mrg se->expr = fold_convert (gfc_get_int_type (gfc_default_integer_kind), tmp);
2667 1.1 mrg }
2668 1.1 mrg
2669 1.1 mrg
2670 1.1 mrg static void
2671 1.1 mrg trans_image_index (gfc_se * se, gfc_expr *expr)
2672 1.1 mrg {
2673 1.1 mrg tree num_images, cond, coindex, type, lbound, ubound, desc, subdesc,
2674 1.1 mrg tmp, invalid_bound;
2675 1.1 mrg gfc_se argse, subse;
2676 1.1 mrg int rank, corank, codim;
2677 1.1 mrg
2678 1.1 mrg type = gfc_get_int_type (gfc_default_integer_kind);
2679 1.1 mrg corank = gfc_get_corank (expr->value.function.actual->expr);
2680 1.1 mrg rank = expr->value.function.actual->expr->rank;
2681 1.1 mrg
2682 1.1 mrg /* Obtain the descriptor of the COARRAY. */
2683 1.1 mrg gfc_init_se (&argse, NULL);
2684 1.1 mrg argse.want_coarray = 1;
2685 1.1 mrg gfc_conv_expr_descriptor (&argse, expr->value.function.actual->expr);
2686 1.1 mrg gfc_add_block_to_block (&se->pre, &argse.pre);
2687 1.1 mrg gfc_add_block_to_block (&se->post, &argse.post);
2688 1.1 mrg desc = argse.expr;
2689 1.1 mrg
2690 1.1 mrg /* Obtain a handle to the SUB argument. */
2691 1.1 mrg gfc_init_se (&subse, NULL);
2692 1.1 mrg gfc_conv_expr_descriptor (&subse, expr->value.function.actual->next->expr);
2693 1.1 mrg gfc_add_block_to_block (&se->pre, &subse.pre);
2694 1.1 mrg gfc_add_block_to_block (&se->post, &subse.post);
2695 1.1 mrg subdesc = build_fold_indirect_ref_loc (input_location,
2696 1.1 mrg gfc_conv_descriptor_data_get (subse.expr));
2697 1.1 mrg
2698 1.1 mrg /* Fortran 2008 does not require that the values remain in the cobounds,
2699 1.1 mrg thus we need explicitly check this - and return 0 if they are exceeded. */
2700 1.1 mrg
2701 1.1 mrg lbound = gfc_conv_descriptor_lbound_get (desc, gfc_rank_cst[rank+corank-1]);
2702 1.1 mrg tmp = gfc_build_array_ref (subdesc, gfc_rank_cst[corank-1], NULL);
2703 1.1 mrg invalid_bound = fold_build2_loc (input_location, LT_EXPR, logical_type_node,
2704 1.1 mrg fold_convert (gfc_array_index_type, tmp),
2705 1.1 mrg lbound);
2706 1.1 mrg
2707 1.1 mrg for (codim = corank + rank - 2; codim >= rank; codim--)
2708 1.1 mrg {
2709 1.1 mrg lbound = gfc_conv_descriptor_lbound_get (desc, gfc_rank_cst[codim]);
2710 1.1 mrg ubound = gfc_conv_descriptor_ubound_get (desc, gfc_rank_cst[codim]);
2711 1.1 mrg tmp = gfc_build_array_ref (subdesc, gfc_rank_cst[codim-rank], NULL);
2712 1.1 mrg cond = fold_build2_loc (input_location, LT_EXPR, logical_type_node,
2713 1.1 mrg fold_convert (gfc_array_index_type, tmp),
2714 1.1 mrg lbound);
2715 1.1 mrg invalid_bound = fold_build2_loc (input_location, TRUTH_OR_EXPR,
2716 1.1 mrg logical_type_node, invalid_bound, cond);
2717 1.1 mrg cond = fold_build2_loc (input_location, GT_EXPR, logical_type_node,
2718 1.1 mrg fold_convert (gfc_array_index_type, tmp),
2719 1.1 mrg ubound);
2720 1.1 mrg invalid_bound = fold_build2_loc (input_location, TRUTH_OR_EXPR,
2721 1.1 mrg logical_type_node, invalid_bound, cond);
2722 1.1 mrg }
2723 1.1 mrg
2724 1.1 mrg invalid_bound = gfc_unlikely (invalid_bound, PRED_FORTRAN_INVALID_BOUND);
2725 1.1 mrg
2726 1.1 mrg /* See Fortran 2008, C.10 for the following algorithm. */
2727 1.1 mrg
2728 1.1 mrg /* coindex = sub(corank) - lcobound(n). */
2729 1.1 mrg coindex = fold_convert (gfc_array_index_type,
2730 1.1 mrg gfc_build_array_ref (subdesc, gfc_rank_cst[corank-1],
2731 1.1 mrg NULL));
2732 1.1 mrg lbound = gfc_conv_descriptor_lbound_get (desc, gfc_rank_cst[rank+corank-1]);
2733 1.1 mrg coindex = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
2734 1.1 mrg fold_convert (gfc_array_index_type, coindex),
2735 1.1 mrg lbound);
2736 1.1 mrg
2737 1.1 mrg for (codim = corank + rank - 2; codim >= rank; codim--)
2738 1.1 mrg {
2739 1.1 mrg tree extent, ubound;
2740 1.1 mrg
2741 1.1 mrg /* coindex = coindex*extent(codim) + sub(codim) - lcobound(codim). */
2742 1.1 mrg lbound = gfc_conv_descriptor_lbound_get (desc, gfc_rank_cst[codim]);
2743 1.1 mrg ubound = gfc_conv_descriptor_ubound_get (desc, gfc_rank_cst[codim]);
2744 1.1 mrg extent = gfc_conv_array_extent_dim (lbound, ubound, NULL);
2745 1.1 mrg
2746 1.1 mrg /* coindex *= extent. */
2747 1.1 mrg coindex = fold_build2_loc (input_location, MULT_EXPR,
2748 1.1 mrg gfc_array_index_type, coindex, extent);
2749 1.1 mrg
2750 1.1 mrg /* coindex += sub(codim). */
2751 1.1 mrg tmp = gfc_build_array_ref (subdesc, gfc_rank_cst[codim-rank], NULL);
2752 1.1 mrg coindex = fold_build2_loc (input_location, PLUS_EXPR,
2753 1.1 mrg gfc_array_index_type, coindex,
2754 1.1 mrg fold_convert (gfc_array_index_type, tmp));
2755 1.1 mrg
2756 1.1 mrg /* coindex -= lbound(codim). */
2757 1.1 mrg lbound = gfc_conv_descriptor_lbound_get (desc, gfc_rank_cst[codim]);
2758 1.1 mrg coindex = fold_build2_loc (input_location, MINUS_EXPR,
2759 1.1 mrg gfc_array_index_type, coindex, lbound);
2760 1.1 mrg }
2761 1.1 mrg
2762 1.1 mrg coindex = fold_build2_loc (input_location, PLUS_EXPR, type,
2763 1.1 mrg fold_convert(type, coindex),
2764 1.1 mrg build_int_cst (type, 1));
2765 1.1 mrg
2766 1.1 mrg /* Return 0 if "coindex" exceeds num_images(). */
2767 1.1 mrg
2768 1.1 mrg if (flag_coarray == GFC_FCOARRAY_SINGLE)
2769 1.1 mrg num_images = build_int_cst (type, 1);
2770 1.1 mrg else
2771 1.1 mrg {
2772 1.1 mrg tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_num_images, 2,
2773 1.1 mrg integer_zero_node,
2774 1.1 mrg build_int_cst (integer_type_node, -1));
2775 1.1 mrg num_images = fold_convert (type, tmp);
2776 1.1 mrg }
2777 1.1 mrg
2778 1.1 mrg tmp = gfc_create_var (type, NULL);
2779 1.1 mrg gfc_add_modify (&se->pre, tmp, coindex);
2780 1.1 mrg
2781 1.1 mrg cond = fold_build2_loc (input_location, GT_EXPR, logical_type_node, tmp,
2782 1.1 mrg num_images);
2783 1.1 mrg cond = fold_build2_loc (input_location, TRUTH_OR_EXPR, logical_type_node,
2784 1.1 mrg cond,
2785 1.1 mrg fold_convert (logical_type_node, invalid_bound));
2786 1.1 mrg se->expr = fold_build3_loc (input_location, COND_EXPR, type, cond,
2787 1.1 mrg build_int_cst (type, 0), tmp);
2788 1.1 mrg }
2789 1.1 mrg
2790 1.1 mrg static void
2791 1.1 mrg trans_num_images (gfc_se * se, gfc_expr *expr)
2792 1.1 mrg {
2793 1.1 mrg tree tmp, distance, failed;
2794 1.1 mrg gfc_se argse;
2795 1.1 mrg
2796 1.1 mrg if (expr->value.function.actual->expr)
2797 1.1 mrg {
2798 1.1 mrg gfc_init_se (&argse, NULL);
2799 1.1 mrg gfc_conv_expr_val (&argse, expr->value.function.actual->expr);
2800 1.1 mrg gfc_add_block_to_block (&se->pre, &argse.pre);
2801 1.1 mrg gfc_add_block_to_block (&se->post, &argse.post);
2802 1.1 mrg distance = fold_convert (integer_type_node, argse.expr);
2803 1.1 mrg }
2804 1.1 mrg else
2805 1.1 mrg distance = integer_zero_node;
2806 1.1 mrg
2807 1.1 mrg if (expr->value.function.actual->next->expr)
2808 1.1 mrg {
2809 1.1 mrg gfc_init_se (&argse, NULL);
2810 1.1 mrg gfc_conv_expr_val (&argse, expr->value.function.actual->next->expr);
2811 1.1 mrg gfc_add_block_to_block (&se->pre, &argse.pre);
2812 1.1 mrg gfc_add_block_to_block (&se->post, &argse.post);
2813 1.1 mrg failed = fold_convert (integer_type_node, argse.expr);
2814 1.1 mrg }
2815 1.1 mrg else
2816 1.1 mrg failed = build_int_cst (integer_type_node, -1);
2817 1.1 mrg tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_num_images, 2,
2818 1.1 mrg distance, failed);
2819 1.1 mrg se->expr = fold_convert (gfc_get_int_type (gfc_default_integer_kind), tmp);
2820 1.1 mrg }
2821 1.1 mrg
2822 1.1 mrg
2823 1.1 mrg static void
2824 1.1 mrg gfc_conv_intrinsic_rank (gfc_se *se, gfc_expr *expr)
2825 1.1 mrg {
2826 1.1 mrg gfc_se argse;
2827 1.1 mrg
2828 1.1 mrg gfc_init_se (&argse, NULL);
2829 1.1 mrg argse.data_not_needed = 1;
2830 1.1 mrg argse.descriptor_only = 1;
2831 1.1 mrg
2832 1.1 mrg gfc_conv_expr_descriptor (&argse, expr->value.function.actual->expr);
2833 1.1 mrg gfc_add_block_to_block (&se->pre, &argse.pre);
2834 1.1 mrg gfc_add_block_to_block (&se->post, &argse.post);
2835 1.1 mrg
2836 1.1 mrg se->expr = gfc_conv_descriptor_rank (argse.expr);
2837 1.1 mrg se->expr = fold_convert (gfc_get_int_type (gfc_default_integer_kind),
2838 1.1 mrg se->expr);
2839 1.1 mrg }
2840 1.1 mrg
2841 1.1 mrg
2842 1.1 mrg static void
2843 1.1 mrg gfc_conv_intrinsic_is_contiguous (gfc_se * se, gfc_expr * expr)
2844 1.1 mrg {
2845 1.1 mrg gfc_expr *arg;
2846 1.1 mrg arg = expr->value.function.actual->expr;
2847 1.1 mrg gfc_conv_is_contiguous_expr (se, arg);
2848 1.1 mrg se->expr = fold_convert (gfc_typenode_for_spec (&expr->ts), se->expr);
2849 1.1 mrg }
2850 1.1 mrg
2851 1.1 mrg /* This function does the work for gfc_conv_intrinsic_is_contiguous,
2852 1.1 mrg plus it can be called directly. */
2853 1.1 mrg
2854 1.1 mrg void
2855 1.1 mrg gfc_conv_is_contiguous_expr (gfc_se *se, gfc_expr *arg)
2856 1.1 mrg {
2857 1.1 mrg gfc_ss *ss;
2858 1.1 mrg gfc_se argse;
2859 1.1 mrg tree desc, tmp, stride, extent, cond;
2860 1.1 mrg int i;
2861 1.1 mrg tree fncall0;
2862 1.1 mrg gfc_array_spec *as;
2863 1.1 mrg
2864 1.1 mrg if (arg->ts.type == BT_CLASS)
2865 1.1 mrg gfc_add_class_array_ref (arg);
2866 1.1 mrg
2867 1.1 mrg ss = gfc_walk_expr (arg);
2868 1.1 mrg gcc_assert (ss != gfc_ss_terminator);
2869 1.1 mrg gfc_init_se (&argse, NULL);
2870 1.1 mrg argse.data_not_needed = 1;
2871 1.1 mrg gfc_conv_expr_descriptor (&argse, arg);
2872 1.1 mrg
2873 1.1 mrg as = gfc_get_full_arrayspec_from_expr (arg);
2874 1.1 mrg
2875 1.1 mrg /* Create: stride[0] == 1 && stride[1] == extend[0]*stride[0] && ...
2876 1.1 mrg Note in addition that zero-sized arrays don't count as contiguous. */
2877 1.1 mrg
2878 1.1 mrg if (as && as->type == AS_ASSUMED_RANK)
2879 1.1 mrg {
2880 1.1 mrg /* Build the call to is_contiguous0. */
2881 1.1 mrg argse.want_pointer = 1;
2882 1.1 mrg gfc_conv_expr_descriptor (&argse, arg);
2883 1.1 mrg gfc_add_block_to_block (&se->pre, &argse.pre);
2884 1.1 mrg gfc_add_block_to_block (&se->post, &argse.post);
2885 1.1 mrg desc = gfc_evaluate_now (argse.expr, &se->pre);
2886 1.1 mrg fncall0 = build_call_expr_loc (input_location,
2887 1.1 mrg gfor_fndecl_is_contiguous0, 1, desc);
2888 1.1 mrg se->expr = fncall0;
2889 1.1 mrg se->expr = convert (logical_type_node, se->expr);
2890 1.1 mrg }
2891 1.1 mrg else
2892 1.1 mrg {
2893 1.1 mrg gfc_add_block_to_block (&se->pre, &argse.pre);
2894 1.1 mrg gfc_add_block_to_block (&se->post, &argse.post);
2895 1.1 mrg desc = gfc_evaluate_now (argse.expr, &se->pre);
2896 1.1 mrg
2897 1.1 mrg stride = gfc_conv_descriptor_stride_get (desc, gfc_rank_cst[0]);
2898 1.1 mrg cond = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node,
2899 1.1 mrg stride, build_int_cst (TREE_TYPE (stride), 1));
2900 1.1 mrg
2901 1.1 mrg for (i = 0; i < arg->rank - 1; i++)
2902 1.1 mrg {
2903 1.1 mrg tmp = gfc_conv_descriptor_lbound_get (desc, gfc_rank_cst[i]);
2904 1.1 mrg extent = gfc_conv_descriptor_ubound_get (desc, gfc_rank_cst[i]);
2905 1.1 mrg extent = fold_build2_loc (input_location, MINUS_EXPR,
2906 1.1 mrg gfc_array_index_type, extent, tmp);
2907 1.1 mrg extent = fold_build2_loc (input_location, PLUS_EXPR,
2908 1.1 mrg gfc_array_index_type, extent,
2909 1.1 mrg gfc_index_one_node);
2910 1.1 mrg tmp = gfc_conv_descriptor_stride_get (desc, gfc_rank_cst[i]);
2911 1.1 mrg tmp = fold_build2_loc (input_location, MULT_EXPR, TREE_TYPE (tmp),
2912 1.1 mrg tmp, extent);
2913 1.1 mrg stride = gfc_conv_descriptor_stride_get (desc, gfc_rank_cst[i+1]);
2914 1.1 mrg tmp = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node,
2915 1.1 mrg stride, tmp);
2916 1.1 mrg cond = fold_build2_loc (input_location, TRUTH_AND_EXPR,
2917 1.1 mrg boolean_type_node, cond, tmp);
2918 1.1 mrg }
2919 1.1 mrg se->expr = cond;
2920 1.1 mrg }
2921 1.1 mrg }
2922 1.1 mrg
2923 1.1 mrg
2924 1.1 mrg /* Evaluate a single upper or lower bound. */
2925 1.1 mrg /* TODO: bound intrinsic generates way too much unnecessary code. */
2926 1.1 mrg
2927 1.1 mrg static void
2928 1.1 mrg gfc_conv_intrinsic_bound (gfc_se * se, gfc_expr * expr, enum gfc_isym_id op)
2929 1.1 mrg {
2930 1.1 mrg gfc_actual_arglist *arg;
2931 1.1 mrg gfc_actual_arglist *arg2;
2932 1.1 mrg tree desc;
2933 1.1 mrg tree type;
2934 1.1 mrg tree bound;
2935 1.1 mrg tree tmp;
2936 1.1 mrg tree cond, cond1;
2937 1.1 mrg tree ubound;
2938 1.1 mrg tree lbound;
2939 1.1 mrg tree size;
2940 1.1 mrg gfc_se argse;
2941 1.1 mrg gfc_array_spec * as;
2942 1.1 mrg bool assumed_rank_lb_one;
2943 1.1 mrg
2944 1.1 mrg arg = expr->value.function.actual;
2945 1.1 mrg arg2 = arg->next;
2946 1.1 mrg
2947 1.1 mrg if (se->ss)
2948 1.1 mrg {
2949 1.1 mrg /* Create an implicit second parameter from the loop variable. */
2950 1.1 mrg gcc_assert (!arg2->expr || op == GFC_ISYM_SHAPE);
2951 1.1 mrg gcc_assert (se->loop->dimen == 1);
2952 1.1 mrg gcc_assert (se->ss->info->expr == expr);
2953 1.1 mrg gfc_advance_se_ss_chain (se);
2954 1.1 mrg bound = se->loop->loopvar[0];
2955 1.1 mrg bound = fold_build2_loc (input_location, MINUS_EXPR,
2956 1.1 mrg gfc_array_index_type, bound,
2957 1.1 mrg se->loop->from[0]);
2958 1.1 mrg }
2959 1.1 mrg else
2960 1.1 mrg {
2961 1.1 mrg /* use the passed argument. */
2962 1.1 mrg gcc_assert (arg2->expr);
2963 1.1 mrg gfc_init_se (&argse, NULL);
2964 1.1 mrg gfc_conv_expr_type (&argse, arg2->expr, gfc_array_index_type);
2965 1.1 mrg gfc_add_block_to_block (&se->pre, &argse.pre);
2966 1.1 mrg bound = argse.expr;
2967 1.1 mrg /* Convert from one based to zero based. */
2968 1.1 mrg bound = fold_build2_loc (input_location, MINUS_EXPR,
2969 1.1 mrg gfc_array_index_type, bound,
2970 1.1 mrg gfc_index_one_node);
2971 1.1 mrg }
2972 1.1 mrg
2973 1.1 mrg /* TODO: don't re-evaluate the descriptor on each iteration. */
2974 1.1 mrg /* Get a descriptor for the first parameter. */
2975 1.1 mrg gfc_init_se (&argse, NULL);
2976 1.1 mrg gfc_conv_expr_descriptor (&argse, arg->expr);
2977 1.1 mrg gfc_add_block_to_block (&se->pre, &argse.pre);
2978 1.1 mrg gfc_add_block_to_block (&se->post, &argse.post);
2979 1.1 mrg
2980 1.1 mrg desc = argse.expr;
2981 1.1 mrg
2982 1.1 mrg as = gfc_get_full_arrayspec_from_expr (arg->expr);
2983 1.1 mrg
2984 1.1 mrg if (INTEGER_CST_P (bound))
2985 1.1 mrg {
2986 1.1 mrg gcc_assert (op != GFC_ISYM_SHAPE);
2987 1.1 mrg if (((!as || as->type != AS_ASSUMED_RANK)
2988 1.1 mrg && wi::geu_p (wi::to_wide (bound),
2989 1.1 mrg GFC_TYPE_ARRAY_RANK (TREE_TYPE (desc))))
2990 1.1 mrg || wi::gtu_p (wi::to_wide (bound), GFC_MAX_DIMENSIONS))
2991 1.1 mrg gfc_error ("%<dim%> argument of %s intrinsic at %L is not a valid "
2992 1.1 mrg "dimension index",
2993 1.1 mrg (op == GFC_ISYM_UBOUND) ? "UBOUND" : "LBOUND",
2994 1.1 mrg &expr->where);
2995 1.1 mrg }
2996 1.1 mrg
2997 1.1 mrg if (!INTEGER_CST_P (bound) || (as && as->type == AS_ASSUMED_RANK))
2998 1.1 mrg {
2999 1.1 mrg if (gfc_option.rtcheck & GFC_RTCHECK_BOUNDS)
3000 1.1 mrg {
3001 1.1 mrg bound = gfc_evaluate_now (bound, &se->pre);
3002 1.1 mrg cond = fold_build2_loc (input_location, LT_EXPR, logical_type_node,
3003 1.1 mrg bound, build_int_cst (TREE_TYPE (bound), 0));
3004 1.1 mrg if (as && as->type == AS_ASSUMED_RANK)
3005 1.1 mrg tmp = gfc_conv_descriptor_rank (desc);
3006 1.1 mrg else
3007 1.1 mrg tmp = gfc_rank_cst[GFC_TYPE_ARRAY_RANK (TREE_TYPE (desc))];
3008 1.1 mrg tmp = fold_build2_loc (input_location, GE_EXPR, logical_type_node,
3009 1.1 mrg bound, fold_convert(TREE_TYPE (bound), tmp));
3010 1.1 mrg cond = fold_build2_loc (input_location, TRUTH_ORIF_EXPR,
3011 1.1 mrg logical_type_node, cond, tmp);
3012 1.1 mrg gfc_trans_runtime_check (true, false, cond, &se->pre, &expr->where,
3013 1.1 mrg gfc_msg_fault);
3014 1.1 mrg }
3015 1.1 mrg }
3016 1.1 mrg
3017 1.1 mrg /* Take care of the lbound shift for assumed-rank arrays that are
3018 1.1 mrg nonallocatable and nonpointers. Those have a lbound of 1. */
3019 1.1 mrg assumed_rank_lb_one = as && as->type == AS_ASSUMED_RANK
3020 1.1 mrg && ((arg->expr->ts.type != BT_CLASS
3021 1.1 mrg && !arg->expr->symtree->n.sym->attr.allocatable
3022 1.1 mrg && !arg->expr->symtree->n.sym->attr.pointer)
3023 1.1 mrg || (arg->expr->ts.type == BT_CLASS
3024 1.1 mrg && !CLASS_DATA (arg->expr)->attr.allocatable
3025 1.1 mrg && !CLASS_DATA (arg->expr)->attr.class_pointer));
3026 1.1 mrg
3027 1.1 mrg ubound = gfc_conv_descriptor_ubound_get (desc, bound);
3028 1.1 mrg lbound = gfc_conv_descriptor_lbound_get (desc, bound);
3029 1.1 mrg size = fold_build2_loc (input_location, MINUS_EXPR,
3030 1.1 mrg gfc_array_index_type, ubound, lbound);
3031 1.1 mrg size = fold_build2_loc (input_location, PLUS_EXPR,
3032 1.1 mrg gfc_array_index_type, size, gfc_index_one_node);
3033 1.1 mrg
3034 1.1 mrg /* 13.14.53: Result value for LBOUND
3035 1.1 mrg
3036 1.1 mrg Case (i): For an array section or for an array expression other than a
3037 1.1 mrg whole array or array structure component, LBOUND(ARRAY, DIM)
3038 1.1 mrg has the value 1. For a whole array or array structure
3039 1.1 mrg component, LBOUND(ARRAY, DIM) has the value:
3040 1.1 mrg (a) equal to the lower bound for subscript DIM of ARRAY if
3041 1.1 mrg dimension DIM of ARRAY does not have extent zero
3042 1.1 mrg or if ARRAY is an assumed-size array of rank DIM,
3043 1.1 mrg or (b) 1 otherwise.
3044 1.1 mrg
3045 1.1 mrg 13.14.113: Result value for UBOUND
3046 1.1 mrg
3047 1.1 mrg Case (i): For an array section or for an array expression other than a
3048 1.1 mrg whole array or array structure component, UBOUND(ARRAY, DIM)
3049 1.1 mrg has the value equal to the number of elements in the given
3050 1.1 mrg dimension; otherwise, it has a value equal to the upper bound
3051 1.1 mrg for subscript DIM of ARRAY if dimension DIM of ARRAY does
3052 1.1 mrg not have size zero and has value zero if dimension DIM has
3053 1.1 mrg size zero. */
3054 1.1 mrg
3055 1.1 mrg if (op == GFC_ISYM_LBOUND && assumed_rank_lb_one)
3056 1.1 mrg se->expr = gfc_index_one_node;
3057 1.1 mrg else if (as)
3058 1.1 mrg {
3059 1.1 mrg if (op == GFC_ISYM_UBOUND)
3060 1.1 mrg {
3061 1.1 mrg cond = fold_build2_loc (input_location, GT_EXPR, logical_type_node,
3062 1.1 mrg size, gfc_index_zero_node);
3063 1.1 mrg se->expr = fold_build3_loc (input_location, COND_EXPR,
3064 1.1 mrg gfc_array_index_type, cond,
3065 1.1 mrg (assumed_rank_lb_one ? size : ubound),
3066 1.1 mrg gfc_index_zero_node);
3067 1.1 mrg }
3068 1.1 mrg else if (op == GFC_ISYM_LBOUND)
3069 1.1 mrg {
3070 1.1 mrg cond = fold_build2_loc (input_location, GT_EXPR, logical_type_node,
3071 1.1 mrg size, gfc_index_zero_node);
3072 1.1 mrg if (as->type == AS_ASSUMED_SIZE)
3073 1.1 mrg {
3074 1.1 mrg cond1 = fold_build2_loc (input_location, EQ_EXPR,
3075 1.1 mrg logical_type_node, bound,
3076 1.1 mrg build_int_cst (TREE_TYPE (bound),
3077 1.1 mrg arg->expr->rank - 1));
3078 1.1 mrg cond = fold_build2_loc (input_location, TRUTH_OR_EXPR,
3079 1.1 mrg logical_type_node, cond, cond1);
3080 1.1 mrg }
3081 1.1 mrg se->expr = fold_build3_loc (input_location, COND_EXPR,
3082 1.1 mrg gfc_array_index_type, cond,
3083 1.1 mrg lbound, gfc_index_one_node);
3084 1.1 mrg }
3085 1.1 mrg else if (op == GFC_ISYM_SHAPE)
3086 1.1 mrg se->expr = fold_build2_loc (input_location, MAX_EXPR,
3087 1.1 mrg gfc_array_index_type, size,
3088 1.1 mrg gfc_index_zero_node);
3089 1.1 mrg else
3090 1.1 mrg gcc_unreachable ();
3091 1.1 mrg
3092 1.1 mrg /* According to F2018 16.9.172, para 5, an assumed rank object,
3093 1.1 mrg argument associated with and assumed size array, has the ubound
3094 1.1 mrg of the final dimension set to -1 and UBOUND must return this.
3095 1.1 mrg Similarly for the SHAPE intrinsic. */
3096 1.1 mrg if (op != GFC_ISYM_LBOUND && assumed_rank_lb_one)
3097 1.1 mrg {
3098 1.1 mrg tree minus_one = build_int_cst (gfc_array_index_type, -1);
3099 1.1 mrg tree rank = fold_convert (gfc_array_index_type,
3100 1.1 mrg gfc_conv_descriptor_rank (desc));
3101 1.1 mrg rank = fold_build2_loc (input_location, PLUS_EXPR,
3102 1.1 mrg gfc_array_index_type, rank, minus_one);
3103 1.1 mrg
3104 1.1 mrg /* Fix the expression to stop it from becoming even more
3105 1.1 mrg complicated. */
3106 1.1 mrg se->expr = gfc_evaluate_now (se->expr, &se->pre);
3107 1.1 mrg
3108 1.1 mrg /* Descriptors for assumed-size arrays have ubound = -1
3109 1.1 mrg in the last dimension. */
3110 1.1 mrg cond1 = fold_build2_loc (input_location, EQ_EXPR,
3111 1.1 mrg logical_type_node, ubound, minus_one);
3112 1.1 mrg cond = fold_build2_loc (input_location, EQ_EXPR,
3113 1.1 mrg logical_type_node, bound, rank);
3114 1.1 mrg cond = fold_build2_loc (input_location, TRUTH_AND_EXPR,
3115 1.1 mrg logical_type_node, cond, cond1);
3116 1.1 mrg se->expr = fold_build3_loc (input_location, COND_EXPR,
3117 1.1 mrg gfc_array_index_type, cond,
3118 1.1 mrg minus_one, se->expr);
3119 1.1 mrg }
3120 1.1 mrg }
3121 1.1 mrg else /* as is null; this is an old-fashioned 1-based array. */
3122 1.1 mrg {
3123 1.1 mrg if (op != GFC_ISYM_LBOUND)
3124 1.1 mrg {
3125 1.1 mrg se->expr = fold_build2_loc (input_location, MAX_EXPR,
3126 1.1 mrg gfc_array_index_type, size,
3127 1.1 mrg gfc_index_zero_node);
3128 1.1 mrg }
3129 1.1 mrg else
3130 1.1 mrg se->expr = gfc_index_one_node;
3131 1.1 mrg }
3132 1.1 mrg
3133 1.1 mrg
3134 1.1 mrg type = gfc_typenode_for_spec (&expr->ts);
3135 1.1 mrg se->expr = convert (type, se->expr);
3136 1.1 mrg }
3137 1.1 mrg
3138 1.1 mrg
3139 1.1 mrg static void
3140 1.1 mrg conv_intrinsic_cobound (gfc_se * se, gfc_expr * expr)
3141 1.1 mrg {
3142 1.1 mrg gfc_actual_arglist *arg;
3143 1.1 mrg gfc_actual_arglist *arg2;
3144 1.1 mrg gfc_se argse;
3145 1.1 mrg tree bound, resbound, resbound2, desc, cond, tmp;
3146 1.1 mrg tree type;
3147 1.1 mrg int corank;
3148 1.1 mrg
3149 1.1 mrg gcc_assert (expr->value.function.isym->id == GFC_ISYM_LCOBOUND
3150 1.1 mrg || expr->value.function.isym->id == GFC_ISYM_UCOBOUND
3151 1.1 mrg || expr->value.function.isym->id == GFC_ISYM_THIS_IMAGE);
3152 1.1 mrg
3153 1.1 mrg arg = expr->value.function.actual;
3154 1.1 mrg arg2 = arg->next;
3155 1.1 mrg
3156 1.1 mrg gcc_assert (arg->expr->expr_type == EXPR_VARIABLE);
3157 1.1 mrg corank = gfc_get_corank (arg->expr);
3158 1.1 mrg
3159 1.1 mrg gfc_init_se (&argse, NULL);
3160 1.1 mrg argse.want_coarray = 1;
3161 1.1 mrg
3162 1.1 mrg gfc_conv_expr_descriptor (&argse, arg->expr);
3163 1.1 mrg gfc_add_block_to_block (&se->pre, &argse.pre);
3164 1.1 mrg gfc_add_block_to_block (&se->post, &argse.post);
3165 1.1 mrg desc = argse.expr;
3166 1.1 mrg
3167 1.1 mrg if (se->ss)
3168 1.1 mrg {
3169 1.1 mrg /* Create an implicit second parameter from the loop variable. */
3170 1.1 mrg gcc_assert (!arg2->expr);
3171 1.1 mrg gcc_assert (corank > 0);
3172 1.1 mrg gcc_assert (se->loop->dimen == 1);
3173 1.1 mrg gcc_assert (se->ss->info->expr == expr);
3174 1.1 mrg
3175 1.1 mrg bound = se->loop->loopvar[0];
3176 1.1 mrg bound = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
3177 1.1 mrg bound, gfc_rank_cst[arg->expr->rank]);
3178 1.1 mrg gfc_advance_se_ss_chain (se);
3179 1.1 mrg }
3180 1.1 mrg else
3181 1.1 mrg {
3182 1.1 mrg /* use the passed argument. */
3183 1.1 mrg gcc_assert (arg2->expr);
3184 1.1 mrg gfc_init_se (&argse, NULL);
3185 1.1 mrg gfc_conv_expr_type (&argse, arg2->expr, gfc_array_index_type);
3186 1.1 mrg gfc_add_block_to_block (&se->pre, &argse.pre);
3187 1.1 mrg bound = argse.expr;
3188 1.1 mrg
3189 1.1 mrg if (INTEGER_CST_P (bound))
3190 1.1 mrg {
3191 1.1 mrg if (wi::ltu_p (wi::to_wide (bound), 1)
3192 1.1 mrg || wi::gtu_p (wi::to_wide (bound),
3193 1.1 mrg GFC_TYPE_ARRAY_CORANK (TREE_TYPE (desc))))
3194 1.1 mrg gfc_error ("%<dim%> argument of %s intrinsic at %L is not a valid "
3195 1.1 mrg "dimension index", expr->value.function.isym->name,
3196 1.1 mrg &expr->where);
3197 1.1 mrg }
3198 1.1 mrg else if (gfc_option.rtcheck & GFC_RTCHECK_BOUNDS)
3199 1.1 mrg {
3200 1.1 mrg bound = gfc_evaluate_now (bound, &se->pre);
3201 1.1 mrg cond = fold_build2_loc (input_location, LT_EXPR, logical_type_node,
3202 1.1 mrg bound, build_int_cst (TREE_TYPE (bound), 1));
3203 1.1 mrg tmp = gfc_rank_cst[GFC_TYPE_ARRAY_CORANK (TREE_TYPE (desc))];
3204 1.1 mrg tmp = fold_build2_loc (input_location, GT_EXPR, logical_type_node,
3205 1.1 mrg bound, tmp);
3206 1.1 mrg cond = fold_build2_loc (input_location, TRUTH_ORIF_EXPR,
3207 1.1 mrg logical_type_node, cond, tmp);
3208 1.1 mrg gfc_trans_runtime_check (true, false, cond, &se->pre, &expr->where,
3209 1.1 mrg gfc_msg_fault);
3210 1.1 mrg }
3211 1.1 mrg
3212 1.1 mrg
3213 1.1 mrg /* Subtract 1 to get to zero based and add dimensions. */
3214 1.1 mrg switch (arg->expr->rank)
3215 1.1 mrg {
3216 1.1 mrg case 0:
3217 1.1 mrg bound = fold_build2_loc (input_location, MINUS_EXPR,
3218 1.1 mrg gfc_array_index_type, bound,
3219 1.1 mrg gfc_index_one_node);
3220 1.1 mrg case 1:
3221 1.1 mrg break;
3222 1.1 mrg default:
3223 1.1 mrg bound = fold_build2_loc (input_location, PLUS_EXPR,
3224 1.1 mrg gfc_array_index_type, bound,
3225 1.1 mrg gfc_rank_cst[arg->expr->rank - 1]);
3226 1.1 mrg }
3227 1.1 mrg }
3228 1.1 mrg
3229 1.1 mrg resbound = gfc_conv_descriptor_lbound_get (desc, bound);
3230 1.1 mrg
3231 1.1 mrg /* Handle UCOBOUND with special handling of the last codimension. */
3232 1.1 mrg if (expr->value.function.isym->id == GFC_ISYM_UCOBOUND)
3233 1.1 mrg {
3234 1.1 mrg /* Last codimension: For -fcoarray=single just return
3235 1.1 mrg the lcobound - otherwise add
3236 1.1 mrg ceiling (real (num_images ()) / real (size)) - 1
3237 1.1 mrg = (num_images () + size - 1) / size - 1
3238 1.1 mrg = (num_images - 1) / size(),
3239 1.1 mrg where size is the product of the extent of all but the last
3240 1.1 mrg codimension. */
3241 1.1 mrg
3242 1.1 mrg if (flag_coarray != GFC_FCOARRAY_SINGLE && corank > 1)
3243 1.1 mrg {
3244 1.1 mrg tree cosize;
3245 1.1 mrg
3246 1.1 mrg cosize = gfc_conv_descriptor_cosize (desc, arg->expr->rank, corank);
3247 1.1 mrg tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_num_images,
3248 1.1 mrg 2, integer_zero_node,
3249 1.1 mrg build_int_cst (integer_type_node, -1));
3250 1.1 mrg tmp = fold_build2_loc (input_location, MINUS_EXPR,
3251 1.1 mrg gfc_array_index_type,
3252 1.1 mrg fold_convert (gfc_array_index_type, tmp),
3253 1.1 mrg build_int_cst (gfc_array_index_type, 1));
3254 1.1 mrg tmp = fold_build2_loc (input_location, TRUNC_DIV_EXPR,
3255 1.1 mrg gfc_array_index_type, tmp,
3256 1.1 mrg fold_convert (gfc_array_index_type, cosize));
3257 1.1 mrg resbound = fold_build2_loc (input_location, PLUS_EXPR,
3258 1.1 mrg gfc_array_index_type, resbound, tmp);
3259 1.1 mrg }
3260 1.1 mrg else if (flag_coarray != GFC_FCOARRAY_SINGLE)
3261 1.1 mrg {
3262 1.1 mrg /* ubound = lbound + num_images() - 1. */
3263 1.1 mrg tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_num_images,
3264 1.1 mrg 2, integer_zero_node,
3265 1.1 mrg build_int_cst (integer_type_node, -1));
3266 1.1 mrg tmp = fold_build2_loc (input_location, MINUS_EXPR,
3267 1.1 mrg gfc_array_index_type,
3268 1.1 mrg fold_convert (gfc_array_index_type, tmp),
3269 1.1 mrg build_int_cst (gfc_array_index_type, 1));
3270 1.1 mrg resbound = fold_build2_loc (input_location, PLUS_EXPR,
3271 1.1 mrg gfc_array_index_type, resbound, tmp);
3272 1.1 mrg }
3273 1.1 mrg
3274 1.1 mrg if (corank > 1)
3275 1.1 mrg {
3276 1.1 mrg cond = fold_build2_loc (input_location, EQ_EXPR, logical_type_node,
3277 1.1 mrg bound,
3278 1.1 mrg build_int_cst (TREE_TYPE (bound),
3279 1.1 mrg arg->expr->rank + corank - 1));
3280 1.1 mrg
3281 1.1 mrg resbound2 = gfc_conv_descriptor_ubound_get (desc, bound);
3282 1.1 mrg se->expr = fold_build3_loc (input_location, COND_EXPR,
3283 1.1 mrg gfc_array_index_type, cond,
3284 1.1 mrg resbound, resbound2);
3285 1.1 mrg }
3286 1.1 mrg else
3287 1.1 mrg se->expr = resbound;
3288 1.1 mrg }
3289 1.1 mrg else
3290 1.1 mrg se->expr = resbound;
3291 1.1 mrg
3292 1.1 mrg type = gfc_typenode_for_spec (&expr->ts);
3293 1.1 mrg se->expr = convert (type, se->expr);
3294 1.1 mrg }
3295 1.1 mrg
3296 1.1 mrg
3297 1.1 mrg static void
3298 1.1 mrg conv_intrinsic_stride (gfc_se * se, gfc_expr * expr)
3299 1.1 mrg {
3300 1.1 mrg gfc_actual_arglist *array_arg;
3301 1.1 mrg gfc_actual_arglist *dim_arg;
3302 1.1 mrg gfc_se argse;
3303 1.1 mrg tree desc, tmp;
3304 1.1 mrg
3305 1.1 mrg array_arg = expr->value.function.actual;
3306 1.1 mrg dim_arg = array_arg->next;
3307 1.1 mrg
3308 1.1 mrg gcc_assert (array_arg->expr->expr_type == EXPR_VARIABLE);
3309 1.1 mrg
3310 1.1 mrg gfc_init_se (&argse, NULL);
3311 1.1 mrg gfc_conv_expr_descriptor (&argse, array_arg->expr);
3312 1.1 mrg gfc_add_block_to_block (&se->pre, &argse.pre);
3313 1.1 mrg gfc_add_block_to_block (&se->post, &argse.post);
3314 1.1 mrg desc = argse.expr;
3315 1.1 mrg
3316 1.1 mrg gcc_assert (dim_arg->expr);
3317 1.1 mrg gfc_init_se (&argse, NULL);
3318 1.1 mrg gfc_conv_expr_type (&argse, dim_arg->expr, gfc_array_index_type);
3319 1.1 mrg gfc_add_block_to_block (&se->pre, &argse.pre);
3320 1.1 mrg tmp = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
3321 1.1 mrg argse.expr, gfc_index_one_node);
3322 1.1 mrg se->expr = gfc_conv_descriptor_stride_get (desc, tmp);
3323 1.1 mrg }
3324 1.1 mrg
3325 1.1 mrg static void
3326 1.1 mrg gfc_conv_intrinsic_abs (gfc_se * se, gfc_expr * expr)
3327 1.1 mrg {
3328 1.1 mrg tree arg, cabs;
3329 1.1 mrg
3330 1.1 mrg gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
3331 1.1 mrg
3332 1.1 mrg switch (expr->value.function.actual->expr->ts.type)
3333 1.1 mrg {
3334 1.1 mrg case BT_INTEGER:
3335 1.1 mrg case BT_REAL:
3336 1.1 mrg se->expr = fold_build1_loc (input_location, ABS_EXPR, TREE_TYPE (arg),
3337 1.1 mrg arg);
3338 1.1 mrg break;
3339 1.1 mrg
3340 1.1 mrg case BT_COMPLEX:
3341 1.1 mrg cabs = gfc_builtin_decl_for_float_kind (BUILT_IN_CABS, expr->ts.kind);
3342 1.1 mrg se->expr = build_call_expr_loc (input_location, cabs, 1, arg);
3343 1.1 mrg break;
3344 1.1 mrg
3345 1.1 mrg default:
3346 1.1 mrg gcc_unreachable ();
3347 1.1 mrg }
3348 1.1 mrg }
3349 1.1 mrg
3350 1.1 mrg
3351 1.1 mrg /* Create a complex value from one or two real components. */
3352 1.1 mrg
3353 1.1 mrg static void
3354 1.1 mrg gfc_conv_intrinsic_cmplx (gfc_se * se, gfc_expr * expr, int both)
3355 1.1 mrg {
3356 1.1 mrg tree real;
3357 1.1 mrg tree imag;
3358 1.1 mrg tree type;
3359 1.1 mrg tree *args;
3360 1.1 mrg unsigned int num_args;
3361 1.1 mrg
3362 1.1 mrg num_args = gfc_intrinsic_argument_list_length (expr);
3363 1.1 mrg args = XALLOCAVEC (tree, num_args);
3364 1.1 mrg
3365 1.1 mrg type = gfc_typenode_for_spec (&expr->ts);
3366 1.1 mrg gfc_conv_intrinsic_function_args (se, expr, args, num_args);
3367 1.1 mrg real = convert (TREE_TYPE (type), args[0]);
3368 1.1 mrg if (both)
3369 1.1 mrg imag = convert (TREE_TYPE (type), args[1]);
3370 1.1 mrg else if (TREE_CODE (TREE_TYPE (args[0])) == COMPLEX_TYPE)
3371 1.1 mrg {
3372 1.1 mrg imag = fold_build1_loc (input_location, IMAGPART_EXPR,
3373 1.1 mrg TREE_TYPE (TREE_TYPE (args[0])), args[0]);
3374 1.1 mrg imag = convert (TREE_TYPE (type), imag);
3375 1.1 mrg }
3376 1.1 mrg else
3377 1.1 mrg imag = build_real_from_int_cst (TREE_TYPE (type), integer_zero_node);
3378 1.1 mrg
3379 1.1 mrg se->expr = fold_build2_loc (input_location, COMPLEX_EXPR, type, real, imag);
3380 1.1 mrg }
3381 1.1 mrg
3382 1.1 mrg
3383 1.1 mrg /* Remainder function MOD(A, P) = A - INT(A / P) * P
3384 1.1 mrg MODULO(A, P) = A - FLOOR (A / P) * P
3385 1.1 mrg
3386 1.1 mrg The obvious algorithms above are numerically instable for large
3387 1.1 mrg arguments, hence these intrinsics are instead implemented via calls
3388 1.1 mrg to the fmod family of functions. It is the responsibility of the
3389 1.1 mrg user to ensure that the second argument is non-zero. */
3390 1.1 mrg
3391 1.1 mrg static void
3392 1.1 mrg gfc_conv_intrinsic_mod (gfc_se * se, gfc_expr * expr, int modulo)
3393 1.1 mrg {
3394 1.1 mrg tree type;
3395 1.1 mrg tree tmp;
3396 1.1 mrg tree test;
3397 1.1 mrg tree test2;
3398 1.1 mrg tree fmod;
3399 1.1 mrg tree zero;
3400 1.1 mrg tree args[2];
3401 1.1 mrg
3402 1.1 mrg gfc_conv_intrinsic_function_args (se, expr, args, 2);
3403 1.1 mrg
3404 1.1 mrg switch (expr->ts.type)
3405 1.1 mrg {
3406 1.1 mrg case BT_INTEGER:
3407 1.1 mrg /* Integer case is easy, we've got a builtin op. */
3408 1.1 mrg type = TREE_TYPE (args[0]);
3409 1.1 mrg
3410 1.1 mrg if (modulo)
3411 1.1 mrg se->expr = fold_build2_loc (input_location, FLOOR_MOD_EXPR, type,
3412 1.1 mrg args[0], args[1]);
3413 1.1 mrg else
3414 1.1 mrg se->expr = fold_build2_loc (input_location, TRUNC_MOD_EXPR, type,
3415 1.1 mrg args[0], args[1]);
3416 1.1 mrg break;
3417 1.1 mrg
3418 1.1 mrg case BT_REAL:
3419 1.1 mrg fmod = NULL_TREE;
3420 1.1 mrg /* Check if we have a builtin fmod. */
3421 1.1 mrg fmod = gfc_builtin_decl_for_float_kind (BUILT_IN_FMOD, expr->ts.kind);
3422 1.1 mrg
3423 1.1 mrg /* The builtin should always be available. */
3424 1.1 mrg gcc_assert (fmod != NULL_TREE);
3425 1.1 mrg
3426 1.1 mrg tmp = build_addr (fmod);
3427 1.1 mrg se->expr = build_call_array_loc (input_location,
3428 1.1 mrg TREE_TYPE (TREE_TYPE (fmod)),
3429 1.1 mrg tmp, 2, args);
3430 1.1 mrg if (modulo == 0)
3431 1.1 mrg return;
3432 1.1 mrg
3433 1.1 mrg type = TREE_TYPE (args[0]);
3434 1.1 mrg
3435 1.1 mrg args[0] = gfc_evaluate_now (args[0], &se->pre);
3436 1.1 mrg args[1] = gfc_evaluate_now (args[1], &se->pre);
3437 1.1 mrg
3438 1.1 mrg /* Definition:
3439 1.1 mrg modulo = arg - floor (arg/arg2) * arg2
3440 1.1 mrg
3441 1.1 mrg In order to calculate the result accurately, we use the fmod
3442 1.1 mrg function as follows.
3443 1.1 mrg
3444 1.1 mrg res = fmod (arg, arg2);
3445 1.1 mrg if (res)
3446 1.1 mrg {
3447 1.1 mrg if ((arg < 0) xor (arg2 < 0))
3448 1.1 mrg res += arg2;
3449 1.1 mrg }
3450 1.1 mrg else
3451 1.1 mrg res = copysign (0., arg2);
3452 1.1 mrg
3453 1.1 mrg => As two nested ternary exprs:
3454 1.1 mrg
3455 1.1 mrg res = res ? (((arg < 0) xor (arg2 < 0)) ? res + arg2 : res)
3456 1.1 mrg : copysign (0., arg2);
3457 1.1 mrg
3458 1.1 mrg */
3459 1.1 mrg
3460 1.1 mrg zero = gfc_build_const (type, integer_zero_node);
3461 1.1 mrg tmp = gfc_evaluate_now (se->expr, &se->pre);
3462 1.1 mrg if (!flag_signed_zeros)
3463 1.1 mrg {
3464 1.1 mrg test = fold_build2_loc (input_location, LT_EXPR, logical_type_node,
3465 1.1 mrg args[0], zero);
3466 1.1 mrg test2 = fold_build2_loc (input_location, LT_EXPR, logical_type_node,
3467 1.1 mrg args[1], zero);
3468 1.1 mrg test2 = fold_build2_loc (input_location, TRUTH_XOR_EXPR,
3469 1.1 mrg logical_type_node, test, test2);
3470 1.1 mrg test = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
3471 1.1 mrg tmp, zero);
3472 1.1 mrg test = fold_build2_loc (input_location, TRUTH_AND_EXPR,
3473 1.1 mrg logical_type_node, test, test2);
3474 1.1 mrg test = gfc_evaluate_now (test, &se->pre);
3475 1.1 mrg se->expr = fold_build3_loc (input_location, COND_EXPR, type, test,
3476 1.1 mrg fold_build2_loc (input_location,
3477 1.1 mrg PLUS_EXPR,
3478 1.1 mrg type, tmp, args[1]),
3479 1.1 mrg tmp);
3480 1.1 mrg }
3481 1.1 mrg else
3482 1.1 mrg {
3483 1.1 mrg tree expr1, copysign, cscall;
3484 1.1 mrg copysign = gfc_builtin_decl_for_float_kind (BUILT_IN_COPYSIGN,
3485 1.1 mrg expr->ts.kind);
3486 1.1 mrg test = fold_build2_loc (input_location, LT_EXPR, logical_type_node,
3487 1.1 mrg args[0], zero);
3488 1.1 mrg test2 = fold_build2_loc (input_location, LT_EXPR, logical_type_node,
3489 1.1 mrg args[1], zero);
3490 1.1 mrg test2 = fold_build2_loc (input_location, TRUTH_XOR_EXPR,
3491 1.1 mrg logical_type_node, test, test2);
3492 1.1 mrg expr1 = fold_build3_loc (input_location, COND_EXPR, type, test2,
3493 1.1 mrg fold_build2_loc (input_location,
3494 1.1 mrg PLUS_EXPR,
3495 1.1 mrg type, tmp, args[1]),
3496 1.1 mrg tmp);
3497 1.1 mrg test = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
3498 1.1 mrg tmp, zero);
3499 1.1 mrg cscall = build_call_expr_loc (input_location, copysign, 2, zero,
3500 1.1 mrg args[1]);
3501 1.1 mrg se->expr = fold_build3_loc (input_location, COND_EXPR, type, test,
3502 1.1 mrg expr1, cscall);
3503 1.1 mrg }
3504 1.1 mrg return;
3505 1.1 mrg
3506 1.1 mrg default:
3507 1.1 mrg gcc_unreachable ();
3508 1.1 mrg }
3509 1.1 mrg }
3510 1.1 mrg
3511 1.1 mrg /* DSHIFTL(I,J,S) = (I << S) | (J >> (BITSIZE(J) - S))
3512 1.1 mrg DSHIFTR(I,J,S) = (I << (BITSIZE(I) - S)) | (J >> S)
3513 1.1 mrg where the right shifts are logical (i.e. 0's are shifted in).
3514 1.1 mrg Because SHIFT_EXPR's want shifts strictly smaller than the integral
3515 1.1 mrg type width, we have to special-case both S == 0 and S == BITSIZE(J):
3516 1.1 mrg DSHIFTL(I,J,0) = I
3517 1.1 mrg DSHIFTL(I,J,BITSIZE) = J
3518 1.1 mrg DSHIFTR(I,J,0) = J
3519 1.1 mrg DSHIFTR(I,J,BITSIZE) = I. */
3520 1.1 mrg
3521 1.1 mrg static void
3522 1.1 mrg gfc_conv_intrinsic_dshift (gfc_se * se, gfc_expr * expr, bool dshiftl)
3523 1.1 mrg {
3524 1.1 mrg tree type, utype, stype, arg1, arg2, shift, res, left, right;
3525 1.1 mrg tree args[3], cond, tmp;
3526 1.1 mrg int bitsize;
3527 1.1 mrg
3528 1.1 mrg gfc_conv_intrinsic_function_args (se, expr, args, 3);
3529 1.1 mrg
3530 1.1 mrg gcc_assert (TREE_TYPE (args[0]) == TREE_TYPE (args[1]));
3531 1.1 mrg type = TREE_TYPE (args[0]);
3532 1.1 mrg bitsize = TYPE_PRECISION (type);
3533 1.1 mrg utype = unsigned_type_for (type);
3534 1.1 mrg stype = TREE_TYPE (args[2]);
3535 1.1 mrg
3536 1.1 mrg arg1 = gfc_evaluate_now (args[0], &se->pre);
3537 1.1 mrg arg2 = gfc_evaluate_now (args[1], &se->pre);
3538 1.1 mrg shift = gfc_evaluate_now (args[2], &se->pre);
3539 1.1 mrg
3540 1.1 mrg /* The generic case. */
3541 1.1 mrg tmp = fold_build2_loc (input_location, MINUS_EXPR, stype,
3542 1.1 mrg build_int_cst (stype, bitsize), shift);
3543 1.1 mrg left = fold_build2_loc (input_location, LSHIFT_EXPR, type,
3544 1.1 mrg arg1, dshiftl ? shift : tmp);
3545 1.1 mrg
3546 1.1 mrg right = fold_build2_loc (input_location, RSHIFT_EXPR, utype,
3547 1.1 mrg fold_convert (utype, arg2), dshiftl ? tmp : shift);
3548 1.1 mrg right = fold_convert (type, right);
3549 1.1 mrg
3550 1.1 mrg res = fold_build2_loc (input_location, BIT_IOR_EXPR, type, left, right);
3551 1.1 mrg
3552 1.1 mrg /* Special cases. */
3553 1.1 mrg cond = fold_build2_loc (input_location, EQ_EXPR, logical_type_node, shift,
3554 1.1 mrg build_int_cst (stype, 0));
3555 1.1 mrg res = fold_build3_loc (input_location, COND_EXPR, type, cond,
3556 1.1 mrg dshiftl ? arg1 : arg2, res);
3557 1.1 mrg
3558 1.1 mrg cond = fold_build2_loc (input_location, EQ_EXPR, logical_type_node, shift,
3559 1.1 mrg build_int_cst (stype, bitsize));
3560 1.1 mrg res = fold_build3_loc (input_location, COND_EXPR, type, cond,
3561 1.1 mrg dshiftl ? arg2 : arg1, res);
3562 1.1 mrg
3563 1.1 mrg se->expr = res;
3564 1.1 mrg }
3565 1.1 mrg
3566 1.1 mrg
3567 1.1 mrg /* Positive difference DIM (x, y) = ((x - y) < 0) ? 0 : x - y. */
3568 1.1 mrg
3569 1.1 mrg static void
3570 1.1 mrg gfc_conv_intrinsic_dim (gfc_se * se, gfc_expr * expr)
3571 1.1 mrg {
3572 1.1 mrg tree val;
3573 1.1 mrg tree tmp;
3574 1.1 mrg tree type;
3575 1.1 mrg tree zero;
3576 1.1 mrg tree args[2];
3577 1.1 mrg
3578 1.1 mrg gfc_conv_intrinsic_function_args (se, expr, args, 2);
3579 1.1 mrg type = TREE_TYPE (args[0]);
3580 1.1 mrg
3581 1.1 mrg val = fold_build2_loc (input_location, MINUS_EXPR, type, args[0], args[1]);
3582 1.1 mrg val = gfc_evaluate_now (val, &se->pre);
3583 1.1 mrg
3584 1.1 mrg zero = gfc_build_const (type, integer_zero_node);
3585 1.1 mrg tmp = fold_build2_loc (input_location, LE_EXPR, logical_type_node, val, zero);
3586 1.1 mrg se->expr = fold_build3_loc (input_location, COND_EXPR, type, tmp, zero, val);
3587 1.1 mrg }
3588 1.1 mrg
3589 1.1 mrg
3590 1.1 mrg /* SIGN(A, B) is absolute value of A times sign of B.
3591 1.1 mrg The real value versions use library functions to ensure the correct
3592 1.1 mrg handling of negative zero. Integer case implemented as:
3593 1.1 mrg SIGN(A, B) = { tmp = (A ^ B) >> C; (A + tmp) ^ tmp }
3594 1.1 mrg */
3595 1.1 mrg
3596 1.1 mrg static void
3597 1.1 mrg gfc_conv_intrinsic_sign (gfc_se * se, gfc_expr * expr)
3598 1.1 mrg {
3599 1.1 mrg tree tmp;
3600 1.1 mrg tree type;
3601 1.1 mrg tree args[2];
3602 1.1 mrg
3603 1.1 mrg gfc_conv_intrinsic_function_args (se, expr, args, 2);
3604 1.1 mrg if (expr->ts.type == BT_REAL)
3605 1.1 mrg {
3606 1.1 mrg tree abs;
3607 1.1 mrg
3608 1.1 mrg tmp = gfc_builtin_decl_for_float_kind (BUILT_IN_COPYSIGN, expr->ts.kind);
3609 1.1 mrg abs = gfc_builtin_decl_for_float_kind (BUILT_IN_FABS, expr->ts.kind);
3610 1.1 mrg
3611 1.1 mrg /* We explicitly have to ignore the minus sign. We do so by using
3612 1.1 mrg result = (arg1 == 0) ? abs(arg0) : copysign(arg0, arg1). */
3613 1.1 mrg if (!flag_sign_zero
3614 1.1 mrg && MODE_HAS_SIGNED_ZEROS (TYPE_MODE (TREE_TYPE (args[1]))))
3615 1.1 mrg {
3616 1.1 mrg tree cond, zero;
3617 1.1 mrg zero = build_real_from_int_cst (TREE_TYPE (args[1]), integer_zero_node);
3618 1.1 mrg cond = fold_build2_loc (input_location, EQ_EXPR, logical_type_node,
3619 1.1 mrg args[1], zero);
3620 1.1 mrg se->expr = fold_build3_loc (input_location, COND_EXPR,
3621 1.1 mrg TREE_TYPE (args[0]), cond,
3622 1.1 mrg build_call_expr_loc (input_location, abs, 1,
3623 1.1 mrg args[0]),
3624 1.1 mrg build_call_expr_loc (input_location, tmp, 2,
3625 1.1 mrg args[0], args[1]));
3626 1.1 mrg }
3627 1.1 mrg else
3628 1.1 mrg se->expr = build_call_expr_loc (input_location, tmp, 2,
3629 1.1 mrg args[0], args[1]);
3630 1.1 mrg return;
3631 1.1 mrg }
3632 1.1 mrg
3633 1.1 mrg /* Having excluded floating point types, we know we are now dealing
3634 1.1 mrg with signed integer types. */
3635 1.1 mrg type = TREE_TYPE (args[0]);
3636 1.1 mrg
3637 1.1 mrg /* Args[0] is used multiple times below. */
3638 1.1 mrg args[0] = gfc_evaluate_now (args[0], &se->pre);
3639 1.1 mrg
3640 1.1 mrg /* Construct (A ^ B) >> 31, which generates a bit mask of all zeros if
3641 1.1 mrg the signs of A and B are the same, and of all ones if they differ. */
3642 1.1 mrg tmp = fold_build2_loc (input_location, BIT_XOR_EXPR, type, args[0], args[1]);
3643 1.1 mrg tmp = fold_build2_loc (input_location, RSHIFT_EXPR, type, tmp,
3644 1.1 mrg build_int_cst (type, TYPE_PRECISION (type) - 1));
3645 1.1 mrg tmp = gfc_evaluate_now (tmp, &se->pre);
3646 1.1 mrg
3647 1.1 mrg /* Construct (A + tmp) ^ tmp, which is A if tmp is zero, and -A if tmp]
3648 1.1 mrg is all ones (i.e. -1). */
3649 1.1 mrg se->expr = fold_build2_loc (input_location, BIT_XOR_EXPR, type,
3650 1.1 mrg fold_build2_loc (input_location, PLUS_EXPR,
3651 1.1 mrg type, args[0], tmp), tmp);
3652 1.1 mrg }
3653 1.1 mrg
3654 1.1 mrg
3655 1.1 mrg /* Test for the presence of an optional argument. */
3656 1.1 mrg
3657 1.1 mrg static void
3658 1.1 mrg gfc_conv_intrinsic_present (gfc_se * se, gfc_expr * expr)
3659 1.1 mrg {
3660 1.1 mrg gfc_expr *arg;
3661 1.1 mrg
3662 1.1 mrg arg = expr->value.function.actual->expr;
3663 1.1 mrg gcc_assert (arg->expr_type == EXPR_VARIABLE);
3664 1.1 mrg se->expr = gfc_conv_expr_present (arg->symtree->n.sym);
3665 1.1 mrg se->expr = convert (gfc_typenode_for_spec (&expr->ts), se->expr);
3666 1.1 mrg }
3667 1.1 mrg
3668 1.1 mrg
3669 1.1 mrg /* Calculate the double precision product of two single precision values. */
3670 1.1 mrg
3671 1.1 mrg static void
3672 1.1 mrg gfc_conv_intrinsic_dprod (gfc_se * se, gfc_expr * expr)
3673 1.1 mrg {
3674 1.1 mrg tree type;
3675 1.1 mrg tree args[2];
3676 1.1 mrg
3677 1.1 mrg gfc_conv_intrinsic_function_args (se, expr, args, 2);
3678 1.1 mrg
3679 1.1 mrg /* Convert the args to double precision before multiplying. */
3680 1.1 mrg type = gfc_typenode_for_spec (&expr->ts);
3681 1.1 mrg args[0] = convert (type, args[0]);
3682 1.1 mrg args[1] = convert (type, args[1]);
3683 1.1 mrg se->expr = fold_build2_loc (input_location, MULT_EXPR, type, args[0],
3684 1.1 mrg args[1]);
3685 1.1 mrg }
3686 1.1 mrg
3687 1.1 mrg
3688 1.1 mrg /* Return a length one character string containing an ascii character. */
3689 1.1 mrg
3690 1.1 mrg static void
3691 1.1 mrg gfc_conv_intrinsic_char (gfc_se * se, gfc_expr * expr)
3692 1.1 mrg {
3693 1.1 mrg tree arg[2];
3694 1.1 mrg tree var;
3695 1.1 mrg tree type;
3696 1.1 mrg unsigned int num_args;
3697 1.1 mrg
3698 1.1 mrg num_args = gfc_intrinsic_argument_list_length (expr);
3699 1.1 mrg gfc_conv_intrinsic_function_args (se, expr, arg, num_args);
3700 1.1 mrg
3701 1.1 mrg type = gfc_get_char_type (expr->ts.kind);
3702 1.1 mrg var = gfc_create_var (type, "char");
3703 1.1 mrg
3704 1.1 mrg arg[0] = fold_build1_loc (input_location, NOP_EXPR, type, arg[0]);
3705 1.1 mrg gfc_add_modify (&se->pre, var, arg[0]);
3706 1.1 mrg se->expr = gfc_build_addr_expr (build_pointer_type (type), var);
3707 1.1 mrg se->string_length = build_int_cst (gfc_charlen_type_node, 1);
3708 1.1 mrg }
3709 1.1 mrg
3710 1.1 mrg
3711 1.1 mrg static void
3712 1.1 mrg gfc_conv_intrinsic_ctime (gfc_se * se, gfc_expr * expr)
3713 1.1 mrg {
3714 1.1 mrg tree var;
3715 1.1 mrg tree len;
3716 1.1 mrg tree tmp;
3717 1.1 mrg tree cond;
3718 1.1 mrg tree fndecl;
3719 1.1 mrg tree *args;
3720 1.1 mrg unsigned int num_args;
3721 1.1 mrg
3722 1.1 mrg num_args = gfc_intrinsic_argument_list_length (expr) + 2;
3723 1.1 mrg args = XALLOCAVEC (tree, num_args);
3724 1.1 mrg
3725 1.1 mrg var = gfc_create_var (pchar_type_node, "pstr");
3726 1.1 mrg len = gfc_create_var (gfc_charlen_type_node, "len");
3727 1.1 mrg
3728 1.1 mrg gfc_conv_intrinsic_function_args (se, expr, &args[2], num_args - 2);
3729 1.1 mrg args[0] = gfc_build_addr_expr (NULL_TREE, var);
3730 1.1 mrg args[1] = gfc_build_addr_expr (NULL_TREE, len);
3731 1.1 mrg
3732 1.1 mrg fndecl = build_addr (gfor_fndecl_ctime);
3733 1.1 mrg tmp = build_call_array_loc (input_location,
3734 1.1 mrg TREE_TYPE (TREE_TYPE (gfor_fndecl_ctime)),
3735 1.1 mrg fndecl, num_args, args);
3736 1.1 mrg gfc_add_expr_to_block (&se->pre, tmp);
3737 1.1 mrg
3738 1.1 mrg /* Free the temporary afterwards, if necessary. */
3739 1.1 mrg cond = fold_build2_loc (input_location, GT_EXPR, logical_type_node,
3740 1.1 mrg len, build_int_cst (TREE_TYPE (len), 0));
3741 1.1 mrg tmp = gfc_call_free (var);
3742 1.1 mrg tmp = build3_v (COND_EXPR, cond, tmp, build_empty_stmt (input_location));
3743 1.1 mrg gfc_add_expr_to_block (&se->post, tmp);
3744 1.1 mrg
3745 1.1 mrg se->expr = var;
3746 1.1 mrg se->string_length = len;
3747 1.1 mrg }
3748 1.1 mrg
3749 1.1 mrg
3750 1.1 mrg static void
3751 1.1 mrg gfc_conv_intrinsic_fdate (gfc_se * se, gfc_expr * expr)
3752 1.1 mrg {
3753 1.1 mrg tree var;
3754 1.1 mrg tree len;
3755 1.1 mrg tree tmp;
3756 1.1 mrg tree cond;
3757 1.1 mrg tree fndecl;
3758 1.1 mrg tree *args;
3759 1.1 mrg unsigned int num_args;
3760 1.1 mrg
3761 1.1 mrg num_args = gfc_intrinsic_argument_list_length (expr) + 2;
3762 1.1 mrg args = XALLOCAVEC (tree, num_args);
3763 1.1 mrg
3764 1.1 mrg var = gfc_create_var (pchar_type_node, "pstr");
3765 1.1 mrg len = gfc_create_var (gfc_charlen_type_node, "len");
3766 1.1 mrg
3767 1.1 mrg gfc_conv_intrinsic_function_args (se, expr, &args[2], num_args - 2);
3768 1.1 mrg args[0] = gfc_build_addr_expr (NULL_TREE, var);
3769 1.1 mrg args[1] = gfc_build_addr_expr (NULL_TREE, len);
3770 1.1 mrg
3771 1.1 mrg fndecl = build_addr (gfor_fndecl_fdate);
3772 1.1 mrg tmp = build_call_array_loc (input_location,
3773 1.1 mrg TREE_TYPE (TREE_TYPE (gfor_fndecl_fdate)),
3774 1.1 mrg fndecl, num_args, args);
3775 1.1 mrg gfc_add_expr_to_block (&se->pre, tmp);
3776 1.1 mrg
3777 1.1 mrg /* Free the temporary afterwards, if necessary. */
3778 1.1 mrg cond = fold_build2_loc (input_location, GT_EXPR, logical_type_node,
3779 1.1 mrg len, build_int_cst (TREE_TYPE (len), 0));
3780 1.1 mrg tmp = gfc_call_free (var);
3781 1.1 mrg tmp = build3_v (COND_EXPR, cond, tmp, build_empty_stmt (input_location));
3782 1.1 mrg gfc_add_expr_to_block (&se->post, tmp);
3783 1.1 mrg
3784 1.1 mrg se->expr = var;
3785 1.1 mrg se->string_length = len;
3786 1.1 mrg }
3787 1.1 mrg
3788 1.1 mrg
3789 1.1 mrg /* Generate a direct call to free() for the FREE subroutine. */
3790 1.1 mrg
3791 1.1 mrg static tree
3792 1.1 mrg conv_intrinsic_free (gfc_code *code)
3793 1.1 mrg {
3794 1.1 mrg stmtblock_t block;
3795 1.1 mrg gfc_se argse;
3796 1.1 mrg tree arg, call;
3797 1.1 mrg
3798 1.1 mrg gfc_init_se (&argse, NULL);
3799 1.1 mrg gfc_conv_expr (&argse, code->ext.actual->expr);
3800 1.1 mrg arg = fold_convert (ptr_type_node, argse.expr);
3801 1.1 mrg
3802 1.1 mrg gfc_init_block (&block);
3803 1.1 mrg call = build_call_expr_loc (input_location,
3804 1.1 mrg builtin_decl_explicit (BUILT_IN_FREE), 1, arg);
3805 1.1 mrg gfc_add_expr_to_block (&block, call);
3806 1.1 mrg return gfc_finish_block (&block);
3807 1.1 mrg }
3808 1.1 mrg
3809 1.1 mrg
3810 1.1 mrg /* Call the RANDOM_INIT library subroutine with a hidden argument for
3811 1.1 mrg handling seeding on coarray images. */
3812 1.1 mrg
3813 1.1 mrg static tree
3814 1.1 mrg conv_intrinsic_random_init (gfc_code *code)
3815 1.1 mrg {
3816 1.1 mrg stmtblock_t block;
3817 1.1 mrg gfc_se se;
3818 1.1 mrg tree arg1, arg2, tmp;
3819 1.1 mrg /* On none coarray == lib compiles use LOGICAL(4) else regular LOGICAL. */
3820 1.1 mrg tree used_bool_type_node = flag_coarray == GFC_FCOARRAY_LIB
3821 1.1 mrg ? logical_type_node
3822 1.1 mrg : gfc_get_logical_type (4);
3823 1.1 mrg
3824 1.1 mrg /* Make the function call. */
3825 1.1 mrg gfc_init_block (&block);
3826 1.1 mrg gfc_init_se (&se, NULL);
3827 1.1 mrg
3828 1.1 mrg /* Convert REPEATABLE to the desired LOGICAL entity. */
3829 1.1 mrg gfc_conv_expr (&se, code->ext.actual->expr);
3830 1.1 mrg gfc_add_block_to_block (&block, &se.pre);
3831 1.1 mrg arg1 = fold_convert (used_bool_type_node, gfc_evaluate_now (se.expr, &block));
3832 1.1 mrg gfc_add_block_to_block (&block, &se.post);
3833 1.1 mrg
3834 1.1 mrg /* Convert IMAGE_DISTINCT to the desired LOGICAL entity. */
3835 1.1 mrg gfc_conv_expr (&se, code->ext.actual->next->expr);
3836 1.1 mrg gfc_add_block_to_block (&block, &se.pre);
3837 1.1 mrg arg2 = fold_convert (used_bool_type_node, gfc_evaluate_now (se.expr, &block));
3838 1.1 mrg gfc_add_block_to_block (&block, &se.post);
3839 1.1 mrg
3840 1.1 mrg if (flag_coarray == GFC_FCOARRAY_LIB)
3841 1.1 mrg {
3842 1.1 mrg tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_random_init,
3843 1.1 mrg 2, arg1, arg2);
3844 1.1 mrg }
3845 1.1 mrg else
3846 1.1 mrg {
3847 1.1 mrg /* The ABI for libgfortran needs to be maintained, so a hidden
3848 1.1 mrg argument must be include if code is compiled with -fcoarray=single
3849 1.1 mrg or without the option. Set to 0. */
3850 1.1 mrg tree arg3 = build_int_cst (gfc_get_int_type (4), 0);
3851 1.1 mrg tmp = build_call_expr_loc (input_location, gfor_fndecl_random_init,
3852 1.1 mrg 3, arg1, arg2, arg3);
3853 1.1 mrg }
3854 1.1 mrg
3855 1.1 mrg gfc_add_expr_to_block (&block, tmp);
3856 1.1 mrg
3857 1.1 mrg return gfc_finish_block (&block);
3858 1.1 mrg }
3859 1.1 mrg
3860 1.1 mrg
3861 1.1 mrg /* Call the SYSTEM_CLOCK library functions, handling the type and kind
3862 1.1 mrg conversions. */
3863 1.1 mrg
3864 1.1 mrg static tree
3865 1.1 mrg conv_intrinsic_system_clock (gfc_code *code)
3866 1.1 mrg {
3867 1.1 mrg stmtblock_t block;
3868 1.1 mrg gfc_se count_se, count_rate_se, count_max_se;
3869 1.1 mrg tree arg1 = NULL_TREE, arg2 = NULL_TREE, arg3 = NULL_TREE;
3870 1.1 mrg tree tmp;
3871 1.1 mrg int least;
3872 1.1 mrg
3873 1.1 mrg gfc_expr *count = code->ext.actual->expr;
3874 1.1 mrg gfc_expr *count_rate = code->ext.actual->next->expr;
3875 1.1 mrg gfc_expr *count_max = code->ext.actual->next->next->expr;
3876 1.1 mrg
3877 1.1 mrg /* Evaluate our arguments. */
3878 1.1 mrg if (count)
3879 1.1 mrg {
3880 1.1 mrg gfc_init_se (&count_se, NULL);
3881 1.1 mrg gfc_conv_expr (&count_se, count);
3882 1.1 mrg }
3883 1.1 mrg
3884 1.1 mrg if (count_rate)
3885 1.1 mrg {
3886 1.1 mrg gfc_init_se (&count_rate_se, NULL);
3887 1.1 mrg gfc_conv_expr (&count_rate_se, count_rate);
3888 1.1 mrg }
3889 1.1 mrg
3890 1.1 mrg if (count_max)
3891 1.1 mrg {
3892 1.1 mrg gfc_init_se (&count_max_se, NULL);
3893 1.1 mrg gfc_conv_expr (&count_max_se, count_max);
3894 1.1 mrg }
3895 1.1 mrg
3896 1.1 mrg /* Find the smallest kind found of the arguments. */
3897 1.1 mrg least = 16;
3898 1.1 mrg least = (count && count->ts.kind < least) ? count->ts.kind : least;
3899 1.1 mrg least = (count_rate && count_rate->ts.kind < least) ? count_rate->ts.kind
3900 1.1 mrg : least;
3901 1.1 mrg least = (count_max && count_max->ts.kind < least) ? count_max->ts.kind
3902 1.1 mrg : least;
3903 1.1 mrg
3904 1.1 mrg /* Prepare temporary variables. */
3905 1.1 mrg
3906 1.1 mrg if (count)
3907 1.1 mrg {
3908 1.1 mrg if (least >= 8)
3909 1.1 mrg arg1 = gfc_create_var (gfc_get_int_type (8), "count");
3910 1.1 mrg else if (least == 4)
3911 1.1 mrg arg1 = gfc_create_var (gfc_get_int_type (4), "count");
3912 1.1 mrg else if (count->ts.kind == 1)
3913 1.1 mrg arg1 = gfc_conv_mpz_to_tree (gfc_integer_kinds[0].pedantic_min_int,
3914 1.1 mrg count->ts.kind);
3915 1.1 mrg else
3916 1.1 mrg arg1 = gfc_conv_mpz_to_tree (gfc_integer_kinds[1].pedantic_min_int,
3917 1.1 mrg count->ts.kind);
3918 1.1 mrg }
3919 1.1 mrg
3920 1.1 mrg if (count_rate)
3921 1.1 mrg {
3922 1.1 mrg if (least >= 8)
3923 1.1 mrg arg2 = gfc_create_var (gfc_get_int_type (8), "count_rate");
3924 1.1 mrg else if (least == 4)
3925 1.1 mrg arg2 = gfc_create_var (gfc_get_int_type (4), "count_rate");
3926 1.1 mrg else
3927 1.1 mrg arg2 = integer_zero_node;
3928 1.1 mrg }
3929 1.1 mrg
3930 1.1 mrg if (count_max)
3931 1.1 mrg {
3932 1.1 mrg if (least >= 8)
3933 1.1 mrg arg3 = gfc_create_var (gfc_get_int_type (8), "count_max");
3934 1.1 mrg else if (least == 4)
3935 1.1 mrg arg3 = gfc_create_var (gfc_get_int_type (4), "count_max");
3936 1.1 mrg else
3937 1.1 mrg arg3 = integer_zero_node;
3938 1.1 mrg }
3939 1.1 mrg
3940 1.1 mrg /* Make the function call. */
3941 1.1 mrg gfc_init_block (&block);
3942 1.1 mrg
3943 1.1 mrg if (least <= 2)
3944 1.1 mrg {
3945 1.1 mrg if (least == 1)
3946 1.1 mrg {
3947 1.1 mrg arg1 ? gfc_build_addr_expr (NULL_TREE, arg1)
3948 1.1 mrg : null_pointer_node;
3949 1.1 mrg arg2 ? gfc_build_addr_expr (NULL_TREE, arg2)
3950 1.1 mrg : null_pointer_node;
3951 1.1 mrg arg3 ? gfc_build_addr_expr (NULL_TREE, arg3)
3952 1.1 mrg : null_pointer_node;
3953 1.1 mrg }
3954 1.1 mrg
3955 1.1 mrg if (least == 2)
3956 1.1 mrg {
3957 1.1 mrg arg1 ? gfc_build_addr_expr (NULL_TREE, arg1)
3958 1.1 mrg : null_pointer_node;
3959 1.1 mrg arg2 ? gfc_build_addr_expr (NULL_TREE, arg2)
3960 1.1 mrg : null_pointer_node;
3961 1.1 mrg arg3 ? gfc_build_addr_expr (NULL_TREE, arg3)
3962 1.1 mrg : null_pointer_node;
3963 1.1 mrg }
3964 1.1 mrg }
3965 1.1 mrg else
3966 1.1 mrg {
3967 1.1 mrg if (least == 4)
3968 1.1 mrg {
3969 1.1 mrg tmp = build_call_expr_loc (input_location,
3970 1.1 mrg gfor_fndecl_system_clock4, 3,
3971 1.1 mrg arg1 ? gfc_build_addr_expr (NULL_TREE, arg1)
3972 1.1 mrg : null_pointer_node,
3973 1.1 mrg arg2 ? gfc_build_addr_expr (NULL_TREE, arg2)
3974 1.1 mrg : null_pointer_node,
3975 1.1 mrg arg3 ? gfc_build_addr_expr (NULL_TREE, arg3)
3976 1.1 mrg : null_pointer_node);
3977 1.1 mrg gfc_add_expr_to_block (&block, tmp);
3978 1.1 mrg }
3979 1.1 mrg /* Handle kind>=8, 10, or 16 arguments */
3980 1.1 mrg if (least >= 8)
3981 1.1 mrg {
3982 1.1 mrg tmp = build_call_expr_loc (input_location,
3983 1.1 mrg gfor_fndecl_system_clock8, 3,
3984 1.1 mrg arg1 ? gfc_build_addr_expr (NULL_TREE, arg1)
3985 1.1 mrg : null_pointer_node,
3986 1.1 mrg arg2 ? gfc_build_addr_expr (NULL_TREE, arg2)
3987 1.1 mrg : null_pointer_node,
3988 1.1 mrg arg3 ? gfc_build_addr_expr (NULL_TREE, arg3)
3989 1.1 mrg : null_pointer_node);
3990 1.1 mrg gfc_add_expr_to_block (&block, tmp);
3991 1.1 mrg }
3992 1.1 mrg }
3993 1.1 mrg
3994 1.1 mrg /* And store values back if needed. */
3995 1.1 mrg if (arg1 && arg1 != count_se.expr)
3996 1.1 mrg gfc_add_modify (&block, count_se.expr,
3997 1.1 mrg fold_convert (TREE_TYPE (count_se.expr), arg1));
3998 1.1 mrg if (arg2 && arg2 != count_rate_se.expr)
3999 1.1 mrg gfc_add_modify (&block, count_rate_se.expr,
4000 1.1 mrg fold_convert (TREE_TYPE (count_rate_se.expr), arg2));
4001 1.1 mrg if (arg3 && arg3 != count_max_se.expr)
4002 1.1 mrg gfc_add_modify (&block, count_max_se.expr,
4003 1.1 mrg fold_convert (TREE_TYPE (count_max_se.expr), arg3));
4004 1.1 mrg
4005 1.1 mrg return gfc_finish_block (&block);
4006 1.1 mrg }
4007 1.1 mrg
4008 1.1 mrg
4009 1.1 mrg /* Return a character string containing the tty name. */
4010 1.1 mrg
4011 1.1 mrg static void
4012 1.1 mrg gfc_conv_intrinsic_ttynam (gfc_se * se, gfc_expr * expr)
4013 1.1 mrg {
4014 1.1 mrg tree var;
4015 1.1 mrg tree len;
4016 1.1 mrg tree tmp;
4017 1.1 mrg tree cond;
4018 1.1 mrg tree fndecl;
4019 1.1 mrg tree *args;
4020 1.1 mrg unsigned int num_args;
4021 1.1 mrg
4022 1.1 mrg num_args = gfc_intrinsic_argument_list_length (expr) + 2;
4023 1.1 mrg args = XALLOCAVEC (tree, num_args);
4024 1.1 mrg
4025 1.1 mrg var = gfc_create_var (pchar_type_node, "pstr");
4026 1.1 mrg len = gfc_create_var (gfc_charlen_type_node, "len");
4027 1.1 mrg
4028 1.1 mrg gfc_conv_intrinsic_function_args (se, expr, &args[2], num_args - 2);
4029 1.1 mrg args[0] = gfc_build_addr_expr (NULL_TREE, var);
4030 1.1 mrg args[1] = gfc_build_addr_expr (NULL_TREE, len);
4031 1.1 mrg
4032 1.1 mrg fndecl = build_addr (gfor_fndecl_ttynam);
4033 1.1 mrg tmp = build_call_array_loc (input_location,
4034 1.1 mrg TREE_TYPE (TREE_TYPE (gfor_fndecl_ttynam)),
4035 1.1 mrg fndecl, num_args, args);
4036 1.1 mrg gfc_add_expr_to_block (&se->pre, tmp);
4037 1.1 mrg
4038 1.1 mrg /* Free the temporary afterwards, if necessary. */
4039 1.1 mrg cond = fold_build2_loc (input_location, GT_EXPR, logical_type_node,
4040 1.1 mrg len, build_int_cst (TREE_TYPE (len), 0));
4041 1.1 mrg tmp = gfc_call_free (var);
4042 1.1 mrg tmp = build3_v (COND_EXPR, cond, tmp, build_empty_stmt (input_location));
4043 1.1 mrg gfc_add_expr_to_block (&se->post, tmp);
4044 1.1 mrg
4045 1.1 mrg se->expr = var;
4046 1.1 mrg se->string_length = len;
4047 1.1 mrg }
4048 1.1 mrg
4049 1.1 mrg
4050 1.1 mrg /* Get the minimum/maximum value of all the parameters.
4051 1.1 mrg minmax (a1, a2, a3, ...)
4052 1.1 mrg {
4053 1.1 mrg mvar = a1;
4054 1.1 mrg mvar = COMP (mvar, a2)
4055 1.1 mrg mvar = COMP (mvar, a3)
4056 1.1 mrg ...
4057 1.1 mrg return mvar;
4058 1.1 mrg }
4059 1.1 mrg Where COMP is MIN/MAX_EXPR for integral types or when we don't
4060 1.1 mrg care about NaNs, or IFN_FMIN/MAX when the target has support for
4061 1.1 mrg fast NaN-honouring min/max. When neither holds expand a sequence
4062 1.1 mrg of explicit comparisons. */
4063 1.1 mrg
4064 1.1 mrg /* TODO: Mismatching types can occur when specific names are used.
4065 1.1 mrg These should be handled during resolution. */
4066 1.1 mrg static void
4067 1.1 mrg gfc_conv_intrinsic_minmax (gfc_se * se, gfc_expr * expr, enum tree_code op)
4068 1.1 mrg {
4069 1.1 mrg tree tmp;
4070 1.1 mrg tree mvar;
4071 1.1 mrg tree val;
4072 1.1 mrg tree *args;
4073 1.1 mrg tree type;
4074 1.1 mrg tree argtype;
4075 1.1 mrg gfc_actual_arglist *argexpr;
4076 1.1 mrg unsigned int i, nargs;
4077 1.1 mrg
4078 1.1 mrg nargs = gfc_intrinsic_argument_list_length (expr);
4079 1.1 mrg args = XALLOCAVEC (tree, nargs);
4080 1.1 mrg
4081 1.1 mrg gfc_conv_intrinsic_function_args (se, expr, args, nargs);
4082 1.1 mrg type = gfc_typenode_for_spec (&expr->ts);
4083 1.1 mrg
4084 1.1 mrg /* Only evaluate the argument once. */
4085 1.1 mrg if (!VAR_P (args[0]) && !TREE_CONSTANT (args[0]))
4086 1.1 mrg args[0] = gfc_evaluate_now (args[0], &se->pre);
4087 1.1 mrg
4088 1.1 mrg /* Determine suitable type of temporary, as a GNU extension allows
4089 1.1 mrg different argument kinds. */
4090 1.1 mrg argtype = TREE_TYPE (args[0]);
4091 1.1 mrg argexpr = expr->value.function.actual;
4092 1.1 mrg for (i = 1, argexpr = argexpr->next; i < nargs; i++, argexpr = argexpr->next)
4093 1.1 mrg {
4094 1.1 mrg tree tmptype = TREE_TYPE (args[i]);
4095 1.1 mrg if (TYPE_PRECISION (tmptype) > TYPE_PRECISION (argtype))
4096 1.1 mrg argtype = tmptype;
4097 1.1 mrg }
4098 1.1 mrg mvar = gfc_create_var (argtype, "M");
4099 1.1 mrg gfc_add_modify (&se->pre, mvar, convert (argtype, args[0]));
4100 1.1 mrg
4101 1.1 mrg argexpr = expr->value.function.actual;
4102 1.1 mrg for (i = 1, argexpr = argexpr->next; i < nargs; i++, argexpr = argexpr->next)
4103 1.1 mrg {
4104 1.1 mrg tree cond = NULL_TREE;
4105 1.1 mrg val = args[i];
4106 1.1 mrg
4107 1.1 mrg /* Handle absent optional arguments by ignoring the comparison. */
4108 1.1 mrg if (argexpr->expr->expr_type == EXPR_VARIABLE
4109 1.1 mrg && argexpr->expr->symtree->n.sym->attr.optional
4110 1.1 mrg && TREE_CODE (val) == INDIRECT_REF)
4111 1.1 mrg {
4112 1.1 mrg cond = fold_build2_loc (input_location,
4113 1.1 mrg NE_EXPR, logical_type_node,
4114 1.1 mrg TREE_OPERAND (val, 0),
4115 1.1 mrg build_int_cst (TREE_TYPE (TREE_OPERAND (val, 0)), 0));
4116 1.1 mrg }
4117 1.1 mrg else if (!VAR_P (val) && !TREE_CONSTANT (val))
4118 1.1 mrg /* Only evaluate the argument once. */
4119 1.1 mrg val = gfc_evaluate_now (val, &se->pre);
4120 1.1 mrg
4121 1.1 mrg tree calc;
4122 1.1 mrg /* For floating point types, the question is what MAX(a, NaN) or
4123 1.1 mrg MIN(a, NaN) should return (where "a" is a normal number).
4124 1.1 mrg There are valid usecase for returning either one, but the
4125 1.1 mrg Fortran standard doesn't specify which one should be chosen.
4126 1.1 mrg Also, there is no consensus among other tested compilers. In
4127 1.1 mrg short, it's a mess. So lets just do whatever is fastest. */
4128 1.1 mrg tree_code code = op == GT_EXPR ? MAX_EXPR : MIN_EXPR;
4129 1.1 mrg calc = fold_build2_loc (input_location, code, argtype,
4130 1.1 mrg convert (argtype, val), mvar);
4131 1.1 mrg tmp = build2_v (MODIFY_EXPR, mvar, calc);
4132 1.1 mrg
4133 1.1 mrg if (cond != NULL_TREE)
4134 1.1 mrg tmp = build3_v (COND_EXPR, cond, tmp,
4135 1.1 mrg build_empty_stmt (input_location));
4136 1.1 mrg gfc_add_expr_to_block (&se->pre, tmp);
4137 1.1 mrg }
4138 1.1 mrg se->expr = convert (type, mvar);
4139 1.1 mrg }
4140 1.1 mrg
4141 1.1 mrg
4142 1.1 mrg /* Generate library calls for MIN and MAX intrinsics for character
4143 1.1 mrg variables. */
4144 1.1 mrg static void
4145 1.1 mrg gfc_conv_intrinsic_minmax_char (gfc_se * se, gfc_expr * expr, int op)
4146 1.1 mrg {
4147 1.1 mrg tree *args;
4148 1.1 mrg tree var, len, fndecl, tmp, cond, function;
4149 1.1 mrg unsigned int nargs;
4150 1.1 mrg
4151 1.1 mrg nargs = gfc_intrinsic_argument_list_length (expr);
4152 1.1 mrg args = XALLOCAVEC (tree, nargs + 4);
4153 1.1 mrg gfc_conv_intrinsic_function_args (se, expr, &args[4], nargs);
4154 1.1 mrg
4155 1.1 mrg /* Create the result variables. */
4156 1.1 mrg len = gfc_create_var (gfc_charlen_type_node, "len");
4157 1.1 mrg args[0] = gfc_build_addr_expr (NULL_TREE, len);
4158 1.1 mrg var = gfc_create_var (gfc_get_pchar_type (expr->ts.kind), "pstr");
4159 1.1 mrg args[1] = gfc_build_addr_expr (ppvoid_type_node, var);
4160 1.1 mrg args[2] = build_int_cst (integer_type_node, op);
4161 1.1 mrg args[3] = build_int_cst (integer_type_node, nargs / 2);
4162 1.1 mrg
4163 1.1 mrg if (expr->ts.kind == 1)
4164 1.1 mrg function = gfor_fndecl_string_minmax;
4165 1.1 mrg else if (expr->ts.kind == 4)
4166 1.1 mrg function = gfor_fndecl_string_minmax_char4;
4167 1.1 mrg else
4168 1.1 mrg gcc_unreachable ();
4169 1.1 mrg
4170 1.1 mrg /* Make the function call. */
4171 1.1 mrg fndecl = build_addr (function);
4172 1.1 mrg tmp = build_call_array_loc (input_location,
4173 1.1 mrg TREE_TYPE (TREE_TYPE (function)), fndecl,
4174 1.1 mrg nargs + 4, args);
4175 1.1 mrg gfc_add_expr_to_block (&se->pre, tmp);
4176 1.1 mrg
4177 1.1 mrg /* Free the temporary afterwards, if necessary. */
4178 1.1 mrg cond = fold_build2_loc (input_location, GT_EXPR, logical_type_node,
4179 1.1 mrg len, build_int_cst (TREE_TYPE (len), 0));
4180 1.1 mrg tmp = gfc_call_free (var);
4181 1.1 mrg tmp = build3_v (COND_EXPR, cond, tmp, build_empty_stmt (input_location));
4182 1.1 mrg gfc_add_expr_to_block (&se->post, tmp);
4183 1.1 mrg
4184 1.1 mrg se->expr = var;
4185 1.1 mrg se->string_length = len;
4186 1.1 mrg }
4187 1.1 mrg
4188 1.1 mrg
4189 1.1 mrg /* Create a symbol node for this intrinsic. The symbol from the frontend
4190 1.1 mrg has the generic name. */
4191 1.1 mrg
4192 1.1 mrg static gfc_symbol *
4193 1.1 mrg gfc_get_symbol_for_expr (gfc_expr * expr, bool ignore_optional)
4194 1.1 mrg {
4195 1.1 mrg gfc_symbol *sym;
4196 1.1 mrg
4197 1.1 mrg /* TODO: Add symbols for intrinsic function to the global namespace. */
4198 1.1 mrg gcc_assert (strlen (expr->value.function.name) <= GFC_MAX_SYMBOL_LEN - 5);
4199 1.1 mrg sym = gfc_new_symbol (expr->value.function.name, NULL);
4200 1.1 mrg
4201 1.1 mrg sym->ts = expr->ts;
4202 1.1 mrg sym->attr.external = 1;
4203 1.1 mrg sym->attr.function = 1;
4204 1.1 mrg sym->attr.always_explicit = 1;
4205 1.1 mrg sym->attr.proc = PROC_INTRINSIC;
4206 1.1 mrg sym->attr.flavor = FL_PROCEDURE;
4207 1.1 mrg sym->result = sym;
4208 1.1 mrg if (expr->rank > 0)
4209 1.1 mrg {
4210 1.1 mrg sym->attr.dimension = 1;
4211 1.1 mrg sym->as = gfc_get_array_spec ();
4212 1.1 mrg sym->as->type = AS_ASSUMED_SHAPE;
4213 1.1 mrg sym->as->rank = expr->rank;
4214 1.1 mrg }
4215 1.1 mrg
4216 1.1 mrg gfc_copy_formal_args_intr (sym, expr->value.function.isym,
4217 1.1 mrg ignore_optional ? expr->value.function.actual
4218 1.1 mrg : NULL);
4219 1.1 mrg
4220 1.1 mrg return sym;
4221 1.1 mrg }
4222 1.1 mrg
4223 1.1 mrg /* Remove empty actual arguments. */
4224 1.1 mrg
4225 1.1 mrg static void
4226 1.1 mrg remove_empty_actual_arguments (gfc_actual_arglist **ap)
4227 1.1 mrg {
4228 1.1 mrg while (*ap)
4229 1.1 mrg {
4230 1.1 mrg if ((*ap)->expr == NULL)
4231 1.1 mrg {
4232 1.1 mrg gfc_actual_arglist *r = *ap;
4233 1.1 mrg *ap = r->next;
4234 1.1 mrg r->next = NULL;
4235 1.1 mrg gfc_free_actual_arglist (r);
4236 1.1 mrg }
4237 1.1 mrg else
4238 1.1 mrg ap = &((*ap)->next);
4239 1.1 mrg }
4240 1.1 mrg }
4241 1.1 mrg
4242 1.1 mrg #define MAX_SPEC_ARG 12
4243 1.1 mrg
4244 1.1 mrg /* Make up an fn spec that's right for intrinsic functions that we
4245 1.1 mrg want to call. */
4246 1.1 mrg
4247 1.1 mrg static char *
4248 1.1 mrg intrinsic_fnspec (gfc_expr *expr)
4249 1.1 mrg {
4250 1.1 mrg static char fnspec_buf[MAX_SPEC_ARG*2+1];
4251 1.1 mrg char *fp;
4252 1.1 mrg int i;
4253 1.1 mrg int num_char_args;
4254 1.1 mrg
4255 1.1 mrg #define ADD_CHAR(c) do { *fp++ = c; *fp++ = ' '; } while(0)
4256 1.1 mrg
4257 1.1 mrg /* Set the fndecl. */
4258 1.1 mrg fp = fnspec_buf;
4259 1.1 mrg /* Function return value. FIXME: Check if the second letter could
4260 1.1 mrg be something other than a space, for further optimization. */
4261 1.1 mrg ADD_CHAR ('.');
4262 1.1 mrg if (expr->rank == 0)
4263 1.1 mrg {
4264 1.1 mrg if (expr->ts.type == BT_CHARACTER)
4265 1.1 mrg {
4266 1.1 mrg ADD_CHAR ('w'); /* Address of character. */
4267 1.1 mrg ADD_CHAR ('.'); /* Length of character. */
4268 1.1 mrg }
4269 1.1 mrg }
4270 1.1 mrg else
4271 1.1 mrg ADD_CHAR ('w'); /* Return value is a descriptor. */
4272 1.1 mrg
4273 1.1 mrg num_char_args = 0;
4274 1.1 mrg for (gfc_actual_arglist *a = expr->value.function.actual; a; a = a->next)
4275 1.1 mrg {
4276 1.1 mrg if (a->expr == NULL)
4277 1.1 mrg continue;
4278 1.1 mrg
4279 1.1 mrg if (a->name && strcmp (a->name,"%VAL") == 0)
4280 1.1 mrg ADD_CHAR ('.');
4281 1.1 mrg else
4282 1.1 mrg {
4283 1.1 mrg if (a->expr->rank > 0)
4284 1.1 mrg ADD_CHAR ('r');
4285 1.1 mrg else
4286 1.1 mrg ADD_CHAR ('R');
4287 1.1 mrg }
4288 1.1 mrg num_char_args += a->expr->ts.type == BT_CHARACTER;
4289 1.1 mrg gcc_assert (fp - fnspec_buf + num_char_args <= MAX_SPEC_ARG*2);
4290 1.1 mrg }
4291 1.1 mrg
4292 1.1 mrg for (i = 0; i < num_char_args; i++)
4293 1.1 mrg ADD_CHAR ('.');
4294 1.1 mrg
4295 1.1 mrg *fp = '\0';
4296 1.1 mrg return fnspec_buf;
4297 1.1 mrg }
4298 1.1 mrg
4299 1.1 mrg #undef MAX_SPEC_ARG
4300 1.1 mrg #undef ADD_CHAR
4301 1.1 mrg
4302 1.1 mrg /* Generate the right symbol for the specific intrinsic function and
4303 1.1 mrg modify the expr accordingly. This assumes that absent optional
4304 1.1 mrg arguments should be removed. */
4305 1.1 mrg
4306 1.1 mrg gfc_symbol *
4307 1.1 mrg specific_intrinsic_symbol (gfc_expr *expr)
4308 1.1 mrg {
4309 1.1 mrg gfc_symbol *sym;
4310 1.1 mrg
4311 1.1 mrg sym = gfc_find_intrinsic_symbol (expr);
4312 1.1 mrg if (sym == NULL)
4313 1.1 mrg {
4314 1.1 mrg sym = gfc_get_intrinsic_function_symbol (expr);
4315 1.1 mrg sym->ts = expr->ts;
4316 1.1 mrg if (sym->ts.type == BT_CHARACTER && sym->ts.u.cl)
4317 1.1 mrg sym->ts.u.cl = gfc_new_charlen (sym->ns, NULL);
4318 1.1 mrg
4319 1.1 mrg gfc_copy_formal_args_intr (sym, expr->value.function.isym,
4320 1.1 mrg expr->value.function.actual, true);
4321 1.1 mrg sym->backend_decl
4322 1.1 mrg = gfc_get_extern_function_decl (sym, expr->value.function.actual,
4323 1.1 mrg intrinsic_fnspec (expr));
4324 1.1 mrg }
4325 1.1 mrg
4326 1.1 mrg remove_empty_actual_arguments (&(expr->value.function.actual));
4327 1.1 mrg
4328 1.1 mrg return sym;
4329 1.1 mrg }
4330 1.1 mrg
4331 1.1 mrg /* Generate a call to an external intrinsic function. FIXME: So far,
4332 1.1 mrg this only works for functions which are called with well-defined
4333 1.1 mrg types; CSHIFT and friends will come later. */
4334 1.1 mrg
4335 1.1 mrg static void
4336 1.1 mrg gfc_conv_intrinsic_funcall (gfc_se * se, gfc_expr * expr)
4337 1.1 mrg {
4338 1.1 mrg gfc_symbol *sym;
4339 1.1 mrg vec<tree, va_gc> *append_args;
4340 1.1 mrg bool specific_symbol;
4341 1.1 mrg
4342 1.1 mrg gcc_assert (!se->ss || se->ss->info->expr == expr);
4343 1.1 mrg
4344 1.1 mrg if (se->ss)
4345 1.1 mrg gcc_assert (expr->rank > 0);
4346 1.1 mrg else
4347 1.1 mrg gcc_assert (expr->rank == 0);
4348 1.1 mrg
4349 1.1 mrg switch (expr->value.function.isym->id)
4350 1.1 mrg {
4351 1.1 mrg case GFC_ISYM_ANY:
4352 1.1 mrg case GFC_ISYM_ALL:
4353 1.1 mrg case GFC_ISYM_FINDLOC:
4354 1.1 mrg case GFC_ISYM_MAXLOC:
4355 1.1 mrg case GFC_ISYM_MINLOC:
4356 1.1 mrg case GFC_ISYM_MAXVAL:
4357 1.1 mrg case GFC_ISYM_MINVAL:
4358 1.1 mrg case GFC_ISYM_NORM2:
4359 1.1 mrg case GFC_ISYM_PRODUCT:
4360 1.1 mrg case GFC_ISYM_SUM:
4361 1.1 mrg specific_symbol = true;
4362 1.1 mrg break;
4363 1.1 mrg default:
4364 1.1 mrg specific_symbol = false;
4365 1.1 mrg }
4366 1.1 mrg
4367 1.1 mrg if (specific_symbol)
4368 1.1 mrg {
4369 1.1 mrg /* Need to copy here because specific_intrinsic_symbol modifies
4370 1.1 mrg expr to omit the absent optional arguments. */
4371 1.1 mrg expr = gfc_copy_expr (expr);
4372 1.1 mrg sym = specific_intrinsic_symbol (expr);
4373 1.1 mrg }
4374 1.1 mrg else
4375 1.1 mrg sym = gfc_get_symbol_for_expr (expr, se->ignore_optional);
4376 1.1 mrg
4377 1.1 mrg /* Calls to libgfortran_matmul need to be appended special arguments,
4378 1.1 mrg to be able to call the BLAS ?gemm functions if required and possible. */
4379 1.1 mrg append_args = NULL;
4380 1.1 mrg if (expr->value.function.isym->id == GFC_ISYM_MATMUL
4381 1.1 mrg && !expr->external_blas
4382 1.1 mrg && sym->ts.type != BT_LOGICAL)
4383 1.1 mrg {
4384 1.1 mrg tree cint = gfc_get_int_type (gfc_c_int_kind);
4385 1.1 mrg
4386 1.1 mrg if (flag_external_blas
4387 1.1 mrg && (sym->ts.type == BT_REAL || sym->ts.type == BT_COMPLEX)
4388 1.1 mrg && (sym->ts.kind == 4 || sym->ts.kind == 8))
4389 1.1 mrg {
4390 1.1 mrg tree gemm_fndecl;
4391 1.1 mrg
4392 1.1 mrg if (sym->ts.type == BT_REAL)
4393 1.1 mrg {
4394 1.1 mrg if (sym->ts.kind == 4)
4395 1.1 mrg gemm_fndecl = gfor_fndecl_sgemm;
4396 1.1 mrg else
4397 1.1 mrg gemm_fndecl = gfor_fndecl_dgemm;
4398 1.1 mrg }
4399 1.1 mrg else
4400 1.1 mrg {
4401 1.1 mrg if (sym->ts.kind == 4)
4402 1.1 mrg gemm_fndecl = gfor_fndecl_cgemm;
4403 1.1 mrg else
4404 1.1 mrg gemm_fndecl = gfor_fndecl_zgemm;
4405 1.1 mrg }
4406 1.1 mrg
4407 1.1 mrg vec_alloc (append_args, 3);
4408 1.1 mrg append_args->quick_push (build_int_cst (cint, 1));
4409 1.1 mrg append_args->quick_push (build_int_cst (cint,
4410 1.1 mrg flag_blas_matmul_limit));
4411 1.1 mrg append_args->quick_push (gfc_build_addr_expr (NULL_TREE,
4412 1.1 mrg gemm_fndecl));
4413 1.1 mrg }
4414 1.1 mrg else
4415 1.1 mrg {
4416 1.1 mrg vec_alloc (append_args, 3);
4417 1.1 mrg append_args->quick_push (build_int_cst (cint, 0));
4418 1.1 mrg append_args->quick_push (build_int_cst (cint, 0));
4419 1.1 mrg append_args->quick_push (null_pointer_node);
4420 1.1 mrg }
4421 1.1 mrg }
4422 1.1 mrg
4423 1.1 mrg gfc_conv_procedure_call (se, sym, expr->value.function.actual, expr,
4424 1.1 mrg append_args);
4425 1.1 mrg
4426 1.1 mrg if (specific_symbol)
4427 1.1 mrg gfc_free_expr (expr);
4428 1.1 mrg else
4429 1.1 mrg gfc_free_symbol (sym);
4430 1.1 mrg }
4431 1.1 mrg
4432 1.1 mrg /* ANY and ALL intrinsics. ANY->op == NE_EXPR, ALL->op == EQ_EXPR.
4433 1.1 mrg Implemented as
4434 1.1 mrg any(a)
4435 1.1 mrg {
4436 1.1 mrg forall (i=...)
4437 1.1 mrg if (a[i] != 0)
4438 1.1 mrg return 1
4439 1.1 mrg end forall
4440 1.1 mrg return 0
4441 1.1 mrg }
4442 1.1 mrg all(a)
4443 1.1 mrg {
4444 1.1 mrg forall (i=...)
4445 1.1 mrg if (a[i] == 0)
4446 1.1 mrg return 0
4447 1.1 mrg end forall
4448 1.1 mrg return 1
4449 1.1 mrg }
4450 1.1 mrg */
4451 1.1 mrg static void
4452 1.1 mrg gfc_conv_intrinsic_anyall (gfc_se * se, gfc_expr * expr, enum tree_code op)
4453 1.1 mrg {
4454 1.1 mrg tree resvar;
4455 1.1 mrg stmtblock_t block;
4456 1.1 mrg stmtblock_t body;
4457 1.1 mrg tree type;
4458 1.1 mrg tree tmp;
4459 1.1 mrg tree found;
4460 1.1 mrg gfc_loopinfo loop;
4461 1.1 mrg gfc_actual_arglist *actual;
4462 1.1 mrg gfc_ss *arrayss;
4463 1.1 mrg gfc_se arrayse;
4464 1.1 mrg tree exit_label;
4465 1.1 mrg
4466 1.1 mrg if (se->ss)
4467 1.1 mrg {
4468 1.1 mrg gfc_conv_intrinsic_funcall (se, expr);
4469 1.1 mrg return;
4470 1.1 mrg }
4471 1.1 mrg
4472 1.1 mrg actual = expr->value.function.actual;
4473 1.1 mrg type = gfc_typenode_for_spec (&expr->ts);
4474 1.1 mrg /* Initialize the result. */
4475 1.1 mrg resvar = gfc_create_var (type, "test");
4476 1.1 mrg if (op == EQ_EXPR)
4477 1.1 mrg tmp = convert (type, boolean_true_node);
4478 1.1 mrg else
4479 1.1 mrg tmp = convert (type, boolean_false_node);
4480 1.1 mrg gfc_add_modify (&se->pre, resvar, tmp);
4481 1.1 mrg
4482 1.1 mrg /* Walk the arguments. */
4483 1.1 mrg arrayss = gfc_walk_expr (actual->expr);
4484 1.1 mrg gcc_assert (arrayss != gfc_ss_terminator);
4485 1.1 mrg
4486 1.1 mrg /* Initialize the scalarizer. */
4487 1.1 mrg gfc_init_loopinfo (&loop);
4488 1.1 mrg exit_label = gfc_build_label_decl (NULL_TREE);
4489 1.1 mrg TREE_USED (exit_label) = 1;
4490 1.1 mrg gfc_add_ss_to_loop (&loop, arrayss);
4491 1.1 mrg
4492 1.1 mrg /* Initialize the loop. */
4493 1.1 mrg gfc_conv_ss_startstride (&loop);
4494 1.1 mrg gfc_conv_loop_setup (&loop, &expr->where);
4495 1.1 mrg
4496 1.1 mrg gfc_mark_ss_chain_used (arrayss, 1);
4497 1.1 mrg /* Generate the loop body. */
4498 1.1 mrg gfc_start_scalarized_body (&loop, &body);
4499 1.1 mrg
4500 1.1 mrg /* If the condition matches then set the return value. */
4501 1.1 mrg gfc_start_block (&block);
4502 1.1 mrg if (op == EQ_EXPR)
4503 1.1 mrg tmp = convert (type, boolean_false_node);
4504 1.1 mrg else
4505 1.1 mrg tmp = convert (type, boolean_true_node);
4506 1.1 mrg gfc_add_modify (&block, resvar, tmp);
4507 1.1 mrg
4508 1.1 mrg /* And break out of the loop. */
4509 1.1 mrg tmp = build1_v (GOTO_EXPR, exit_label);
4510 1.1 mrg gfc_add_expr_to_block (&block, tmp);
4511 1.1 mrg
4512 1.1 mrg found = gfc_finish_block (&block);
4513 1.1 mrg
4514 1.1 mrg /* Check this element. */
4515 1.1 mrg gfc_init_se (&arrayse, NULL);
4516 1.1 mrg gfc_copy_loopinfo_to_se (&arrayse, &loop);
4517 1.1 mrg arrayse.ss = arrayss;
4518 1.1 mrg gfc_conv_expr_val (&arrayse, actual->expr);
4519 1.1 mrg
4520 1.1 mrg gfc_add_block_to_block (&body, &arrayse.pre);
4521 1.1 mrg tmp = fold_build2_loc (input_location, op, logical_type_node, arrayse.expr,
4522 1.1 mrg build_int_cst (TREE_TYPE (arrayse.expr), 0));
4523 1.1 mrg tmp = build3_v (COND_EXPR, tmp, found, build_empty_stmt (input_location));
4524 1.1 mrg gfc_add_expr_to_block (&body, tmp);
4525 1.1 mrg gfc_add_block_to_block (&body, &arrayse.post);
4526 1.1 mrg
4527 1.1 mrg gfc_trans_scalarizing_loops (&loop, &body);
4528 1.1 mrg
4529 1.1 mrg /* Add the exit label. */
4530 1.1 mrg tmp = build1_v (LABEL_EXPR, exit_label);
4531 1.1 mrg gfc_add_expr_to_block (&loop.pre, tmp);
4532 1.1 mrg
4533 1.1 mrg gfc_add_block_to_block (&se->pre, &loop.pre);
4534 1.1 mrg gfc_add_block_to_block (&se->pre, &loop.post);
4535 1.1 mrg gfc_cleanup_loop (&loop);
4536 1.1 mrg
4537 1.1 mrg se->expr = resvar;
4538 1.1 mrg }
4539 1.1 mrg
4540 1.1 mrg
4541 1.1 mrg /* Generate the constant 180 / pi, which is used in the conversion
4542 1.1 mrg of acosd(), asind(), atand(), atan2d(). */
4543 1.1 mrg
4544 1.1 mrg static tree
4545 1.1 mrg rad2deg (int kind)
4546 1.1 mrg {
4547 1.1 mrg tree retval;
4548 1.1 mrg mpfr_t pi, t0;
4549 1.1 mrg
4550 1.1 mrg gfc_set_model_kind (kind);
4551 1.1 mrg mpfr_init (pi);
4552 1.1 mrg mpfr_init (t0);
4553 1.1 mrg mpfr_set_si (t0, 180, GFC_RND_MODE);
4554 1.1 mrg mpfr_const_pi (pi, GFC_RND_MODE);
4555 1.1 mrg mpfr_div (t0, t0, pi, GFC_RND_MODE);
4556 1.1 mrg retval = gfc_conv_mpfr_to_tree (t0, kind, 0);
4557 1.1 mrg mpfr_clear (t0);
4558 1.1 mrg mpfr_clear (pi);
4559 1.1 mrg return retval;
4560 1.1 mrg }
4561 1.1 mrg
4562 1.1 mrg
4563 1.1 mrg static gfc_intrinsic_map_t *
4564 1.1 mrg gfc_lookup_intrinsic (gfc_isym_id id)
4565 1.1 mrg {
4566 1.1 mrg gfc_intrinsic_map_t *m = gfc_intrinsic_map;
4567 1.1 mrg for (; m->id != GFC_ISYM_NONE || m->double_built_in != END_BUILTINS; m++)
4568 1.1 mrg if (id == m->id)
4569 1.1 mrg break;
4570 1.1 mrg gcc_assert (id == m->id);
4571 1.1 mrg return m;
4572 1.1 mrg }
4573 1.1 mrg
4574 1.1 mrg
4575 1.1 mrg /* ACOSD(x) is translated into ACOS(x) * 180 / pi.
4576 1.1 mrg ASIND(x) is translated into ASIN(x) * 180 / pi.
4577 1.1 mrg ATAND(x) is translated into ATAN(x) * 180 / pi. */
4578 1.1 mrg
4579 1.1 mrg static void
4580 1.1 mrg gfc_conv_intrinsic_atrigd (gfc_se * se, gfc_expr * expr, gfc_isym_id id)
4581 1.1 mrg {
4582 1.1 mrg tree arg;
4583 1.1 mrg tree atrigd;
4584 1.1 mrg tree type;
4585 1.1 mrg gfc_intrinsic_map_t *m;
4586 1.1 mrg
4587 1.1 mrg type = gfc_typenode_for_spec (&expr->ts);
4588 1.1 mrg
4589 1.1 mrg gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
4590 1.1 mrg
4591 1.1 mrg switch (id)
4592 1.1 mrg {
4593 1.1 mrg case GFC_ISYM_ACOSD:
4594 1.1 mrg m = gfc_lookup_intrinsic (GFC_ISYM_ACOS);
4595 1.1 mrg break;
4596 1.1 mrg case GFC_ISYM_ASIND:
4597 1.1 mrg m = gfc_lookup_intrinsic (GFC_ISYM_ASIN);
4598 1.1 mrg break;
4599 1.1 mrg case GFC_ISYM_ATAND:
4600 1.1 mrg m = gfc_lookup_intrinsic (GFC_ISYM_ATAN);
4601 1.1 mrg break;
4602 1.1 mrg default:
4603 1.1 mrg gcc_unreachable ();
4604 1.1 mrg }
4605 1.1 mrg atrigd = gfc_get_intrinsic_lib_fndecl (m, expr);
4606 1.1 mrg atrigd = build_call_expr_loc (input_location, atrigd, 1, arg);
4607 1.1 mrg
4608 1.1 mrg se->expr = fold_build2_loc (input_location, MULT_EXPR, type, atrigd,
4609 1.1 mrg fold_convert (type, rad2deg (expr->ts.kind)));
4610 1.1 mrg }
4611 1.1 mrg
4612 1.1 mrg
4613 1.1 mrg /* COTAN(X) is translated into -TAN(X+PI/2) for REAL argument and
4614 1.1 mrg COS(X) / SIN(X) for COMPLEX argument. */
4615 1.1 mrg
4616 1.1 mrg static void
4617 1.1 mrg gfc_conv_intrinsic_cotan (gfc_se *se, gfc_expr *expr)
4618 1.1 mrg {
4619 1.1 mrg gfc_intrinsic_map_t *m;
4620 1.1 mrg tree arg;
4621 1.1 mrg tree type;
4622 1.1 mrg
4623 1.1 mrg type = gfc_typenode_for_spec (&expr->ts);
4624 1.1 mrg gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
4625 1.1 mrg
4626 1.1 mrg if (expr->ts.type == BT_REAL)
4627 1.1 mrg {
4628 1.1 mrg tree tan;
4629 1.1 mrg tree tmp;
4630 1.1 mrg mpfr_t pio2;
4631 1.1 mrg
4632 1.1 mrg /* Create pi/2. */
4633 1.1 mrg gfc_set_model_kind (expr->ts.kind);
4634 1.1 mrg mpfr_init (pio2);
4635 1.1 mrg mpfr_const_pi (pio2, GFC_RND_MODE);
4636 1.1 mrg mpfr_div_ui (pio2, pio2, 2, GFC_RND_MODE);
4637 1.1 mrg tmp = gfc_conv_mpfr_to_tree (pio2, expr->ts.kind, 0);
4638 1.1 mrg mpfr_clear (pio2);
4639 1.1 mrg
4640 1.1 mrg /* Find tan builtin function. */
4641 1.1 mrg m = gfc_lookup_intrinsic (GFC_ISYM_TAN);
4642 1.1 mrg tan = gfc_get_intrinsic_lib_fndecl (m, expr);
4643 1.1 mrg tmp = fold_build2_loc (input_location, PLUS_EXPR, type, arg, tmp);
4644 1.1 mrg tan = build_call_expr_loc (input_location, tan, 1, tmp);
4645 1.1 mrg se->expr = fold_build1_loc (input_location, NEGATE_EXPR, type, tan);
4646 1.1 mrg }
4647 1.1 mrg else
4648 1.1 mrg {
4649 1.1 mrg tree sin;
4650 1.1 mrg tree cos;
4651 1.1 mrg
4652 1.1 mrg /* Find cos builtin function. */
4653 1.1 mrg m = gfc_lookup_intrinsic (GFC_ISYM_COS);
4654 1.1 mrg cos = gfc_get_intrinsic_lib_fndecl (m, expr);
4655 1.1 mrg cos = build_call_expr_loc (input_location, cos, 1, arg);
4656 1.1 mrg
4657 1.1 mrg /* Find sin builtin function. */
4658 1.1 mrg m = gfc_lookup_intrinsic (GFC_ISYM_SIN);
4659 1.1 mrg sin = gfc_get_intrinsic_lib_fndecl (m, expr);
4660 1.1 mrg sin = build_call_expr_loc (input_location, sin, 1, arg);
4661 1.1 mrg
4662 1.1 mrg /* Divide cos by sin. */
4663 1.1 mrg se->expr = fold_build2_loc (input_location, RDIV_EXPR, type, cos, sin);
4664 1.1 mrg }
4665 1.1 mrg }
4666 1.1 mrg
4667 1.1 mrg
4668 1.1 mrg /* COTAND(X) is translated into -TAND(X+90) for REAL argument. */
4669 1.1 mrg
4670 1.1 mrg static void
4671 1.1 mrg gfc_conv_intrinsic_cotand (gfc_se *se, gfc_expr *expr)
4672 1.1 mrg {
4673 1.1 mrg tree arg;
4674 1.1 mrg tree type;
4675 1.1 mrg tree ninety_tree;
4676 1.1 mrg mpfr_t ninety;
4677 1.1 mrg
4678 1.1 mrg type = gfc_typenode_for_spec (&expr->ts);
4679 1.1 mrg gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
4680 1.1 mrg
4681 1.1 mrg gfc_set_model_kind (expr->ts.kind);
4682 1.1 mrg
4683 1.1 mrg /* Build the tree for x + 90. */
4684 1.1 mrg mpfr_init_set_ui (ninety, 90, GFC_RND_MODE);
4685 1.1 mrg ninety_tree = gfc_conv_mpfr_to_tree (ninety, expr->ts.kind, 0);
4686 1.1 mrg arg = fold_build2_loc (input_location, PLUS_EXPR, type, arg, ninety_tree);
4687 1.1 mrg mpfr_clear (ninety);
4688 1.1 mrg
4689 1.1 mrg /* Find tand. */
4690 1.1 mrg gfc_intrinsic_map_t *m = gfc_lookup_intrinsic (GFC_ISYM_TAND);
4691 1.1 mrg tree tand = gfc_get_intrinsic_lib_fndecl (m, expr);
4692 1.1 mrg tand = build_call_expr_loc (input_location, tand, 1, arg);
4693 1.1 mrg
4694 1.1 mrg se->expr = fold_build1_loc (input_location, NEGATE_EXPR, type, tand);
4695 1.1 mrg }
4696 1.1 mrg
4697 1.1 mrg
4698 1.1 mrg /* ATAN2D(Y,X) is translated into ATAN2(Y,X) * 180 / PI. */
4699 1.1 mrg
4700 1.1 mrg static void
4701 1.1 mrg gfc_conv_intrinsic_atan2d (gfc_se *se, gfc_expr *expr)
4702 1.1 mrg {
4703 1.1 mrg tree args[2];
4704 1.1 mrg tree atan2d;
4705 1.1 mrg tree type;
4706 1.1 mrg
4707 1.1 mrg gfc_conv_intrinsic_function_args (se, expr, args, 2);
4708 1.1 mrg type = TREE_TYPE (args[0]);
4709 1.1 mrg
4710 1.1 mrg gfc_intrinsic_map_t *m = gfc_lookup_intrinsic (GFC_ISYM_ATAN2);
4711 1.1 mrg atan2d = gfc_get_intrinsic_lib_fndecl (m, expr);
4712 1.1 mrg atan2d = build_call_expr_loc (input_location, atan2d, 2, args[0], args[1]);
4713 1.1 mrg
4714 1.1 mrg se->expr = fold_build2_loc (input_location, MULT_EXPR, type, atan2d,
4715 1.1 mrg rad2deg (expr->ts.kind));
4716 1.1 mrg }
4717 1.1 mrg
4718 1.1 mrg
4719 1.1 mrg /* COUNT(A) = Number of true elements in A. */
4720 1.1 mrg static void
4721 1.1 mrg gfc_conv_intrinsic_count (gfc_se * se, gfc_expr * expr)
4722 1.1 mrg {
4723 1.1 mrg tree resvar;
4724 1.1 mrg tree type;
4725 1.1 mrg stmtblock_t body;
4726 1.1 mrg tree tmp;
4727 1.1 mrg gfc_loopinfo loop;
4728 1.1 mrg gfc_actual_arglist *actual;
4729 1.1 mrg gfc_ss *arrayss;
4730 1.1 mrg gfc_se arrayse;
4731 1.1 mrg
4732 1.1 mrg if (se->ss)
4733 1.1 mrg {
4734 1.1 mrg gfc_conv_intrinsic_funcall (se, expr);
4735 1.1 mrg return;
4736 1.1 mrg }
4737 1.1 mrg
4738 1.1 mrg actual = expr->value.function.actual;
4739 1.1 mrg
4740 1.1 mrg type = gfc_typenode_for_spec (&expr->ts);
4741 1.1 mrg /* Initialize the result. */
4742 1.1 mrg resvar = gfc_create_var (type, "count");
4743 1.1 mrg gfc_add_modify (&se->pre, resvar, build_int_cst (type, 0));
4744 1.1 mrg
4745 1.1 mrg /* Walk the arguments. */
4746 1.1 mrg arrayss = gfc_walk_expr (actual->expr);
4747 1.1 mrg gcc_assert (arrayss != gfc_ss_terminator);
4748 1.1 mrg
4749 1.1 mrg /* Initialize the scalarizer. */
4750 1.1 mrg gfc_init_loopinfo (&loop);
4751 1.1 mrg gfc_add_ss_to_loop (&loop, arrayss);
4752 1.1 mrg
4753 1.1 mrg /* Initialize the loop. */
4754 1.1 mrg gfc_conv_ss_startstride (&loop);
4755 1.1 mrg gfc_conv_loop_setup (&loop, &expr->where);
4756 1.1 mrg
4757 1.1 mrg gfc_mark_ss_chain_used (arrayss, 1);
4758 1.1 mrg /* Generate the loop body. */
4759 1.1 mrg gfc_start_scalarized_body (&loop, &body);
4760 1.1 mrg
4761 1.1 mrg tmp = fold_build2_loc (input_location, PLUS_EXPR, TREE_TYPE (resvar),
4762 1.1 mrg resvar, build_int_cst (TREE_TYPE (resvar), 1));
4763 1.1 mrg tmp = build2_v (MODIFY_EXPR, resvar, tmp);
4764 1.1 mrg
4765 1.1 mrg gfc_init_se (&arrayse, NULL);
4766 1.1 mrg gfc_copy_loopinfo_to_se (&arrayse, &loop);
4767 1.1 mrg arrayse.ss = arrayss;
4768 1.1 mrg gfc_conv_expr_val (&arrayse, actual->expr);
4769 1.1 mrg tmp = build3_v (COND_EXPR, arrayse.expr, tmp,
4770 1.1 mrg build_empty_stmt (input_location));
4771 1.1 mrg
4772 1.1 mrg gfc_add_block_to_block (&body, &arrayse.pre);
4773 1.1 mrg gfc_add_expr_to_block (&body, tmp);
4774 1.1 mrg gfc_add_block_to_block (&body, &arrayse.post);
4775 1.1 mrg
4776 1.1 mrg gfc_trans_scalarizing_loops (&loop, &body);
4777 1.1 mrg
4778 1.1 mrg gfc_add_block_to_block (&se->pre, &loop.pre);
4779 1.1 mrg gfc_add_block_to_block (&se->pre, &loop.post);
4780 1.1 mrg gfc_cleanup_loop (&loop);
4781 1.1 mrg
4782 1.1 mrg se->expr = resvar;
4783 1.1 mrg }
4784 1.1 mrg
4785 1.1 mrg
4786 1.1 mrg /* Update given gfc_se to have ss component pointing to the nested gfc_ss
4787 1.1 mrg struct and return the corresponding loopinfo. */
4788 1.1 mrg
4789 1.1 mrg static gfc_loopinfo *
4790 1.1 mrg enter_nested_loop (gfc_se *se)
4791 1.1 mrg {
4792 1.1 mrg se->ss = se->ss->nested_ss;
4793 1.1 mrg gcc_assert (se->ss == se->ss->loop->ss);
4794 1.1 mrg
4795 1.1 mrg return se->ss->loop;
4796 1.1 mrg }
4797 1.1 mrg
4798 1.1 mrg /* Build the condition for a mask, which may be optional. */
4799 1.1 mrg
4800 1.1 mrg static tree
4801 1.1 mrg conv_mask_condition (gfc_se *maskse, gfc_expr *maskexpr,
4802 1.1 mrg bool optional_mask)
4803 1.1 mrg {
4804 1.1 mrg tree present;
4805 1.1 mrg tree type;
4806 1.1 mrg
4807 1.1 mrg if (optional_mask)
4808 1.1 mrg {
4809 1.1 mrg type = TREE_TYPE (maskse->expr);
4810 1.1 mrg present = gfc_conv_expr_present (maskexpr->symtree->n.sym);
4811 1.1 mrg present = convert (type, present);
4812 1.1 mrg present = fold_build1_loc (input_location, TRUTH_NOT_EXPR, type,
4813 1.1 mrg present);
4814 1.1 mrg return fold_build2_loc (input_location, TRUTH_ORIF_EXPR,
4815 1.1 mrg type, present, maskse->expr);
4816 1.1 mrg }
4817 1.1 mrg else
4818 1.1 mrg return maskse->expr;
4819 1.1 mrg }
4820 1.1 mrg
4821 1.1 mrg /* Inline implementation of the sum and product intrinsics. */
4822 1.1 mrg static void
4823 1.1 mrg gfc_conv_intrinsic_arith (gfc_se * se, gfc_expr * expr, enum tree_code op,
4824 1.1 mrg bool norm2)
4825 1.1 mrg {
4826 1.1 mrg tree resvar;
4827 1.1 mrg tree scale = NULL_TREE;
4828 1.1 mrg tree type;
4829 1.1 mrg stmtblock_t body;
4830 1.1 mrg stmtblock_t block;
4831 1.1 mrg tree tmp;
4832 1.1 mrg gfc_loopinfo loop, *ploop;
4833 1.1 mrg gfc_actual_arglist *arg_array, *arg_mask;
4834 1.1 mrg gfc_ss *arrayss = NULL;
4835 1.1 mrg gfc_ss *maskss = NULL;
4836 1.1 mrg gfc_se arrayse;
4837 1.1 mrg gfc_se maskse;
4838 1.1 mrg gfc_se *parent_se;
4839 1.1 mrg gfc_expr *arrayexpr;
4840 1.1 mrg gfc_expr *maskexpr;
4841 1.1 mrg bool optional_mask;
4842 1.1 mrg
4843 1.1 mrg if (expr->rank > 0)
4844 1.1 mrg {
4845 1.1 mrg gcc_assert (gfc_inline_intrinsic_function_p (expr));
4846 1.1 mrg parent_se = se;
4847 1.1 mrg }
4848 1.1 mrg else
4849 1.1 mrg parent_se = NULL;
4850 1.1 mrg
4851 1.1 mrg type = gfc_typenode_for_spec (&expr->ts);
4852 1.1 mrg /* Initialize the result. */
4853 1.1 mrg resvar = gfc_create_var (type, "val");
4854 1.1 mrg if (norm2)
4855 1.1 mrg {
4856 1.1 mrg /* result = 0.0;
4857 1.1 mrg scale = 1.0. */
4858 1.1 mrg scale = gfc_create_var (type, "scale");
4859 1.1 mrg gfc_add_modify (&se->pre, scale,
4860 1.1 mrg gfc_build_const (type, integer_one_node));
4861 1.1 mrg tmp = gfc_build_const (type, integer_zero_node);
4862 1.1 mrg }
4863 1.1 mrg else if (op == PLUS_EXPR || op == BIT_IOR_EXPR || op == BIT_XOR_EXPR)
4864 1.1 mrg tmp = gfc_build_const (type, integer_zero_node);
4865 1.1 mrg else if (op == NE_EXPR)
4866 1.1 mrg /* PARITY. */
4867 1.1 mrg tmp = convert (type, boolean_false_node);
4868 1.1 mrg else if (op == BIT_AND_EXPR)
4869 1.1 mrg tmp = gfc_build_const (type, fold_build1_loc (input_location, NEGATE_EXPR,
4870 1.1 mrg type, integer_one_node));
4871 1.1 mrg else
4872 1.1 mrg tmp = gfc_build_const (type, integer_one_node);
4873 1.1 mrg
4874 1.1 mrg gfc_add_modify (&se->pre, resvar, tmp);
4875 1.1 mrg
4876 1.1 mrg arg_array = expr->value.function.actual;
4877 1.1 mrg
4878 1.1 mrg arrayexpr = arg_array->expr;
4879 1.1 mrg
4880 1.1 mrg if (op == NE_EXPR || norm2)
4881 1.1 mrg {
4882 1.1 mrg /* PARITY and NORM2. */
4883 1.1 mrg maskexpr = NULL;
4884 1.1 mrg optional_mask = false;
4885 1.1 mrg }
4886 1.1 mrg else
4887 1.1 mrg {
4888 1.1 mrg arg_mask = arg_array->next->next;
4889 1.1 mrg gcc_assert (arg_mask != NULL);
4890 1.1 mrg maskexpr = arg_mask->expr;
4891 1.1 mrg optional_mask = maskexpr && maskexpr->expr_type == EXPR_VARIABLE
4892 1.1 mrg && maskexpr->symtree->n.sym->attr.dummy
4893 1.1 mrg && maskexpr->symtree->n.sym->attr.optional;
4894 1.1 mrg }
4895 1.1 mrg
4896 1.1 mrg if (expr->rank == 0)
4897 1.1 mrg {
4898 1.1 mrg /* Walk the arguments. */
4899 1.1 mrg arrayss = gfc_walk_expr (arrayexpr);
4900 1.1 mrg gcc_assert (arrayss != gfc_ss_terminator);
4901 1.1 mrg
4902 1.1 mrg if (maskexpr && maskexpr->rank > 0)
4903 1.1 mrg {
4904 1.1 mrg maskss = gfc_walk_expr (maskexpr);
4905 1.1 mrg gcc_assert (maskss != gfc_ss_terminator);
4906 1.1 mrg }
4907 1.1 mrg else
4908 1.1 mrg maskss = NULL;
4909 1.1 mrg
4910 1.1 mrg /* Initialize the scalarizer. */
4911 1.1 mrg gfc_init_loopinfo (&loop);
4912 1.1 mrg
4913 1.1 mrg /* We add the mask first because the number of iterations is
4914 1.1 mrg taken from the last ss, and this breaks if an absent
4915 1.1 mrg optional argument is used for mask. */
4916 1.1 mrg
4917 1.1 mrg if (maskexpr && maskexpr->rank > 0)
4918 1.1 mrg gfc_add_ss_to_loop (&loop, maskss);
4919 1.1 mrg gfc_add_ss_to_loop (&loop, arrayss);
4920 1.1 mrg
4921 1.1 mrg /* Initialize the loop. */
4922 1.1 mrg gfc_conv_ss_startstride (&loop);
4923 1.1 mrg gfc_conv_loop_setup (&loop, &expr->where);
4924 1.1 mrg
4925 1.1 mrg if (maskexpr && maskexpr->rank > 0)
4926 1.1 mrg gfc_mark_ss_chain_used (maskss, 1);
4927 1.1 mrg gfc_mark_ss_chain_used (arrayss, 1);
4928 1.1 mrg
4929 1.1 mrg ploop = &loop;
4930 1.1 mrg }
4931 1.1 mrg else
4932 1.1 mrg /* All the work has been done in the parent loops. */
4933 1.1 mrg ploop = enter_nested_loop (se);
4934 1.1 mrg
4935 1.1 mrg gcc_assert (ploop);
4936 1.1 mrg
4937 1.1 mrg /* Generate the loop body. */
4938 1.1 mrg gfc_start_scalarized_body (ploop, &body);
4939 1.1 mrg
4940 1.1 mrg /* If we have a mask, only add this element if the mask is set. */
4941 1.1 mrg if (maskexpr && maskexpr->rank > 0)
4942 1.1 mrg {
4943 1.1 mrg gfc_init_se (&maskse, parent_se);
4944 1.1 mrg gfc_copy_loopinfo_to_se (&maskse, ploop);
4945 1.1 mrg if (expr->rank == 0)
4946 1.1 mrg maskse.ss = maskss;
4947 1.1 mrg gfc_conv_expr_val (&maskse, maskexpr);
4948 1.1 mrg gfc_add_block_to_block (&body, &maskse.pre);
4949 1.1 mrg
4950 1.1 mrg gfc_start_block (&block);
4951 1.1 mrg }
4952 1.1 mrg else
4953 1.1 mrg gfc_init_block (&block);
4954 1.1 mrg
4955 1.1 mrg /* Do the actual summation/product. */
4956 1.1 mrg gfc_init_se (&arrayse, parent_se);
4957 1.1 mrg gfc_copy_loopinfo_to_se (&arrayse, ploop);
4958 1.1 mrg if (expr->rank == 0)
4959 1.1 mrg arrayse.ss = arrayss;
4960 1.1 mrg gfc_conv_expr_val (&arrayse, arrayexpr);
4961 1.1 mrg gfc_add_block_to_block (&block, &arrayse.pre);
4962 1.1 mrg
4963 1.1 mrg if (norm2)
4964 1.1 mrg {
4965 1.1 mrg /* if (x (i) != 0.0)
4966 1.1 mrg {
4967 1.1 mrg absX = abs(x(i))
4968 1.1 mrg if (absX > scale)
4969 1.1 mrg {
4970 1.1 mrg val = scale/absX;
4971 1.1 mrg result = 1.0 + result * val * val;
4972 1.1 mrg scale = absX;
4973 1.1 mrg }
4974 1.1 mrg else
4975 1.1 mrg {
4976 1.1 mrg val = absX/scale;
4977 1.1 mrg result += val * val;
4978 1.1 mrg }
4979 1.1 mrg } */
4980 1.1 mrg tree res1, res2, cond, absX, val;
4981 1.1 mrg stmtblock_t ifblock1, ifblock2, ifblock3;
4982 1.1 mrg
4983 1.1 mrg gfc_init_block (&ifblock1);
4984 1.1 mrg
4985 1.1 mrg absX = gfc_create_var (type, "absX");
4986 1.1 mrg gfc_add_modify (&ifblock1, absX,
4987 1.1 mrg fold_build1_loc (input_location, ABS_EXPR, type,
4988 1.1 mrg arrayse.expr));
4989 1.1 mrg val = gfc_create_var (type, "val");
4990 1.1 mrg gfc_add_expr_to_block (&ifblock1, val);
4991 1.1 mrg
4992 1.1 mrg gfc_init_block (&ifblock2);
4993 1.1 mrg gfc_add_modify (&ifblock2, val,
4994 1.1 mrg fold_build2_loc (input_location, RDIV_EXPR, type, scale,
4995 1.1 mrg absX));
4996 1.1 mrg res1 = fold_build2_loc (input_location, MULT_EXPR, type, val, val);
4997 1.1 mrg res1 = fold_build2_loc (input_location, MULT_EXPR, type, resvar, res1);
4998 1.1 mrg res1 = fold_build2_loc (input_location, PLUS_EXPR, type, res1,
4999 1.1 mrg gfc_build_const (type, integer_one_node));
5000 1.1 mrg gfc_add_modify (&ifblock2, resvar, res1);
5001 1.1 mrg gfc_add_modify (&ifblock2, scale, absX);
5002 1.1 mrg res1 = gfc_finish_block (&ifblock2);
5003 1.1 mrg
5004 1.1 mrg gfc_init_block (&ifblock3);
5005 1.1 mrg gfc_add_modify (&ifblock3, val,
5006 1.1 mrg fold_build2_loc (input_location, RDIV_EXPR, type, absX,
5007 1.1 mrg scale));
5008 1.1 mrg res2 = fold_build2_loc (input_location, MULT_EXPR, type, val, val);
5009 1.1 mrg res2 = fold_build2_loc (input_location, PLUS_EXPR, type, resvar, res2);
5010 1.1 mrg gfc_add_modify (&ifblock3, resvar, res2);
5011 1.1 mrg res2 = gfc_finish_block (&ifblock3);
5012 1.1 mrg
5013 1.1 mrg cond = fold_build2_loc (input_location, GT_EXPR, logical_type_node,
5014 1.1 mrg absX, scale);
5015 1.1 mrg tmp = build3_v (COND_EXPR, cond, res1, res2);
5016 1.1 mrg gfc_add_expr_to_block (&ifblock1, tmp);
5017 1.1 mrg tmp = gfc_finish_block (&ifblock1);
5018 1.1 mrg
5019 1.1 mrg cond = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
5020 1.1 mrg arrayse.expr,
5021 1.1 mrg gfc_build_const (type, integer_zero_node));
5022 1.1 mrg
5023 1.1 mrg tmp = build3_v (COND_EXPR, cond, tmp, build_empty_stmt (input_location));
5024 1.1 mrg gfc_add_expr_to_block (&block, tmp);
5025 1.1 mrg }
5026 1.1 mrg else
5027 1.1 mrg {
5028 1.1 mrg tmp = fold_build2_loc (input_location, op, type, resvar, arrayse.expr);
5029 1.1 mrg gfc_add_modify (&block, resvar, tmp);
5030 1.1 mrg }
5031 1.1 mrg
5032 1.1 mrg gfc_add_block_to_block (&block, &arrayse.post);
5033 1.1 mrg
5034 1.1 mrg if (maskexpr && maskexpr->rank > 0)
5035 1.1 mrg {
5036 1.1 mrg /* We enclose the above in if (mask) {...} . If the mask is an
5037 1.1 mrg optional argument, generate
5038 1.1 mrg IF (.NOT. PRESENT(MASK) .OR. MASK(I)). */
5039 1.1 mrg tree ifmask;
5040 1.1 mrg tmp = gfc_finish_block (&block);
5041 1.1 mrg ifmask = conv_mask_condition (&maskse, maskexpr, optional_mask);
5042 1.1 mrg tmp = build3_v (COND_EXPR, ifmask, tmp,
5043 1.1 mrg build_empty_stmt (input_location));
5044 1.1 mrg }
5045 1.1 mrg else
5046 1.1 mrg tmp = gfc_finish_block (&block);
5047 1.1 mrg gfc_add_expr_to_block (&body, tmp);
5048 1.1 mrg
5049 1.1 mrg gfc_trans_scalarizing_loops (ploop, &body);
5050 1.1 mrg
5051 1.1 mrg /* For a scalar mask, enclose the loop in an if statement. */
5052 1.1 mrg if (maskexpr && maskexpr->rank == 0)
5053 1.1 mrg {
5054 1.1 mrg gfc_init_block (&block);
5055 1.1 mrg gfc_add_block_to_block (&block, &ploop->pre);
5056 1.1 mrg gfc_add_block_to_block (&block, &ploop->post);
5057 1.1 mrg tmp = gfc_finish_block (&block);
5058 1.1 mrg
5059 1.1 mrg if (expr->rank > 0)
5060 1.1 mrg {
5061 1.1 mrg tmp = build3_v (COND_EXPR, se->ss->info->data.scalar.value, tmp,
5062 1.1 mrg build_empty_stmt (input_location));
5063 1.1 mrg gfc_advance_se_ss_chain (se);
5064 1.1 mrg }
5065 1.1 mrg else
5066 1.1 mrg {
5067 1.1 mrg tree ifmask;
5068 1.1 mrg
5069 1.1 mrg gcc_assert (expr->rank == 0);
5070 1.1 mrg gfc_init_se (&maskse, NULL);
5071 1.1 mrg gfc_conv_expr_val (&maskse, maskexpr);
5072 1.1 mrg ifmask = conv_mask_condition (&maskse, maskexpr, optional_mask);
5073 1.1 mrg tmp = build3_v (COND_EXPR, ifmask, tmp,
5074 1.1 mrg build_empty_stmt (input_location));
5075 1.1 mrg }
5076 1.1 mrg
5077 1.1 mrg gfc_add_expr_to_block (&block, tmp);
5078 1.1 mrg gfc_add_block_to_block (&se->pre, &block);
5079 1.1 mrg gcc_assert (se->post.head == NULL);
5080 1.1 mrg }
5081 1.1 mrg else
5082 1.1 mrg {
5083 1.1 mrg gfc_add_block_to_block (&se->pre, &ploop->pre);
5084 1.1 mrg gfc_add_block_to_block (&se->pre, &ploop->post);
5085 1.1 mrg }
5086 1.1 mrg
5087 1.1 mrg if (expr->rank == 0)
5088 1.1 mrg gfc_cleanup_loop (ploop);
5089 1.1 mrg
5090 1.1 mrg if (norm2)
5091 1.1 mrg {
5092 1.1 mrg /* result = scale * sqrt(result). */
5093 1.1 mrg tree sqrt;
5094 1.1 mrg sqrt = gfc_builtin_decl_for_float_kind (BUILT_IN_SQRT, expr->ts.kind);
5095 1.1 mrg resvar = build_call_expr_loc (input_location,
5096 1.1 mrg sqrt, 1, resvar);
5097 1.1 mrg resvar = fold_build2_loc (input_location, MULT_EXPR, type, scale, resvar);
5098 1.1 mrg }
5099 1.1 mrg
5100 1.1 mrg se->expr = resvar;
5101 1.1 mrg }
5102 1.1 mrg
5103 1.1 mrg
5104 1.1 mrg /* Inline implementation of the dot_product intrinsic. This function
5105 1.1 mrg is based on gfc_conv_intrinsic_arith (the previous function). */
5106 1.1 mrg static void
5107 1.1 mrg gfc_conv_intrinsic_dot_product (gfc_se * se, gfc_expr * expr)
5108 1.1 mrg {
5109 1.1 mrg tree resvar;
5110 1.1 mrg tree type;
5111 1.1 mrg stmtblock_t body;
5112 1.1 mrg stmtblock_t block;
5113 1.1 mrg tree tmp;
5114 1.1 mrg gfc_loopinfo loop;
5115 1.1 mrg gfc_actual_arglist *actual;
5116 1.1 mrg gfc_ss *arrayss1, *arrayss2;
5117 1.1 mrg gfc_se arrayse1, arrayse2;
5118 1.1 mrg gfc_expr *arrayexpr1, *arrayexpr2;
5119 1.1 mrg
5120 1.1 mrg type = gfc_typenode_for_spec (&expr->ts);
5121 1.1 mrg
5122 1.1 mrg /* Initialize the result. */
5123 1.1 mrg resvar = gfc_create_var (type, "val");
5124 1.1 mrg if (expr->ts.type == BT_LOGICAL)
5125 1.1 mrg tmp = build_int_cst (type, 0);
5126 1.1 mrg else
5127 1.1 mrg tmp = gfc_build_const (type, integer_zero_node);
5128 1.1 mrg
5129 1.1 mrg gfc_add_modify (&se->pre, resvar, tmp);
5130 1.1 mrg
5131 1.1 mrg /* Walk argument #1. */
5132 1.1 mrg actual = expr->value.function.actual;
5133 1.1 mrg arrayexpr1 = actual->expr;
5134 1.1 mrg arrayss1 = gfc_walk_expr (arrayexpr1);
5135 1.1 mrg gcc_assert (arrayss1 != gfc_ss_terminator);
5136 1.1 mrg
5137 1.1 mrg /* Walk argument #2. */
5138 1.1 mrg actual = actual->next;
5139 1.1 mrg arrayexpr2 = actual->expr;
5140 1.1 mrg arrayss2 = gfc_walk_expr (arrayexpr2);
5141 1.1 mrg gcc_assert (arrayss2 != gfc_ss_terminator);
5142 1.1 mrg
5143 1.1 mrg /* Initialize the scalarizer. */
5144 1.1 mrg gfc_init_loopinfo (&loop);
5145 1.1 mrg gfc_add_ss_to_loop (&loop, arrayss1);
5146 1.1 mrg gfc_add_ss_to_loop (&loop, arrayss2);
5147 1.1 mrg
5148 1.1 mrg /* Initialize the loop. */
5149 1.1 mrg gfc_conv_ss_startstride (&loop);
5150 1.1 mrg gfc_conv_loop_setup (&loop, &expr->where);
5151 1.1 mrg
5152 1.1 mrg gfc_mark_ss_chain_used (arrayss1, 1);
5153 1.1 mrg gfc_mark_ss_chain_used (arrayss2, 1);
5154 1.1 mrg
5155 1.1 mrg /* Generate the loop body. */
5156 1.1 mrg gfc_start_scalarized_body (&loop, &body);
5157 1.1 mrg gfc_init_block (&block);
5158 1.1 mrg
5159 1.1 mrg /* Make the tree expression for [conjg(]array1[)]. */
5160 1.1 mrg gfc_init_se (&arrayse1, NULL);
5161 1.1 mrg gfc_copy_loopinfo_to_se (&arrayse1, &loop);
5162 1.1 mrg arrayse1.ss = arrayss1;
5163 1.1 mrg gfc_conv_expr_val (&arrayse1, arrayexpr1);
5164 1.1 mrg if (expr->ts.type == BT_COMPLEX)
5165 1.1 mrg arrayse1.expr = fold_build1_loc (input_location, CONJ_EXPR, type,
5166 1.1 mrg arrayse1.expr);
5167 1.1 mrg gfc_add_block_to_block (&block, &arrayse1.pre);
5168 1.1 mrg
5169 1.1 mrg /* Make the tree expression for array2. */
5170 1.1 mrg gfc_init_se (&arrayse2, NULL);
5171 1.1 mrg gfc_copy_loopinfo_to_se (&arrayse2, &loop);
5172 1.1 mrg arrayse2.ss = arrayss2;
5173 1.1 mrg gfc_conv_expr_val (&arrayse2, arrayexpr2);
5174 1.1 mrg gfc_add_block_to_block (&block, &arrayse2.pre);
5175 1.1 mrg
5176 1.1 mrg /* Do the actual product and sum. */
5177 1.1 mrg if (expr->ts.type == BT_LOGICAL)
5178 1.1 mrg {
5179 1.1 mrg tmp = fold_build2_loc (input_location, TRUTH_AND_EXPR, type,
5180 1.1 mrg arrayse1.expr, arrayse2.expr);
5181 1.1 mrg tmp = fold_build2_loc (input_location, TRUTH_OR_EXPR, type, resvar, tmp);
5182 1.1 mrg }
5183 1.1 mrg else
5184 1.1 mrg {
5185 1.1 mrg tmp = fold_build2_loc (input_location, MULT_EXPR, type, arrayse1.expr,
5186 1.1 mrg arrayse2.expr);
5187 1.1 mrg tmp = fold_build2_loc (input_location, PLUS_EXPR, type, resvar, tmp);
5188 1.1 mrg }
5189 1.1 mrg gfc_add_modify (&block, resvar, tmp);
5190 1.1 mrg
5191 1.1 mrg /* Finish up the loop block and the loop. */
5192 1.1 mrg tmp = gfc_finish_block (&block);
5193 1.1 mrg gfc_add_expr_to_block (&body, tmp);
5194 1.1 mrg
5195 1.1 mrg gfc_trans_scalarizing_loops (&loop, &body);
5196 1.1 mrg gfc_add_block_to_block (&se->pre, &loop.pre);
5197 1.1 mrg gfc_add_block_to_block (&se->pre, &loop.post);
5198 1.1 mrg gfc_cleanup_loop (&loop);
5199 1.1 mrg
5200 1.1 mrg se->expr = resvar;
5201 1.1 mrg }
5202 1.1 mrg
5203 1.1 mrg
5204 1.1 mrg /* Emit code for minloc or maxloc intrinsic. There are many different cases
5205 1.1 mrg we need to handle. For performance reasons we sometimes create two
5206 1.1 mrg loops instead of one, where the second one is much simpler.
5207 1.1 mrg Examples for minloc intrinsic:
5208 1.1 mrg 1) Result is an array, a call is generated
5209 1.1 mrg 2) Array mask is used and NaNs need to be supported:
5210 1.1 mrg limit = Infinity;
5211 1.1 mrg pos = 0;
5212 1.1 mrg S = from;
5213 1.1 mrg while (S <= to) {
5214 1.1 mrg if (mask[S]) {
5215 1.1 mrg if (pos == 0) pos = S + (1 - from);
5216 1.1 mrg if (a[S] <= limit) { limit = a[S]; pos = S + (1 - from); goto lab1; }
5217 1.1 mrg }
5218 1.1 mrg S++;
5219 1.1 mrg }
5220 1.1 mrg goto lab2;
5221 1.1 mrg lab1:;
5222 1.1 mrg while (S <= to) {
5223 1.1 mrg if (mask[S]) if (a[S] < limit) { limit = a[S]; pos = S + (1 - from); }
5224 1.1 mrg S++;
5225 1.1 mrg }
5226 1.1 mrg lab2:;
5227 1.1 mrg 3) NaNs need to be supported, but it is known at compile time or cheaply
5228 1.1 mrg at runtime whether array is nonempty or not:
5229 1.1 mrg limit = Infinity;
5230 1.1 mrg pos = 0;
5231 1.1 mrg S = from;
5232 1.1 mrg while (S <= to) {
5233 1.1 mrg if (a[S] <= limit) { limit = a[S]; pos = S + (1 - from); goto lab1; }
5234 1.1 mrg S++;
5235 1.1 mrg }
5236 1.1 mrg if (from <= to) pos = 1;
5237 1.1 mrg goto lab2;
5238 1.1 mrg lab1:;
5239 1.1 mrg while (S <= to) {
5240 1.1 mrg if (a[S] < limit) { limit = a[S]; pos = S + (1 - from); }
5241 1.1 mrg S++;
5242 1.1 mrg }
5243 1.1 mrg lab2:;
5244 1.1 mrg 4) NaNs aren't supported, array mask is used:
5245 1.1 mrg limit = infinities_supported ? Infinity : huge (limit);
5246 1.1 mrg pos = 0;
5247 1.1 mrg S = from;
5248 1.1 mrg while (S <= to) {
5249 1.1 mrg if (mask[S]) { limit = a[S]; pos = S + (1 - from); goto lab1; }
5250 1.1 mrg S++;
5251 1.1 mrg }
5252 1.1 mrg goto lab2;
5253 1.1 mrg lab1:;
5254 1.1 mrg while (S <= to) {
5255 1.1 mrg if (mask[S]) if (a[S] < limit) { limit = a[S]; pos = S + (1 - from); }
5256 1.1 mrg S++;
5257 1.1 mrg }
5258 1.1 mrg lab2:;
5259 1.1 mrg 5) Same without array mask:
5260 1.1 mrg limit = infinities_supported ? Infinity : huge (limit);
5261 1.1 mrg pos = (from <= to) ? 1 : 0;
5262 1.1 mrg S = from;
5263 1.1 mrg while (S <= to) {
5264 1.1 mrg if (a[S] < limit) { limit = a[S]; pos = S + (1 - from); }
5265 1.1 mrg S++;
5266 1.1 mrg }
5267 1.1 mrg For 3) and 5), if mask is scalar, this all goes into a conditional,
5268 1.1 mrg setting pos = 0; in the else branch.
5269 1.1 mrg
5270 1.1 mrg Since we now also support the BACK argument, instead of using
5271 1.1 mrg if (a[S] < limit), we now use
5272 1.1 mrg
5273 1.1 mrg if (back)
5274 1.1 mrg cond = a[S] <= limit;
5275 1.1 mrg else
5276 1.1 mrg cond = a[S] < limit;
5277 1.1 mrg if (cond) {
5278 1.1 mrg ....
5279 1.1 mrg
5280 1.1 mrg The optimizer is smart enough to move the condition out of the loop.
5281 1.1 mrg The are now marked as unlikely to for further speedup. */
5282 1.1 mrg
5283 1.1 mrg static void
5284 1.1 mrg gfc_conv_intrinsic_minmaxloc (gfc_se * se, gfc_expr * expr, enum tree_code op)
5285 1.1 mrg {
5286 1.1 mrg stmtblock_t body;
5287 1.1 mrg stmtblock_t block;
5288 1.1 mrg stmtblock_t ifblock;
5289 1.1 mrg stmtblock_t elseblock;
5290 1.1 mrg tree limit;
5291 1.1 mrg tree type;
5292 1.1 mrg tree tmp;
5293 1.1 mrg tree cond;
5294 1.1 mrg tree elsetmp;
5295 1.1 mrg tree ifbody;
5296 1.1 mrg tree offset;
5297 1.1 mrg tree nonempty;
5298 1.1 mrg tree lab1, lab2;
5299 1.1 mrg tree b_if, b_else;
5300 1.1 mrg gfc_loopinfo loop;
5301 1.1 mrg gfc_actual_arglist *array_arg, *dim_arg, *mask_arg, *kind_arg;
5302 1.1 mrg gfc_actual_arglist *back_arg;
5303 1.1 mrg gfc_ss *arrayss;
5304 1.1 mrg gfc_ss *maskss;
5305 1.1 mrg gfc_se arrayse;
5306 1.1 mrg gfc_se maskse;
5307 1.1 mrg gfc_expr *arrayexpr;
5308 1.1 mrg gfc_expr *maskexpr;
5309 1.1 mrg gfc_expr *backexpr;
5310 1.1 mrg gfc_se backse;
5311 1.1 mrg tree pos;
5312 1.1 mrg int n;
5313 1.1 mrg bool optional_mask;
5314 1.1 mrg
5315 1.1 mrg array_arg = expr->value.function.actual;
5316 1.1 mrg dim_arg = array_arg->next;
5317 1.1 mrg mask_arg = dim_arg->next;
5318 1.1 mrg kind_arg = mask_arg->next;
5319 1.1 mrg back_arg = kind_arg->next;
5320 1.1 mrg
5321 1.1 mrg /* Remove kind. */
5322 1.1 mrg if (kind_arg->expr)
5323 1.1 mrg {
5324 1.1 mrg gfc_free_expr (kind_arg->expr);
5325 1.1 mrg kind_arg->expr = NULL;
5326 1.1 mrg }
5327 1.1 mrg
5328 1.1 mrg /* Pass BACK argument by value. */
5329 1.1 mrg back_arg->name = "%VAL";
5330 1.1 mrg
5331 1.1 mrg if (se->ss)
5332 1.1 mrg {
5333 1.1 mrg gfc_conv_intrinsic_funcall (se, expr);
5334 1.1 mrg return;
5335 1.1 mrg }
5336 1.1 mrg
5337 1.1 mrg arrayexpr = array_arg->expr;
5338 1.1 mrg
5339 1.1 mrg /* Special case for character maxloc. Remove unneeded "dim" actual
5340 1.1 mrg argument, then call a library function. */
5341 1.1 mrg
5342 1.1 mrg if (arrayexpr->ts.type == BT_CHARACTER)
5343 1.1 mrg {
5344 1.1 mrg if (dim_arg->expr)
5345 1.1 mrg {
5346 1.1 mrg gfc_free_expr (dim_arg->expr);
5347 1.1 mrg dim_arg->expr = NULL;
5348 1.1 mrg }
5349 1.1 mrg gfc_conv_intrinsic_funcall (se, expr);
5350 1.1 mrg return;
5351 1.1 mrg }
5352 1.1 mrg
5353 1.1 mrg /* Initialize the result. */
5354 1.1 mrg pos = gfc_create_var (gfc_array_index_type, "pos");
5355 1.1 mrg offset = gfc_create_var (gfc_array_index_type, "offset");
5356 1.1 mrg type = gfc_typenode_for_spec (&expr->ts);
5357 1.1 mrg
5358 1.1 mrg /* Walk the arguments. */
5359 1.1 mrg arrayss = gfc_walk_expr (arrayexpr);
5360 1.1 mrg gcc_assert (arrayss != gfc_ss_terminator);
5361 1.1 mrg
5362 1.1 mrg maskexpr = mask_arg->expr;
5363 1.1 mrg optional_mask = maskexpr && maskexpr->expr_type == EXPR_VARIABLE
5364 1.1 mrg && maskexpr->symtree->n.sym->attr.dummy
5365 1.1 mrg && maskexpr->symtree->n.sym->attr.optional;
5366 1.1 mrg backexpr = back_arg->expr;
5367 1.1 mrg nonempty = NULL;
5368 1.1 mrg if (maskexpr && maskexpr->rank != 0)
5369 1.1 mrg {
5370 1.1 mrg maskss = gfc_walk_expr (maskexpr);
5371 1.1 mrg gcc_assert (maskss != gfc_ss_terminator);
5372 1.1 mrg }
5373 1.1 mrg else
5374 1.1 mrg {
5375 1.1 mrg mpz_t asize;
5376 1.1 mrg if (gfc_array_size (arrayexpr, &asize))
5377 1.1 mrg {
5378 1.1 mrg nonempty = gfc_conv_mpz_to_tree (asize, gfc_index_integer_kind);
5379 1.1 mrg mpz_clear (asize);
5380 1.1 mrg nonempty = fold_build2_loc (input_location, GT_EXPR,
5381 1.1 mrg logical_type_node, nonempty,
5382 1.1 mrg gfc_index_zero_node);
5383 1.1 mrg }
5384 1.1 mrg maskss = NULL;
5385 1.1 mrg }
5386 1.1 mrg
5387 1.1 mrg limit = gfc_create_var (gfc_typenode_for_spec (&arrayexpr->ts), "limit");
5388 1.1 mrg switch (arrayexpr->ts.type)
5389 1.1 mrg {
5390 1.1 mrg case BT_REAL:
5391 1.1 mrg tmp = gfc_build_inf_or_huge (TREE_TYPE (limit), arrayexpr->ts.kind);
5392 1.1 mrg break;
5393 1.1 mrg
5394 1.1 mrg case BT_INTEGER:
5395 1.1 mrg n = gfc_validate_kind (arrayexpr->ts.type, arrayexpr->ts.kind, false);
5396 1.1 mrg tmp = gfc_conv_mpz_to_tree (gfc_integer_kinds[n].huge,
5397 1.1 mrg arrayexpr->ts.kind);
5398 1.1 mrg break;
5399 1.1 mrg
5400 1.1 mrg default:
5401 1.1 mrg gcc_unreachable ();
5402 1.1 mrg }
5403 1.1 mrg
5404 1.1 mrg /* We start with the most negative possible value for MAXLOC, and the most
5405 1.1 mrg positive possible value for MINLOC. The most negative possible value is
5406 1.1 mrg -HUGE for BT_REAL and (-HUGE - 1) for BT_INTEGER; the most positive
5407 1.1 mrg possible value is HUGE in both cases. */
5408 1.1 mrg if (op == GT_EXPR)
5409 1.1 mrg tmp = fold_build1_loc (input_location, NEGATE_EXPR, TREE_TYPE (tmp), tmp);
5410 1.1 mrg if (op == GT_EXPR && arrayexpr->ts.type == BT_INTEGER)
5411 1.1 mrg tmp = fold_build2_loc (input_location, MINUS_EXPR, TREE_TYPE (tmp), tmp,
5412 1.1 mrg build_int_cst (TREE_TYPE (tmp), 1));
5413 1.1 mrg
5414 1.1 mrg gfc_add_modify (&se->pre, limit, tmp);
5415 1.1 mrg
5416 1.1 mrg /* Initialize the scalarizer. */
5417 1.1 mrg gfc_init_loopinfo (&loop);
5418 1.1 mrg
5419 1.1 mrg /* We add the mask first because the number of iterations is taken
5420 1.1 mrg from the last ss, and this breaks if an absent optional argument
5421 1.1 mrg is used for mask. */
5422 1.1 mrg
5423 1.1 mrg if (maskss)
5424 1.1 mrg gfc_add_ss_to_loop (&loop, maskss);
5425 1.1 mrg
5426 1.1 mrg gfc_add_ss_to_loop (&loop, arrayss);
5427 1.1 mrg
5428 1.1 mrg /* Initialize the loop. */
5429 1.1 mrg gfc_conv_ss_startstride (&loop);
5430 1.1 mrg
5431 1.1 mrg /* The code generated can have more than one loop in sequence (see the
5432 1.1 mrg comment at the function header). This doesn't work well with the
5433 1.1 mrg scalarizer, which changes arrays' offset when the scalarization loops
5434 1.1 mrg are generated (see gfc_trans_preloop_setup). Fortunately, {min,max}loc
5435 1.1 mrg are currently inlined in the scalar case only (for which loop is of rank
5436 1.1 mrg one). As there is no dependency to care about in that case, there is no
5437 1.1 mrg temporary, so that we can use the scalarizer temporary code to handle
5438 1.1 mrg multiple loops. Thus, we set temp_dim here, we call gfc_mark_ss_chain_used
5439 1.1 mrg with flag=3 later, and we use gfc_trans_scalarized_loop_boundary even later
5440 1.1 mrg to restore offset.
5441 1.1 mrg TODO: this prevents inlining of rank > 0 minmaxloc calls, so this
5442 1.1 mrg should eventually go away. We could either create two loops properly,
5443 1.1 mrg or find another way to save/restore the array offsets between the two
5444 1.1 mrg loops (without conflicting with temporary management), or use a single
5445 1.1 mrg loop minmaxloc implementation. See PR 31067. */
5446 1.1 mrg loop.temp_dim = loop.dimen;
5447 1.1 mrg gfc_conv_loop_setup (&loop, &expr->where);
5448 1.1 mrg
5449 1.1 mrg gcc_assert (loop.dimen == 1);
5450 1.1 mrg if (nonempty == NULL && maskss == NULL && loop.from[0] && loop.to[0])
5451 1.1 mrg nonempty = fold_build2_loc (input_location, LE_EXPR, logical_type_node,
5452 1.1 mrg loop.from[0], loop.to[0]);
5453 1.1 mrg
5454 1.1 mrg lab1 = NULL;
5455 1.1 mrg lab2 = NULL;
5456 1.1 mrg /* Initialize the position to zero, following Fortran 2003. We are free
5457 1.1 mrg to do this because Fortran 95 allows the result of an entirely false
5458 1.1 mrg mask to be processor dependent. If we know at compile time the array
5459 1.1 mrg is non-empty and no MASK is used, we can initialize to 1 to simplify
5460 1.1 mrg the inner loop. */
5461 1.1 mrg if (nonempty != NULL && !HONOR_NANS (DECL_MODE (limit)))
5462 1.1 mrg gfc_add_modify (&loop.pre, pos,
5463 1.1 mrg fold_build3_loc (input_location, COND_EXPR,
5464 1.1 mrg gfc_array_index_type,
5465 1.1 mrg nonempty, gfc_index_one_node,
5466 1.1 mrg gfc_index_zero_node));
5467 1.1 mrg else
5468 1.1 mrg {
5469 1.1 mrg gfc_add_modify (&loop.pre, pos, gfc_index_zero_node);
5470 1.1 mrg lab1 = gfc_build_label_decl (NULL_TREE);
5471 1.1 mrg TREE_USED (lab1) = 1;
5472 1.1 mrg lab2 = gfc_build_label_decl (NULL_TREE);
5473 1.1 mrg TREE_USED (lab2) = 1;
5474 1.1 mrg }
5475 1.1 mrg
5476 1.1 mrg /* An offset must be added to the loop
5477 1.1 mrg counter to obtain the required position. */
5478 1.1 mrg gcc_assert (loop.from[0]);
5479 1.1 mrg
5480 1.1 mrg tmp = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
5481 1.1 mrg gfc_index_one_node, loop.from[0]);
5482 1.1 mrg gfc_add_modify (&loop.pre, offset, tmp);
5483 1.1 mrg
5484 1.1 mrg gfc_mark_ss_chain_used (arrayss, lab1 ? 3 : 1);
5485 1.1 mrg if (maskss)
5486 1.1 mrg gfc_mark_ss_chain_used (maskss, lab1 ? 3 : 1);
5487 1.1 mrg /* Generate the loop body. */
5488 1.1 mrg gfc_start_scalarized_body (&loop, &body);
5489 1.1 mrg
5490 1.1 mrg /* If we have a mask, only check this element if the mask is set. */
5491 1.1 mrg if (maskss)
5492 1.1 mrg {
5493 1.1 mrg gfc_init_se (&maskse, NULL);
5494 1.1 mrg gfc_copy_loopinfo_to_se (&maskse, &loop);
5495 1.1 mrg maskse.ss = maskss;
5496 1.1 mrg gfc_conv_expr_val (&maskse, maskexpr);
5497 1.1 mrg gfc_add_block_to_block (&body, &maskse.pre);
5498 1.1 mrg
5499 1.1 mrg gfc_start_block (&block);
5500 1.1 mrg }
5501 1.1 mrg else
5502 1.1 mrg gfc_init_block (&block);
5503 1.1 mrg
5504 1.1 mrg /* Compare with the current limit. */
5505 1.1 mrg gfc_init_se (&arrayse, NULL);
5506 1.1 mrg gfc_copy_loopinfo_to_se (&arrayse, &loop);
5507 1.1 mrg arrayse.ss = arrayss;
5508 1.1 mrg gfc_conv_expr_val (&arrayse, arrayexpr);
5509 1.1 mrg gfc_add_block_to_block (&block, &arrayse.pre);
5510 1.1 mrg
5511 1.1 mrg gfc_init_se (&backse, NULL);
5512 1.1 mrg gfc_conv_expr_val (&backse, backexpr);
5513 1.1 mrg gfc_add_block_to_block (&block, &backse.pre);
5514 1.1 mrg
5515 1.1 mrg /* We do the following if this is a more extreme value. */
5516 1.1 mrg gfc_start_block (&ifblock);
5517 1.1 mrg
5518 1.1 mrg /* Assign the value to the limit... */
5519 1.1 mrg gfc_add_modify (&ifblock, limit, arrayse.expr);
5520 1.1 mrg
5521 1.1 mrg if (nonempty == NULL && HONOR_NANS (DECL_MODE (limit)))
5522 1.1 mrg {
5523 1.1 mrg stmtblock_t ifblock2;
5524 1.1 mrg tree ifbody2;
5525 1.1 mrg
5526 1.1 mrg gfc_start_block (&ifblock2);
5527 1.1 mrg tmp = fold_build2_loc (input_location, PLUS_EXPR, TREE_TYPE (pos),
5528 1.1 mrg loop.loopvar[0], offset);
5529 1.1 mrg gfc_add_modify (&ifblock2, pos, tmp);
5530 1.1 mrg ifbody2 = gfc_finish_block (&ifblock2);
5531 1.1 mrg cond = fold_build2_loc (input_location, EQ_EXPR, logical_type_node, pos,
5532 1.1 mrg gfc_index_zero_node);
5533 1.1 mrg tmp = build3_v (COND_EXPR, cond, ifbody2,
5534 1.1 mrg build_empty_stmt (input_location));
5535 1.1 mrg gfc_add_expr_to_block (&block, tmp);
5536 1.1 mrg }
5537 1.1 mrg
5538 1.1 mrg tmp = fold_build2_loc (input_location, PLUS_EXPR, TREE_TYPE (pos),
5539 1.1 mrg loop.loopvar[0], offset);
5540 1.1 mrg gfc_add_modify (&ifblock, pos, tmp);
5541 1.1 mrg
5542 1.1 mrg if (lab1)
5543 1.1 mrg gfc_add_expr_to_block (&ifblock, build1_v (GOTO_EXPR, lab1));
5544 1.1 mrg
5545 1.1 mrg ifbody = gfc_finish_block (&ifblock);
5546 1.1 mrg
5547 1.1 mrg if (!lab1 || HONOR_NANS (DECL_MODE (limit)))
5548 1.1 mrg {
5549 1.1 mrg if (lab1)
5550 1.1 mrg cond = fold_build2_loc (input_location,
5551 1.1 mrg op == GT_EXPR ? GE_EXPR : LE_EXPR,
5552 1.1 mrg logical_type_node, arrayse.expr, limit);
5553 1.1 mrg else
5554 1.1 mrg {
5555 1.1 mrg tree ifbody2, elsebody2;
5556 1.1 mrg
5557 1.1 mrg /* We switch to > or >= depending on the value of the BACK argument. */
5558 1.1 mrg cond = gfc_create_var (logical_type_node, "cond");
5559 1.1 mrg
5560 1.1 mrg gfc_start_block (&ifblock);
5561 1.1 mrg b_if = fold_build2_loc (input_location, op == GT_EXPR ? GE_EXPR : LE_EXPR,
5562 1.1 mrg logical_type_node, arrayse.expr, limit);
5563 1.1 mrg
5564 1.1 mrg gfc_add_modify (&ifblock, cond, b_if);
5565 1.1 mrg ifbody2 = gfc_finish_block (&ifblock);
5566 1.1 mrg
5567 1.1 mrg gfc_start_block (&elseblock);
5568 1.1 mrg b_else = fold_build2_loc (input_location, op, logical_type_node,
5569 1.1 mrg arrayse.expr, limit);
5570 1.1 mrg
5571 1.1 mrg gfc_add_modify (&elseblock, cond, b_else);
5572 1.1 mrg elsebody2 = gfc_finish_block (&elseblock);
5573 1.1 mrg
5574 1.1 mrg tmp = fold_build3_loc (input_location, COND_EXPR, logical_type_node,
5575 1.1 mrg backse.expr, ifbody2, elsebody2);
5576 1.1 mrg
5577 1.1 mrg gfc_add_expr_to_block (&block, tmp);
5578 1.1 mrg }
5579 1.1 mrg
5580 1.1 mrg cond = gfc_unlikely (cond, PRED_BUILTIN_EXPECT);
5581 1.1 mrg ifbody = build3_v (COND_EXPR, cond, ifbody,
5582 1.1 mrg build_empty_stmt (input_location));
5583 1.1 mrg }
5584 1.1 mrg gfc_add_expr_to_block (&block, ifbody);
5585 1.1 mrg
5586 1.1 mrg if (maskss)
5587 1.1 mrg {
5588 1.1 mrg /* We enclose the above in if (mask) {...}. If the mask is an
5589 1.1 mrg optional argument, generate IF (.NOT. PRESENT(MASK)
5590 1.1 mrg .OR. MASK(I)). */
5591 1.1 mrg
5592 1.1 mrg tree ifmask;
5593 1.1 mrg ifmask = conv_mask_condition (&maskse, maskexpr, optional_mask);
5594 1.1 mrg tmp = gfc_finish_block (&block);
5595 1.1 mrg tmp = build3_v (COND_EXPR, ifmask, tmp,
5596 1.1 mrg build_empty_stmt (input_location));
5597 1.1 mrg }
5598 1.1 mrg else
5599 1.1 mrg tmp = gfc_finish_block (&block);
5600 1.1 mrg gfc_add_expr_to_block (&body, tmp);
5601 1.1 mrg
5602 1.1 mrg if (lab1)
5603 1.1 mrg {
5604 1.1 mrg gfc_trans_scalarized_loop_boundary (&loop, &body);
5605 1.1 mrg
5606 1.1 mrg if (HONOR_NANS (DECL_MODE (limit)))
5607 1.1 mrg {
5608 1.1 mrg if (nonempty != NULL)
5609 1.1 mrg {
5610 1.1 mrg ifbody = build2_v (MODIFY_EXPR, pos, gfc_index_one_node);
5611 1.1 mrg tmp = build3_v (COND_EXPR, nonempty, ifbody,
5612 1.1 mrg build_empty_stmt (input_location));
5613 1.1 mrg gfc_add_expr_to_block (&loop.code[0], tmp);
5614 1.1 mrg }
5615 1.1 mrg }
5616 1.1 mrg
5617 1.1 mrg gfc_add_expr_to_block (&loop.code[0], build1_v (GOTO_EXPR, lab2));
5618 1.1 mrg gfc_add_expr_to_block (&loop.code[0], build1_v (LABEL_EXPR, lab1));
5619 1.1 mrg
5620 1.1 mrg /* If we have a mask, only check this element if the mask is set. */
5621 1.1 mrg if (maskss)
5622 1.1 mrg {
5623 1.1 mrg gfc_init_se (&maskse, NULL);
5624 1.1 mrg gfc_copy_loopinfo_to_se (&maskse, &loop);
5625 1.1 mrg maskse.ss = maskss;
5626 1.1 mrg gfc_conv_expr_val (&maskse, maskexpr);
5627 1.1 mrg gfc_add_block_to_block (&body, &maskse.pre);
5628 1.1 mrg
5629 1.1 mrg gfc_start_block (&block);
5630 1.1 mrg }
5631 1.1 mrg else
5632 1.1 mrg gfc_init_block (&block);
5633 1.1 mrg
5634 1.1 mrg /* Compare with the current limit. */
5635 1.1 mrg gfc_init_se (&arrayse, NULL);
5636 1.1 mrg gfc_copy_loopinfo_to_se (&arrayse, &loop);
5637 1.1 mrg arrayse.ss = arrayss;
5638 1.1 mrg gfc_conv_expr_val (&arrayse, arrayexpr);
5639 1.1 mrg gfc_add_block_to_block (&block, &arrayse.pre);
5640 1.1 mrg
5641 1.1 mrg /* We do the following if this is a more extreme value. */
5642 1.1 mrg gfc_start_block (&ifblock);
5643 1.1 mrg
5644 1.1 mrg /* Assign the value to the limit... */
5645 1.1 mrg gfc_add_modify (&ifblock, limit, arrayse.expr);
5646 1.1 mrg
5647 1.1 mrg tmp = fold_build2_loc (input_location, PLUS_EXPR, TREE_TYPE (pos),
5648 1.1 mrg loop.loopvar[0], offset);
5649 1.1 mrg gfc_add_modify (&ifblock, pos, tmp);
5650 1.1 mrg
5651 1.1 mrg ifbody = gfc_finish_block (&ifblock);
5652 1.1 mrg
5653 1.1 mrg /* We switch to > or >= depending on the value of the BACK argument. */
5654 1.1 mrg {
5655 1.1 mrg tree ifbody2, elsebody2;
5656 1.1 mrg
5657 1.1 mrg cond = gfc_create_var (logical_type_node, "cond");
5658 1.1 mrg
5659 1.1 mrg gfc_start_block (&ifblock);
5660 1.1 mrg b_if = fold_build2_loc (input_location, op == GT_EXPR ? GE_EXPR : LE_EXPR,
5661 1.1 mrg logical_type_node, arrayse.expr, limit);
5662 1.1 mrg
5663 1.1 mrg gfc_add_modify (&ifblock, cond, b_if);
5664 1.1 mrg ifbody2 = gfc_finish_block (&ifblock);
5665 1.1 mrg
5666 1.1 mrg gfc_start_block (&elseblock);
5667 1.1 mrg b_else = fold_build2_loc (input_location, op, logical_type_node,
5668 1.1 mrg arrayse.expr, limit);
5669 1.1 mrg
5670 1.1 mrg gfc_add_modify (&elseblock, cond, b_else);
5671 1.1 mrg elsebody2 = gfc_finish_block (&elseblock);
5672 1.1 mrg
5673 1.1 mrg tmp = fold_build3_loc (input_location, COND_EXPR, logical_type_node,
5674 1.1 mrg backse.expr, ifbody2, elsebody2);
5675 1.1 mrg }
5676 1.1 mrg
5677 1.1 mrg gfc_add_expr_to_block (&block, tmp);
5678 1.1 mrg cond = gfc_unlikely (cond, PRED_BUILTIN_EXPECT);
5679 1.1 mrg tmp = build3_v (COND_EXPR, cond, ifbody,
5680 1.1 mrg build_empty_stmt (input_location));
5681 1.1 mrg
5682 1.1 mrg gfc_add_expr_to_block (&block, tmp);
5683 1.1 mrg
5684 1.1 mrg if (maskss)
5685 1.1 mrg {
5686 1.1 mrg /* We enclose the above in if (mask) {...}. If the mask is
5687 1.1 mrg an optional argument, generate IF (.NOT. PRESENT(MASK)
5688 1.1 mrg .OR. MASK(I)).*/
5689 1.1 mrg
5690 1.1 mrg tree ifmask;
5691 1.1 mrg ifmask = conv_mask_condition (&maskse, maskexpr, optional_mask);
5692 1.1 mrg tmp = gfc_finish_block (&block);
5693 1.1 mrg tmp = build3_v (COND_EXPR, ifmask, tmp,
5694 1.1 mrg build_empty_stmt (input_location));
5695 1.1 mrg }
5696 1.1 mrg else
5697 1.1 mrg tmp = gfc_finish_block (&block);
5698 1.1 mrg gfc_add_expr_to_block (&body, tmp);
5699 1.1 mrg /* Avoid initializing loopvar[0] again, it should be left where
5700 1.1 mrg it finished by the first loop. */
5701 1.1 mrg loop.from[0] = loop.loopvar[0];
5702 1.1 mrg }
5703 1.1 mrg
5704 1.1 mrg gfc_trans_scalarizing_loops (&loop, &body);
5705 1.1 mrg
5706 1.1 mrg if (lab2)
5707 1.1 mrg gfc_add_expr_to_block (&loop.pre, build1_v (LABEL_EXPR, lab2));
5708 1.1 mrg
5709 1.1 mrg /* For a scalar mask, enclose the loop in an if statement. */
5710 1.1 mrg if (maskexpr && maskss == NULL)
5711 1.1 mrg {
5712 1.1 mrg tree ifmask;
5713 1.1 mrg
5714 1.1 mrg gfc_init_se (&maskse, NULL);
5715 1.1 mrg gfc_conv_expr_val (&maskse, maskexpr);
5716 1.1 mrg gfc_init_block (&block);
5717 1.1 mrg gfc_add_block_to_block (&block, &loop.pre);
5718 1.1 mrg gfc_add_block_to_block (&block, &loop.post);
5719 1.1 mrg tmp = gfc_finish_block (&block);
5720 1.1 mrg
5721 1.1 mrg /* For the else part of the scalar mask, just initialize
5722 1.1 mrg the pos variable the same way as above. */
5723 1.1 mrg
5724 1.1 mrg gfc_init_block (&elseblock);
5725 1.1 mrg gfc_add_modify (&elseblock, pos, gfc_index_zero_node);
5726 1.1 mrg elsetmp = gfc_finish_block (&elseblock);
5727 1.1 mrg ifmask = conv_mask_condition (&maskse, maskexpr, optional_mask);
5728 1.1 mrg tmp = build3_v (COND_EXPR, ifmask, tmp, elsetmp);
5729 1.1 mrg gfc_add_expr_to_block (&block, tmp);
5730 1.1 mrg gfc_add_block_to_block (&se->pre, &block);
5731 1.1 mrg }
5732 1.1 mrg else
5733 1.1 mrg {
5734 1.1 mrg gfc_add_block_to_block (&se->pre, &loop.pre);
5735 1.1 mrg gfc_add_block_to_block (&se->pre, &loop.post);
5736 1.1 mrg }
5737 1.1 mrg gfc_cleanup_loop (&loop);
5738 1.1 mrg
5739 1.1 mrg se->expr = convert (type, pos);
5740 1.1 mrg }
5741 1.1 mrg
5742 1.1 mrg /* Emit code for findloc. */
5743 1.1 mrg
5744 1.1 mrg static void
5745 1.1 mrg gfc_conv_intrinsic_findloc (gfc_se *se, gfc_expr *expr)
5746 1.1 mrg {
5747 1.1 mrg gfc_actual_arglist *array_arg, *value_arg, *dim_arg, *mask_arg,
5748 1.1 mrg *kind_arg, *back_arg;
5749 1.1 mrg gfc_expr *value_expr;
5750 1.1 mrg int ikind;
5751 1.1 mrg tree resvar;
5752 1.1 mrg stmtblock_t block;
5753 1.1 mrg stmtblock_t body;
5754 1.1 mrg stmtblock_t loopblock;
5755 1.1 mrg tree type;
5756 1.1 mrg tree tmp;
5757 1.1 mrg tree found;
5758 1.1 mrg tree forward_branch = NULL_TREE;
5759 1.1 mrg tree back_branch;
5760 1.1 mrg gfc_loopinfo loop;
5761 1.1 mrg gfc_ss *arrayss;
5762 1.1 mrg gfc_ss *maskss;
5763 1.1 mrg gfc_se arrayse;
5764 1.1 mrg gfc_se valuese;
5765 1.1 mrg gfc_se maskse;
5766 1.1 mrg gfc_se backse;
5767 1.1 mrg tree exit_label;
5768 1.1 mrg gfc_expr *maskexpr;
5769 1.1 mrg tree offset;
5770 1.1 mrg int i;
5771 1.1 mrg bool optional_mask;
5772 1.1 mrg
5773 1.1 mrg array_arg = expr->value.function.actual;
5774 1.1 mrg value_arg = array_arg->next;
5775 1.1 mrg dim_arg = value_arg->next;
5776 1.1 mrg mask_arg = dim_arg->next;
5777 1.1 mrg kind_arg = mask_arg->next;
5778 1.1 mrg back_arg = kind_arg->next;
5779 1.1 mrg
5780 1.1 mrg /* Remove kind and set ikind. */
5781 1.1 mrg if (kind_arg->expr)
5782 1.1 mrg {
5783 1.1 mrg ikind = mpz_get_si (kind_arg->expr->value.integer);
5784 1.1 mrg gfc_free_expr (kind_arg->expr);
5785 1.1 mrg kind_arg->expr = NULL;
5786 1.1 mrg }
5787 1.1 mrg else
5788 1.1 mrg ikind = gfc_default_integer_kind;
5789 1.1 mrg
5790 1.1 mrg value_expr = value_arg->expr;
5791 1.1 mrg
5792 1.1 mrg /* Unless it's a string, pass VALUE by value. */
5793 1.1 mrg if (value_expr->ts.type != BT_CHARACTER)
5794 1.1 mrg value_arg->name = "%VAL";
5795 1.1 mrg
5796 1.1 mrg /* Pass BACK argument by value. */
5797 1.1 mrg back_arg->name = "%VAL";
5798 1.1 mrg
5799 1.1 mrg /* Call the library if we have a character function or if
5800 1.1 mrg rank > 0. */
5801 1.1 mrg if (se->ss || array_arg->expr->ts.type == BT_CHARACTER)
5802 1.1 mrg {
5803 1.1 mrg se->ignore_optional = 1;
5804 1.1 mrg if (expr->rank == 0)
5805 1.1 mrg {
5806 1.1 mrg /* Remove dim argument. */
5807 1.1 mrg gfc_free_expr (dim_arg->expr);
5808 1.1 mrg dim_arg->expr = NULL;
5809 1.1 mrg }
5810 1.1 mrg gfc_conv_intrinsic_funcall (se, expr);
5811 1.1 mrg return;
5812 1.1 mrg }
5813 1.1 mrg
5814 1.1 mrg type = gfc_get_int_type (ikind);
5815 1.1 mrg
5816 1.1 mrg /* Initialize the result. */
5817 1.1 mrg resvar = gfc_create_var (gfc_array_index_type, "pos");
5818 1.1 mrg gfc_add_modify (&se->pre, resvar, build_int_cst (gfc_array_index_type, 0));
5819 1.1 mrg offset = gfc_create_var (gfc_array_index_type, "offset");
5820 1.1 mrg
5821 1.1 mrg maskexpr = mask_arg->expr;
5822 1.1 mrg optional_mask = maskexpr && maskexpr->expr_type == EXPR_VARIABLE
5823 1.1 mrg && maskexpr->symtree->n.sym->attr.dummy
5824 1.1 mrg && maskexpr->symtree->n.sym->attr.optional;
5825 1.1 mrg
5826 1.1 mrg /* Generate two loops, one for BACK=.true. and one for BACK=.false. */
5827 1.1 mrg
5828 1.1 mrg for (i = 0 ; i < 2; i++)
5829 1.1 mrg {
5830 1.1 mrg /* Walk the arguments. */
5831 1.1 mrg arrayss = gfc_walk_expr (array_arg->expr);
5832 1.1 mrg gcc_assert (arrayss != gfc_ss_terminator);
5833 1.1 mrg
5834 1.1 mrg if (maskexpr && maskexpr->rank != 0)
5835 1.1 mrg {
5836 1.1 mrg maskss = gfc_walk_expr (maskexpr);
5837 1.1 mrg gcc_assert (maskss != gfc_ss_terminator);
5838 1.1 mrg }
5839 1.1 mrg else
5840 1.1 mrg maskss = NULL;
5841 1.1 mrg
5842 1.1 mrg /* Initialize the scalarizer. */
5843 1.1 mrg gfc_init_loopinfo (&loop);
5844 1.1 mrg exit_label = gfc_build_label_decl (NULL_TREE);
5845 1.1 mrg TREE_USED (exit_label) = 1;
5846 1.1 mrg
5847 1.1 mrg /* We add the mask first because the number of iterations is
5848 1.1 mrg taken from the last ss, and this breaks if an absent
5849 1.1 mrg optional argument is used for mask. */
5850 1.1 mrg
5851 1.1 mrg if (maskss)
5852 1.1 mrg gfc_add_ss_to_loop (&loop, maskss);
5853 1.1 mrg gfc_add_ss_to_loop (&loop, arrayss);
5854 1.1 mrg
5855 1.1 mrg /* Initialize the loop. */
5856 1.1 mrg gfc_conv_ss_startstride (&loop);
5857 1.1 mrg gfc_conv_loop_setup (&loop, &expr->where);
5858 1.1 mrg
5859 1.1 mrg /* Calculate the offset. */
5860 1.1 mrg tmp = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
5861 1.1 mrg gfc_index_one_node, loop.from[0]);
5862 1.1 mrg gfc_add_modify (&loop.pre, offset, tmp);
5863 1.1 mrg
5864 1.1 mrg gfc_mark_ss_chain_used (arrayss, 1);
5865 1.1 mrg if (maskss)
5866 1.1 mrg gfc_mark_ss_chain_used (maskss, 1);
5867 1.1 mrg
5868 1.1 mrg /* The first loop is for BACK=.true. */
5869 1.1 mrg if (i == 0)
5870 1.1 mrg loop.reverse[0] = GFC_REVERSE_SET;
5871 1.1 mrg
5872 1.1 mrg /* Generate the loop body. */
5873 1.1 mrg gfc_start_scalarized_body (&loop, &body);
5874 1.1 mrg
5875 1.1 mrg /* If we have an array mask, only add the element if it is
5876 1.1 mrg set. */
5877 1.1 mrg if (maskss)
5878 1.1 mrg {
5879 1.1 mrg gfc_init_se (&maskse, NULL);
5880 1.1 mrg gfc_copy_loopinfo_to_se (&maskse, &loop);
5881 1.1 mrg maskse.ss = maskss;
5882 1.1 mrg gfc_conv_expr_val (&maskse, maskexpr);
5883 1.1 mrg gfc_add_block_to_block (&body, &maskse.pre);
5884 1.1 mrg }
5885 1.1 mrg
5886 1.1 mrg /* If the condition matches then set the return value. */
5887 1.1 mrg gfc_start_block (&block);
5888 1.1 mrg
5889 1.1 mrg /* Add the offset. */
5890 1.1 mrg tmp = fold_build2_loc (input_location, PLUS_EXPR,
5891 1.1 mrg TREE_TYPE (resvar),
5892 1.1 mrg loop.loopvar[0], offset);
5893 1.1 mrg gfc_add_modify (&block, resvar, tmp);
5894 1.1 mrg /* And break out of the loop. */
5895 1.1 mrg tmp = build1_v (GOTO_EXPR, exit_label);
5896 1.1 mrg gfc_add_expr_to_block (&block, tmp);
5897 1.1 mrg
5898 1.1 mrg found = gfc_finish_block (&block);
5899 1.1 mrg
5900 1.1 mrg /* Check this element. */
5901 1.1 mrg gfc_init_se (&arrayse, NULL);
5902 1.1 mrg gfc_copy_loopinfo_to_se (&arrayse, &loop);
5903 1.1 mrg arrayse.ss = arrayss;
5904 1.1 mrg gfc_conv_expr_val (&arrayse, array_arg->expr);
5905 1.1 mrg gfc_add_block_to_block (&body, &arrayse.pre);
5906 1.1 mrg
5907 1.1 mrg gfc_init_se (&valuese, NULL);
5908 1.1 mrg gfc_conv_expr_val (&valuese, value_arg->expr);
5909 1.1 mrg gfc_add_block_to_block (&body, &valuese.pre);
5910 1.1 mrg
5911 1.1 mrg tmp = fold_build2_loc (input_location, EQ_EXPR, logical_type_node,
5912 1.1 mrg arrayse.expr, valuese.expr);
5913 1.1 mrg
5914 1.1 mrg tmp = build3_v (COND_EXPR, tmp, found, build_empty_stmt (input_location));
5915 1.1 mrg if (maskss)
5916 1.1 mrg {
5917 1.1 mrg /* We enclose the above in if (mask) {...}. If the mask is
5918 1.1 mrg an optional argument, generate IF (.NOT. PRESENT(MASK)
5919 1.1 mrg .OR. MASK(I)). */
5920 1.1 mrg
5921 1.1 mrg tree ifmask;
5922 1.1 mrg ifmask = conv_mask_condition (&maskse, maskexpr, optional_mask);
5923 1.1 mrg tmp = build3_v (COND_EXPR, ifmask, tmp,
5924 1.1 mrg build_empty_stmt (input_location));
5925 1.1 mrg }
5926 1.1 mrg
5927 1.1 mrg gfc_add_expr_to_block (&body, tmp);
5928 1.1 mrg gfc_add_block_to_block (&body, &arrayse.post);
5929 1.1 mrg
5930 1.1 mrg gfc_trans_scalarizing_loops (&loop, &body);
5931 1.1 mrg
5932 1.1 mrg /* Add the exit label. */
5933 1.1 mrg tmp = build1_v (LABEL_EXPR, exit_label);
5934 1.1 mrg gfc_add_expr_to_block (&loop.pre, tmp);
5935 1.1 mrg gfc_start_block (&loopblock);
5936 1.1 mrg gfc_add_block_to_block (&loopblock, &loop.pre);
5937 1.1 mrg gfc_add_block_to_block (&loopblock, &loop.post);
5938 1.1 mrg if (i == 0)
5939 1.1 mrg forward_branch = gfc_finish_block (&loopblock);
5940 1.1 mrg else
5941 1.1 mrg back_branch = gfc_finish_block (&loopblock);
5942 1.1 mrg
5943 1.1 mrg gfc_cleanup_loop (&loop);
5944 1.1 mrg }
5945 1.1 mrg
5946 1.1 mrg /* Enclose the two loops in an IF statement. */
5947 1.1 mrg
5948 1.1 mrg gfc_init_se (&backse, NULL);
5949 1.1 mrg gfc_conv_expr_val (&backse, back_arg->expr);
5950 1.1 mrg gfc_add_block_to_block (&se->pre, &backse.pre);
5951 1.1 mrg tmp = build3_v (COND_EXPR, backse.expr, forward_branch, back_branch);
5952 1.1 mrg
5953 1.1 mrg /* For a scalar mask, enclose the loop in an if statement. */
5954 1.1 mrg if (maskexpr && maskss == NULL)
5955 1.1 mrg {
5956 1.1 mrg tree ifmask;
5957 1.1 mrg tree if_stmt;
5958 1.1 mrg
5959 1.1 mrg gfc_init_se (&maskse, NULL);
5960 1.1 mrg gfc_conv_expr_val (&maskse, maskexpr);
5961 1.1 mrg gfc_init_block (&block);
5962 1.1 mrg gfc_add_expr_to_block (&block, maskse.expr);
5963 1.1 mrg ifmask = conv_mask_condition (&maskse, maskexpr, optional_mask);
5964 1.1 mrg if_stmt = build3_v (COND_EXPR, ifmask, tmp,
5965 1.1 mrg build_empty_stmt (input_location));
5966 1.1 mrg gfc_add_expr_to_block (&block, if_stmt);
5967 1.1 mrg tmp = gfc_finish_block (&block);
5968 1.1 mrg }
5969 1.1 mrg
5970 1.1 mrg gfc_add_expr_to_block (&se->pre, tmp);
5971 1.1 mrg se->expr = convert (type, resvar);
5972 1.1 mrg
5973 1.1 mrg }
5974 1.1 mrg
5975 1.1 mrg /* Emit code for minval or maxval intrinsic. There are many different cases
5976 1.1 mrg we need to handle. For performance reasons we sometimes create two
5977 1.1 mrg loops instead of one, where the second one is much simpler.
5978 1.1 mrg Examples for minval intrinsic:
5979 1.1 mrg 1) Result is an array, a call is generated
5980 1.1 mrg 2) Array mask is used and NaNs need to be supported, rank 1:
5981 1.1 mrg limit = Infinity;
5982 1.1 mrg nonempty = false;
5983 1.1 mrg S = from;
5984 1.1 mrg while (S <= to) {
5985 1.1 mrg if (mask[S]) { nonempty = true; if (a[S] <= limit) goto lab; }
5986 1.1 mrg S++;
5987 1.1 mrg }
5988 1.1 mrg limit = nonempty ? NaN : huge (limit);
5989 1.1 mrg lab:
5990 1.1 mrg while (S <= to) { if(mask[S]) limit = min (a[S], limit); S++; }
5991 1.1 mrg 3) NaNs need to be supported, but it is known at compile time or cheaply
5992 1.1 mrg at runtime whether array is nonempty or not, rank 1:
5993 1.1 mrg limit = Infinity;
5994 1.1 mrg S = from;
5995 1.1 mrg while (S <= to) { if (a[S] <= limit) goto lab; S++; }
5996 1.1 mrg limit = (from <= to) ? NaN : huge (limit);
5997 1.1 mrg lab:
5998 1.1 mrg while (S <= to) { limit = min (a[S], limit); S++; }
5999 1.1 mrg 4) Array mask is used and NaNs need to be supported, rank > 1:
6000 1.1 mrg limit = Infinity;
6001 1.1 mrg nonempty = false;
6002 1.1 mrg fast = false;
6003 1.1 mrg S1 = from1;
6004 1.1 mrg while (S1 <= to1) {
6005 1.1 mrg S2 = from2;
6006 1.1 mrg while (S2 <= to2) {
6007 1.1 mrg if (mask[S1][S2]) {
6008 1.1 mrg if (fast) limit = min (a[S1][S2], limit);
6009 1.1 mrg else {
6010 1.1 mrg nonempty = true;
6011 1.1 mrg if (a[S1][S2] <= limit) {
6012 1.1 mrg limit = a[S1][S2];
6013 1.1 mrg fast = true;
6014 1.1 mrg }
6015 1.1 mrg }
6016 1.1 mrg }
6017 1.1 mrg S2++;
6018 1.1 mrg }
6019 1.1 mrg S1++;
6020 1.1 mrg }
6021 1.1 mrg if (!fast)
6022 1.1 mrg limit = nonempty ? NaN : huge (limit);
6023 1.1 mrg 5) NaNs need to be supported, but it is known at compile time or cheaply
6024 1.1 mrg at runtime whether array is nonempty or not, rank > 1:
6025 1.1 mrg limit = Infinity;
6026 1.1 mrg fast = false;
6027 1.1 mrg S1 = from1;
6028 1.1 mrg while (S1 <= to1) {
6029 1.1 mrg S2 = from2;
6030 1.1 mrg while (S2 <= to2) {
6031 1.1 mrg if (fast) limit = min (a[S1][S2], limit);
6032 1.1 mrg else {
6033 1.1 mrg if (a[S1][S2] <= limit) {
6034 1.1 mrg limit = a[S1][S2];
6035 1.1 mrg fast = true;
6036 1.1 mrg }
6037 1.1 mrg }
6038 1.1 mrg S2++;
6039 1.1 mrg }
6040 1.1 mrg S1++;
6041 1.1 mrg }
6042 1.1 mrg if (!fast)
6043 1.1 mrg limit = (nonempty_array) ? NaN : huge (limit);
6044 1.1 mrg 6) NaNs aren't supported, but infinities are. Array mask is used:
6045 1.1 mrg limit = Infinity;
6046 1.1 mrg nonempty = false;
6047 1.1 mrg S = from;
6048 1.1 mrg while (S <= to) {
6049 1.1 mrg if (mask[S]) { nonempty = true; limit = min (a[S], limit); }
6050 1.1 mrg S++;
6051 1.1 mrg }
6052 1.1 mrg limit = nonempty ? limit : huge (limit);
6053 1.1 mrg 7) Same without array mask:
6054 1.1 mrg limit = Infinity;
6055 1.1 mrg S = from;
6056 1.1 mrg while (S <= to) { limit = min (a[S], limit); S++; }
6057 1.1 mrg limit = (from <= to) ? limit : huge (limit);
6058 1.1 mrg 8) Neither NaNs nor infinities are supported (-ffast-math or BT_INTEGER):
6059 1.1 mrg limit = huge (limit);
6060 1.1 mrg S = from;
6061 1.1 mrg while (S <= to) { limit = min (a[S], limit); S++); }
6062 1.1 mrg (or
6063 1.1 mrg while (S <= to) { if (mask[S]) limit = min (a[S], limit); S++; }
6064 1.1 mrg with array mask instead).
6065 1.1 mrg For 3), 5), 7) and 8), if mask is scalar, this all goes into a conditional,
6066 1.1 mrg setting limit = huge (limit); in the else branch. */
6067 1.1 mrg
6068 1.1 mrg static void
6069 1.1 mrg gfc_conv_intrinsic_minmaxval (gfc_se * se, gfc_expr * expr, enum tree_code op)
6070 1.1 mrg {
6071 1.1 mrg tree limit;
6072 1.1 mrg tree type;
6073 1.1 mrg tree tmp;
6074 1.1 mrg tree ifbody;
6075 1.1 mrg tree nonempty;
6076 1.1 mrg tree nonempty_var;
6077 1.1 mrg tree lab;
6078 1.1 mrg tree fast;
6079 1.1 mrg tree huge_cst = NULL, nan_cst = NULL;
6080 1.1 mrg stmtblock_t body;
6081 1.1 mrg stmtblock_t block, block2;
6082 1.1 mrg gfc_loopinfo loop;
6083 1.1 mrg gfc_actual_arglist *actual;
6084 1.1 mrg gfc_ss *arrayss;
6085 1.1 mrg gfc_ss *maskss;
6086 1.1 mrg gfc_se arrayse;
6087 1.1 mrg gfc_se maskse;
6088 1.1 mrg gfc_expr *arrayexpr;
6089 1.1 mrg gfc_expr *maskexpr;
6090 1.1 mrg int n;
6091 1.1 mrg bool optional_mask;
6092 1.1 mrg
6093 1.1 mrg if (se->ss)
6094 1.1 mrg {
6095 1.1 mrg gfc_conv_intrinsic_funcall (se, expr);
6096 1.1 mrg return;
6097 1.1 mrg }
6098 1.1 mrg
6099 1.1 mrg actual = expr->value.function.actual;
6100 1.1 mrg arrayexpr = actual->expr;
6101 1.1 mrg
6102 1.1 mrg if (arrayexpr->ts.type == BT_CHARACTER)
6103 1.1 mrg {
6104 1.1 mrg gfc_actual_arglist *dim = actual->next;
6105 1.1 mrg if (expr->rank == 0 && dim->expr != 0)
6106 1.1 mrg {
6107 1.1 mrg gfc_free_expr (dim->expr);
6108 1.1 mrg dim->expr = NULL;
6109 1.1 mrg }
6110 1.1 mrg gfc_conv_intrinsic_funcall (se, expr);
6111 1.1 mrg return;
6112 1.1 mrg }
6113 1.1 mrg
6114 1.1 mrg type = gfc_typenode_for_spec (&expr->ts);
6115 1.1 mrg /* Initialize the result. */
6116 1.1 mrg limit = gfc_create_var (type, "limit");
6117 1.1 mrg n = gfc_validate_kind (expr->ts.type, expr->ts.kind, false);
6118 1.1 mrg switch (expr->ts.type)
6119 1.1 mrg {
6120 1.1 mrg case BT_REAL:
6121 1.1 mrg huge_cst = gfc_conv_mpfr_to_tree (gfc_real_kinds[n].huge,
6122 1.1 mrg expr->ts.kind, 0);
6123 1.1 mrg if (HONOR_INFINITIES (DECL_MODE (limit)))
6124 1.1 mrg {
6125 1.1 mrg REAL_VALUE_TYPE real;
6126 1.1 mrg real_inf (&real);
6127 1.1 mrg tmp = build_real (type, real);
6128 1.1 mrg }
6129 1.1 mrg else
6130 1.1 mrg tmp = huge_cst;
6131 1.1 mrg if (HONOR_NANS (DECL_MODE (limit)))
6132 1.1 mrg nan_cst = gfc_build_nan (type, "");
6133 1.1 mrg break;
6134 1.1 mrg
6135 1.1 mrg case BT_INTEGER:
6136 1.1 mrg tmp = gfc_conv_mpz_to_tree (gfc_integer_kinds[n].huge, expr->ts.kind);
6137 1.1 mrg break;
6138 1.1 mrg
6139 1.1 mrg default:
6140 1.1 mrg gcc_unreachable ();
6141 1.1 mrg }
6142 1.1 mrg
6143 1.1 mrg /* We start with the most negative possible value for MAXVAL, and the most
6144 1.1 mrg positive possible value for MINVAL. The most negative possible value is
6145 1.1 mrg -HUGE for BT_REAL and (-HUGE - 1) for BT_INTEGER; the most positive
6146 1.1 mrg possible value is HUGE in both cases. */
6147 1.1 mrg if (op == GT_EXPR)
6148 1.1 mrg {
6149 1.1 mrg tmp = fold_build1_loc (input_location, NEGATE_EXPR, TREE_TYPE (tmp), tmp);
6150 1.1 mrg if (huge_cst)
6151 1.1 mrg huge_cst = fold_build1_loc (input_location, NEGATE_EXPR,
6152 1.1 mrg TREE_TYPE (huge_cst), huge_cst);
6153 1.1 mrg }
6154 1.1 mrg
6155 1.1 mrg if (op == GT_EXPR && expr->ts.type == BT_INTEGER)
6156 1.1 mrg tmp = fold_build2_loc (input_location, MINUS_EXPR, TREE_TYPE (tmp),
6157 1.1 mrg tmp, build_int_cst (type, 1));
6158 1.1 mrg
6159 1.1 mrg gfc_add_modify (&se->pre, limit, tmp);
6160 1.1 mrg
6161 1.1 mrg /* Walk the arguments. */
6162 1.1 mrg arrayss = gfc_walk_expr (arrayexpr);
6163 1.1 mrg gcc_assert (arrayss != gfc_ss_terminator);
6164 1.1 mrg
6165 1.1 mrg actual = actual->next->next;
6166 1.1 mrg gcc_assert (actual);
6167 1.1 mrg maskexpr = actual->expr;
6168 1.1 mrg optional_mask = maskexpr && maskexpr->expr_type == EXPR_VARIABLE
6169 1.1 mrg && maskexpr->symtree->n.sym->attr.dummy
6170 1.1 mrg && maskexpr->symtree->n.sym->attr.optional;
6171 1.1 mrg nonempty = NULL;
6172 1.1 mrg if (maskexpr && maskexpr->rank != 0)
6173 1.1 mrg {
6174 1.1 mrg maskss = gfc_walk_expr (maskexpr);
6175 1.1 mrg gcc_assert (maskss != gfc_ss_terminator);
6176 1.1 mrg }
6177 1.1 mrg else
6178 1.1 mrg {
6179 1.1 mrg mpz_t asize;
6180 1.1 mrg if (gfc_array_size (arrayexpr, &asize))
6181 1.1 mrg {
6182 1.1 mrg nonempty = gfc_conv_mpz_to_tree (asize, gfc_index_integer_kind);
6183 1.1 mrg mpz_clear (asize);
6184 1.1 mrg nonempty = fold_build2_loc (input_location, GT_EXPR,
6185 1.1 mrg logical_type_node, nonempty,
6186 1.1 mrg gfc_index_zero_node);
6187 1.1 mrg }
6188 1.1 mrg maskss = NULL;
6189 1.1 mrg }
6190 1.1 mrg
6191 1.1 mrg /* Initialize the scalarizer. */
6192 1.1 mrg gfc_init_loopinfo (&loop);
6193 1.1 mrg
6194 1.1 mrg /* We add the mask first because the number of iterations is taken
6195 1.1 mrg from the last ss, and this breaks if an absent optional argument
6196 1.1 mrg is used for mask. */
6197 1.1 mrg
6198 1.1 mrg if (maskss)
6199 1.1 mrg gfc_add_ss_to_loop (&loop, maskss);
6200 1.1 mrg gfc_add_ss_to_loop (&loop, arrayss);
6201 1.1 mrg
6202 1.1 mrg /* Initialize the loop. */
6203 1.1 mrg gfc_conv_ss_startstride (&loop);
6204 1.1 mrg
6205 1.1 mrg /* The code generated can have more than one loop in sequence (see the
6206 1.1 mrg comment at the function header). This doesn't work well with the
6207 1.1 mrg scalarizer, which changes arrays' offset when the scalarization loops
6208 1.1 mrg are generated (see gfc_trans_preloop_setup). Fortunately, {min,max}val
6209 1.1 mrg are currently inlined in the scalar case only. As there is no dependency
6210 1.1 mrg to care about in that case, there is no temporary, so that we can use the
6211 1.1 mrg scalarizer temporary code to handle multiple loops. Thus, we set temp_dim
6212 1.1 mrg here, we call gfc_mark_ss_chain_used with flag=3 later, and we use
6213 1.1 mrg gfc_trans_scalarized_loop_boundary even later to restore offset.
6214 1.1 mrg TODO: this prevents inlining of rank > 0 minmaxval calls, so this
6215 1.1 mrg should eventually go away. We could either create two loops properly,
6216 1.1 mrg or find another way to save/restore the array offsets between the two
6217 1.1 mrg loops (without conflicting with temporary management), or use a single
6218 1.1 mrg loop minmaxval implementation. See PR 31067. */
6219 1.1 mrg loop.temp_dim = loop.dimen;
6220 1.1 mrg gfc_conv_loop_setup (&loop, &expr->where);
6221 1.1 mrg
6222 1.1 mrg if (nonempty == NULL && maskss == NULL
6223 1.1 mrg && loop.dimen == 1 && loop.from[0] && loop.to[0])
6224 1.1 mrg nonempty = fold_build2_loc (input_location, LE_EXPR, logical_type_node,
6225 1.1 mrg loop.from[0], loop.to[0]);
6226 1.1 mrg nonempty_var = NULL;
6227 1.1 mrg if (nonempty == NULL
6228 1.1 mrg && (HONOR_INFINITIES (DECL_MODE (limit))
6229 1.1 mrg || HONOR_NANS (DECL_MODE (limit))))
6230 1.1 mrg {
6231 1.1 mrg nonempty_var = gfc_create_var (logical_type_node, "nonempty");
6232 1.1 mrg gfc_add_modify (&se->pre, nonempty_var, logical_false_node);
6233 1.1 mrg nonempty = nonempty_var;
6234 1.1 mrg }
6235 1.1 mrg lab = NULL;
6236 1.1 mrg fast = NULL;
6237 1.1 mrg if (HONOR_NANS (DECL_MODE (limit)))
6238 1.1 mrg {
6239 1.1 mrg if (loop.dimen == 1)
6240 1.1 mrg {
6241 1.1 mrg lab = gfc_build_label_decl (NULL_TREE);
6242 1.1 mrg TREE_USED (lab) = 1;
6243 1.1 mrg }
6244 1.1 mrg else
6245 1.1 mrg {
6246 1.1 mrg fast = gfc_create_var (logical_type_node, "fast");
6247 1.1 mrg gfc_add_modify (&se->pre, fast, logical_false_node);
6248 1.1 mrg }
6249 1.1 mrg }
6250 1.1 mrg
6251 1.1 mrg gfc_mark_ss_chain_used (arrayss, lab ? 3 : 1);
6252 1.1 mrg if (maskss)
6253 1.1 mrg gfc_mark_ss_chain_used (maskss, lab ? 3 : 1);
6254 1.1 mrg /* Generate the loop body. */
6255 1.1 mrg gfc_start_scalarized_body (&loop, &body);
6256 1.1 mrg
6257 1.1 mrg /* If we have a mask, only add this element if the mask is set. */
6258 1.1 mrg if (maskss)
6259 1.1 mrg {
6260 1.1 mrg gfc_init_se (&maskse, NULL);
6261 1.1 mrg gfc_copy_loopinfo_to_se (&maskse, &loop);
6262 1.1 mrg maskse.ss = maskss;
6263 1.1 mrg gfc_conv_expr_val (&maskse, maskexpr);
6264 1.1 mrg gfc_add_block_to_block (&body, &maskse.pre);
6265 1.1 mrg
6266 1.1 mrg gfc_start_block (&block);
6267 1.1 mrg }
6268 1.1 mrg else
6269 1.1 mrg gfc_init_block (&block);
6270 1.1 mrg
6271 1.1 mrg /* Compare with the current limit. */
6272 1.1 mrg gfc_init_se (&arrayse, NULL);
6273 1.1 mrg gfc_copy_loopinfo_to_se (&arrayse, &loop);
6274 1.1 mrg arrayse.ss = arrayss;
6275 1.1 mrg gfc_conv_expr_val (&arrayse, arrayexpr);
6276 1.1 mrg gfc_add_block_to_block (&block, &arrayse.pre);
6277 1.1 mrg
6278 1.1 mrg gfc_init_block (&block2);
6279 1.1 mrg
6280 1.1 mrg if (nonempty_var)
6281 1.1 mrg gfc_add_modify (&block2, nonempty_var, logical_true_node);
6282 1.1 mrg
6283 1.1 mrg if (HONOR_NANS (DECL_MODE (limit)))
6284 1.1 mrg {
6285 1.1 mrg tmp = fold_build2_loc (input_location, op == GT_EXPR ? GE_EXPR : LE_EXPR,
6286 1.1 mrg logical_type_node, arrayse.expr, limit);
6287 1.1 mrg if (lab)
6288 1.1 mrg ifbody = build1_v (GOTO_EXPR, lab);
6289 1.1 mrg else
6290 1.1 mrg {
6291 1.1 mrg stmtblock_t ifblock;
6292 1.1 mrg
6293 1.1 mrg gfc_init_block (&ifblock);
6294 1.1 mrg gfc_add_modify (&ifblock, limit, arrayse.expr);
6295 1.1 mrg gfc_add_modify (&ifblock, fast, logical_true_node);
6296 1.1 mrg ifbody = gfc_finish_block (&ifblock);
6297 1.1 mrg }
6298 1.1 mrg tmp = build3_v (COND_EXPR, tmp, ifbody,
6299 1.1 mrg build_empty_stmt (input_location));
6300 1.1 mrg gfc_add_expr_to_block (&block2, tmp);
6301 1.1 mrg }
6302 1.1 mrg else
6303 1.1 mrg {
6304 1.1 mrg /* MIN_EXPR/MAX_EXPR has unspecified behavior with NaNs or
6305 1.1 mrg signed zeros. */
6306 1.1 mrg tmp = fold_build2_loc (input_location,
6307 1.1 mrg op == GT_EXPR ? MAX_EXPR : MIN_EXPR,
6308 1.1 mrg type, arrayse.expr, limit);
6309 1.1 mrg gfc_add_modify (&block2, limit, tmp);
6310 1.1 mrg }
6311 1.1 mrg
6312 1.1 mrg if (fast)
6313 1.1 mrg {
6314 1.1 mrg tree elsebody = gfc_finish_block (&block2);
6315 1.1 mrg
6316 1.1 mrg /* MIN_EXPR/MAX_EXPR has unspecified behavior with NaNs or
6317 1.1 mrg signed zeros. */
6318 1.1 mrg if (HONOR_NANS (DECL_MODE (limit)))
6319 1.1 mrg {
6320 1.1 mrg tmp = fold_build2_loc (input_location, op, logical_type_node,
6321 1.1 mrg arrayse.expr, limit);
6322 1.1 mrg ifbody = build2_v (MODIFY_EXPR, limit, arrayse.expr);
6323 1.1 mrg ifbody = build3_v (COND_EXPR, tmp, ifbody,
6324 1.1 mrg build_empty_stmt (input_location));
6325 1.1 mrg }
6326 1.1 mrg else
6327 1.1 mrg {
6328 1.1 mrg tmp = fold_build2_loc (input_location,
6329 1.1 mrg op == GT_EXPR ? MAX_EXPR : MIN_EXPR,
6330 1.1 mrg type, arrayse.expr, limit);
6331 1.1 mrg ifbody = build2_v (MODIFY_EXPR, limit, tmp);
6332 1.1 mrg }
6333 1.1 mrg tmp = build3_v (COND_EXPR, fast, ifbody, elsebody);
6334 1.1 mrg gfc_add_expr_to_block (&block, tmp);
6335 1.1 mrg }
6336 1.1 mrg else
6337 1.1 mrg gfc_add_block_to_block (&block, &block2);
6338 1.1 mrg
6339 1.1 mrg gfc_add_block_to_block (&block, &arrayse.post);
6340 1.1 mrg
6341 1.1 mrg tmp = gfc_finish_block (&block);
6342 1.1 mrg if (maskss)
6343 1.1 mrg {
6344 1.1 mrg /* We enclose the above in if (mask) {...}. If the mask is an
6345 1.1 mrg optional argument, generate IF (.NOT. PRESENT(MASK)
6346 1.1 mrg .OR. MASK(I)). */
6347 1.1 mrg tree ifmask;
6348 1.1 mrg ifmask = conv_mask_condition (&maskse, maskexpr, optional_mask);
6349 1.1 mrg tmp = build3_v (COND_EXPR, ifmask, tmp,
6350 1.1 mrg build_empty_stmt (input_location));
6351 1.1 mrg }
6352 1.1 mrg gfc_add_expr_to_block (&body, tmp);
6353 1.1 mrg
6354 1.1 mrg if (lab)
6355 1.1 mrg {
6356 1.1 mrg gfc_trans_scalarized_loop_boundary (&loop, &body);
6357 1.1 mrg
6358 1.1 mrg tmp = fold_build3_loc (input_location, COND_EXPR, type, nonempty,
6359 1.1 mrg nan_cst, huge_cst);
6360 1.1 mrg gfc_add_modify (&loop.code[0], limit, tmp);
6361 1.1 mrg gfc_add_expr_to_block (&loop.code[0], build1_v (LABEL_EXPR, lab));
6362 1.1 mrg
6363 1.1 mrg /* If we have a mask, only add this element if the mask is set. */
6364 1.1 mrg if (maskss)
6365 1.1 mrg {
6366 1.1 mrg gfc_init_se (&maskse, NULL);
6367 1.1 mrg gfc_copy_loopinfo_to_se (&maskse, &loop);
6368 1.1 mrg maskse.ss = maskss;
6369 1.1 mrg gfc_conv_expr_val (&maskse, maskexpr);
6370 1.1 mrg gfc_add_block_to_block (&body, &maskse.pre);
6371 1.1 mrg
6372 1.1 mrg gfc_start_block (&block);
6373 1.1 mrg }
6374 1.1 mrg else
6375 1.1 mrg gfc_init_block (&block);
6376 1.1 mrg
6377 1.1 mrg /* Compare with the current limit. */
6378 1.1 mrg gfc_init_se (&arrayse, NULL);
6379 1.1 mrg gfc_copy_loopinfo_to_se (&arrayse, &loop);
6380 1.1 mrg arrayse.ss = arrayss;
6381 1.1 mrg gfc_conv_expr_val (&arrayse, arrayexpr);
6382 1.1 mrg gfc_add_block_to_block (&block, &arrayse.pre);
6383 1.1 mrg
6384 1.1 mrg /* MIN_EXPR/MAX_EXPR has unspecified behavior with NaNs or
6385 1.1 mrg signed zeros. */
6386 1.1 mrg if (HONOR_NANS (DECL_MODE (limit)))
6387 1.1 mrg {
6388 1.1 mrg tmp = fold_build2_loc (input_location, op, logical_type_node,
6389 1.1 mrg arrayse.expr, limit);
6390 1.1 mrg ifbody = build2_v (MODIFY_EXPR, limit, arrayse.expr);
6391 1.1 mrg tmp = build3_v (COND_EXPR, tmp, ifbody,
6392 1.1 mrg build_empty_stmt (input_location));
6393 1.1 mrg gfc_add_expr_to_block (&block, tmp);
6394 1.1 mrg }
6395 1.1 mrg else
6396 1.1 mrg {
6397 1.1 mrg tmp = fold_build2_loc (input_location,
6398 1.1 mrg op == GT_EXPR ? MAX_EXPR : MIN_EXPR,
6399 1.1 mrg type, arrayse.expr, limit);
6400 1.1 mrg gfc_add_modify (&block, limit, tmp);
6401 1.1 mrg }
6402 1.1 mrg
6403 1.1 mrg gfc_add_block_to_block (&block, &arrayse.post);
6404 1.1 mrg
6405 1.1 mrg tmp = gfc_finish_block (&block);
6406 1.1 mrg if (maskss)
6407 1.1 mrg /* We enclose the above in if (mask) {...}. */
6408 1.1 mrg {
6409 1.1 mrg tree ifmask;
6410 1.1 mrg ifmask = conv_mask_condition (&maskse, maskexpr, optional_mask);
6411 1.1 mrg tmp = build3_v (COND_EXPR, ifmask, tmp,
6412 1.1 mrg build_empty_stmt (input_location));
6413 1.1 mrg }
6414 1.1 mrg
6415 1.1 mrg gfc_add_expr_to_block (&body, tmp);
6416 1.1 mrg /* Avoid initializing loopvar[0] again, it should be left where
6417 1.1 mrg it finished by the first loop. */
6418 1.1 mrg loop.from[0] = loop.loopvar[0];
6419 1.1 mrg }
6420 1.1 mrg gfc_trans_scalarizing_loops (&loop, &body);
6421 1.1 mrg
6422 1.1 mrg if (fast)
6423 1.1 mrg {
6424 1.1 mrg tmp = fold_build3_loc (input_location, COND_EXPR, type, nonempty,
6425 1.1 mrg nan_cst, huge_cst);
6426 1.1 mrg ifbody = build2_v (MODIFY_EXPR, limit, tmp);
6427 1.1 mrg tmp = build3_v (COND_EXPR, fast, build_empty_stmt (input_location),
6428 1.1 mrg ifbody);
6429 1.1 mrg gfc_add_expr_to_block (&loop.pre, tmp);
6430 1.1 mrg }
6431 1.1 mrg else if (HONOR_INFINITIES (DECL_MODE (limit)) && !lab)
6432 1.1 mrg {
6433 1.1 mrg tmp = fold_build3_loc (input_location, COND_EXPR, type, nonempty, limit,
6434 1.1 mrg huge_cst);
6435 1.1 mrg gfc_add_modify (&loop.pre, limit, tmp);
6436 1.1 mrg }
6437 1.1 mrg
6438 1.1 mrg /* For a scalar mask, enclose the loop in an if statement. */
6439 1.1 mrg if (maskexpr && maskss == NULL)
6440 1.1 mrg {
6441 1.1 mrg tree else_stmt;
6442 1.1 mrg tree ifmask;
6443 1.1 mrg
6444 1.1 mrg gfc_init_se (&maskse, NULL);
6445 1.1 mrg gfc_conv_expr_val (&maskse, maskexpr);
6446 1.1 mrg gfc_init_block (&block);
6447 1.1 mrg gfc_add_block_to_block (&block, &loop.pre);
6448 1.1 mrg gfc_add_block_to_block (&block, &loop.post);
6449 1.1 mrg tmp = gfc_finish_block (&block);
6450 1.1 mrg
6451 1.1 mrg if (HONOR_INFINITIES (DECL_MODE (limit)))
6452 1.1 mrg else_stmt = build2_v (MODIFY_EXPR, limit, huge_cst);
6453 1.1 mrg else
6454 1.1 mrg else_stmt = build_empty_stmt (input_location);
6455 1.1 mrg
6456 1.1 mrg ifmask = conv_mask_condition (&maskse, maskexpr, optional_mask);
6457 1.1 mrg tmp = build3_v (COND_EXPR, ifmask, tmp, else_stmt);
6458 1.1 mrg gfc_add_expr_to_block (&block, tmp);
6459 1.1 mrg gfc_add_block_to_block (&se->pre, &block);
6460 1.1 mrg }
6461 1.1 mrg else
6462 1.1 mrg {
6463 1.1 mrg gfc_add_block_to_block (&se->pre, &loop.pre);
6464 1.1 mrg gfc_add_block_to_block (&se->pre, &loop.post);
6465 1.1 mrg }
6466 1.1 mrg
6467 1.1 mrg gfc_cleanup_loop (&loop);
6468 1.1 mrg
6469 1.1 mrg se->expr = limit;
6470 1.1 mrg }
6471 1.1 mrg
6472 1.1 mrg /* BTEST (i, pos) = (i & (1 << pos)) != 0. */
6473 1.1 mrg static void
6474 1.1 mrg gfc_conv_intrinsic_btest (gfc_se * se, gfc_expr * expr)
6475 1.1 mrg {
6476 1.1 mrg tree args[2];
6477 1.1 mrg tree type;
6478 1.1 mrg tree tmp;
6479 1.1 mrg
6480 1.1 mrg gfc_conv_intrinsic_function_args (se, expr, args, 2);
6481 1.1 mrg type = TREE_TYPE (args[0]);
6482 1.1 mrg
6483 1.1 mrg /* Optionally generate code for runtime argument check. */
6484 1.1 mrg if (gfc_option.rtcheck & GFC_RTCHECK_BITS)
6485 1.1 mrg {
6486 1.1 mrg tree below = fold_build2_loc (input_location, LT_EXPR,
6487 1.1 mrg logical_type_node, args[1],
6488 1.1 mrg build_int_cst (TREE_TYPE (args[1]), 0));
6489 1.1 mrg tree nbits = build_int_cst (TREE_TYPE (args[1]), TYPE_PRECISION (type));
6490 1.1 mrg tree above = fold_build2_loc (input_location, GE_EXPR,
6491 1.1 mrg logical_type_node, args[1], nbits);
6492 1.1 mrg tree scond = fold_build2_loc (input_location, TRUTH_ORIF_EXPR,
6493 1.1 mrg logical_type_node, below, above);
6494 1.1 mrg gfc_trans_runtime_check (true, false, scond, &se->pre, &expr->where,
6495 1.1 mrg "POS argument (%ld) out of range 0:%ld "
6496 1.1 mrg "in intrinsic BTEST",
6497 1.1 mrg fold_convert (long_integer_type_node, args[1]),
6498 1.1 mrg fold_convert (long_integer_type_node, nbits));
6499 1.1 mrg }
6500 1.1 mrg
6501 1.1 mrg tmp = fold_build2_loc (input_location, LSHIFT_EXPR, type,
6502 1.1 mrg build_int_cst (type, 1), args[1]);
6503 1.1 mrg tmp = fold_build2_loc (input_location, BIT_AND_EXPR, type, args[0], tmp);
6504 1.1 mrg tmp = fold_build2_loc (input_location, NE_EXPR, logical_type_node, tmp,
6505 1.1 mrg build_int_cst (type, 0));
6506 1.1 mrg type = gfc_typenode_for_spec (&expr->ts);
6507 1.1 mrg se->expr = convert (type, tmp);
6508 1.1 mrg }
6509 1.1 mrg
6510 1.1 mrg
6511 1.1 mrg /* Generate code for BGE, BGT, BLE and BLT intrinsics. */
6512 1.1 mrg static void
6513 1.1 mrg gfc_conv_intrinsic_bitcomp (gfc_se * se, gfc_expr * expr, enum tree_code op)
6514 1.1 mrg {
6515 1.1 mrg tree args[2];
6516 1.1 mrg
6517 1.1 mrg gfc_conv_intrinsic_function_args (se, expr, args, 2);
6518 1.1 mrg
6519 1.1 mrg /* Convert both arguments to the unsigned type of the same size. */
6520 1.1 mrg args[0] = fold_convert (unsigned_type_for (TREE_TYPE (args[0])), args[0]);
6521 1.1 mrg args[1] = fold_convert (unsigned_type_for (TREE_TYPE (args[1])), args[1]);
6522 1.1 mrg
6523 1.1 mrg /* If they have unequal type size, convert to the larger one. */
6524 1.1 mrg if (TYPE_PRECISION (TREE_TYPE (args[0]))
6525 1.1 mrg > TYPE_PRECISION (TREE_TYPE (args[1])))
6526 1.1 mrg args[1] = fold_convert (TREE_TYPE (args[0]), args[1]);
6527 1.1 mrg else if (TYPE_PRECISION (TREE_TYPE (args[1]))
6528 1.1 mrg > TYPE_PRECISION (TREE_TYPE (args[0])))
6529 1.1 mrg args[0] = fold_convert (TREE_TYPE (args[1]), args[0]);
6530 1.1 mrg
6531 1.1 mrg /* Now, we compare them. */
6532 1.1 mrg se->expr = fold_build2_loc (input_location, op, logical_type_node,
6533 1.1 mrg args[0], args[1]);
6534 1.1 mrg }
6535 1.1 mrg
6536 1.1 mrg
6537 1.1 mrg /* Generate code to perform the specified operation. */
6538 1.1 mrg static void
6539 1.1 mrg gfc_conv_intrinsic_bitop (gfc_se * se, gfc_expr * expr, enum tree_code op)
6540 1.1 mrg {
6541 1.1 mrg tree args[2];
6542 1.1 mrg
6543 1.1 mrg gfc_conv_intrinsic_function_args (se, expr, args, 2);
6544 1.1 mrg se->expr = fold_build2_loc (input_location, op, TREE_TYPE (args[0]),
6545 1.1 mrg args[0], args[1]);
6546 1.1 mrg }
6547 1.1 mrg
6548 1.1 mrg /* Bitwise not. */
6549 1.1 mrg static void
6550 1.1 mrg gfc_conv_intrinsic_not (gfc_se * se, gfc_expr * expr)
6551 1.1 mrg {
6552 1.1 mrg tree arg;
6553 1.1 mrg
6554 1.1 mrg gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
6555 1.1 mrg se->expr = fold_build1_loc (input_location, BIT_NOT_EXPR,
6556 1.1 mrg TREE_TYPE (arg), arg);
6557 1.1 mrg }
6558 1.1 mrg
6559 1.1 mrg /* Set or clear a single bit. */
6560 1.1 mrg static void
6561 1.1 mrg gfc_conv_intrinsic_singlebitop (gfc_se * se, gfc_expr * expr, int set)
6562 1.1 mrg {
6563 1.1 mrg tree args[2];
6564 1.1 mrg tree type;
6565 1.1 mrg tree tmp;
6566 1.1 mrg enum tree_code op;
6567 1.1 mrg
6568 1.1 mrg gfc_conv_intrinsic_function_args (se, expr, args, 2);
6569 1.1 mrg type = TREE_TYPE (args[0]);
6570 1.1 mrg
6571 1.1 mrg /* Optionally generate code for runtime argument check. */
6572 1.1 mrg if (gfc_option.rtcheck & GFC_RTCHECK_BITS)
6573 1.1 mrg {
6574 1.1 mrg tree below = fold_build2_loc (input_location, LT_EXPR,
6575 1.1 mrg logical_type_node, args[1],
6576 1.1 mrg build_int_cst (TREE_TYPE (args[1]), 0));
6577 1.1 mrg tree nbits = build_int_cst (TREE_TYPE (args[1]), TYPE_PRECISION (type));
6578 1.1 mrg tree above = fold_build2_loc (input_location, GE_EXPR,
6579 1.1 mrg logical_type_node, args[1], nbits);
6580 1.1 mrg tree scond = fold_build2_loc (input_location, TRUTH_ORIF_EXPR,
6581 1.1 mrg logical_type_node, below, above);
6582 1.1 mrg size_t len_name = strlen (expr->value.function.isym->name);
6583 1.1 mrg char *name = XALLOCAVEC (char, len_name + 1);
6584 1.1 mrg for (size_t i = 0; i < len_name; i++)
6585 1.1 mrg name[i] = TOUPPER (expr->value.function.isym->name[i]);
6586 1.1 mrg name[len_name] = '\0';
6587 1.1 mrg tree iname = gfc_build_addr_expr (pchar_type_node,
6588 1.1 mrg gfc_build_cstring_const (name));
6589 1.1 mrg gfc_trans_runtime_check (true, false, scond, &se->pre, &expr->where,
6590 1.1 mrg "POS argument (%ld) out of range 0:%ld "
6591 1.1 mrg "in intrinsic %s",
6592 1.1 mrg fold_convert (long_integer_type_node, args[1]),
6593 1.1 mrg fold_convert (long_integer_type_node, nbits),
6594 1.1 mrg iname);
6595 1.1 mrg }
6596 1.1 mrg
6597 1.1 mrg tmp = fold_build2_loc (input_location, LSHIFT_EXPR, type,
6598 1.1 mrg build_int_cst (type, 1), args[1]);
6599 1.1 mrg if (set)
6600 1.1 mrg op = BIT_IOR_EXPR;
6601 1.1 mrg else
6602 1.1 mrg {
6603 1.1 mrg op = BIT_AND_EXPR;
6604 1.1 mrg tmp = fold_build1_loc (input_location, BIT_NOT_EXPR, type, tmp);
6605 1.1 mrg }
6606 1.1 mrg se->expr = fold_build2_loc (input_location, op, type, args[0], tmp);
6607 1.1 mrg }
6608 1.1 mrg
6609 1.1 mrg /* Extract a sequence of bits.
6610 1.1 mrg IBITS(I, POS, LEN) = (I >> POS) & ~((~0) << LEN). */
6611 1.1 mrg static void
6612 1.1 mrg gfc_conv_intrinsic_ibits (gfc_se * se, gfc_expr * expr)
6613 1.1 mrg {
6614 1.1 mrg tree args[3];
6615 1.1 mrg tree type;
6616 1.1 mrg tree tmp;
6617 1.1 mrg tree mask;
6618 1.1 mrg tree num_bits, cond;
6619 1.1 mrg
6620 1.1 mrg gfc_conv_intrinsic_function_args (se, expr, args, 3);
6621 1.1 mrg type = TREE_TYPE (args[0]);
6622 1.1 mrg
6623 1.1 mrg /* Optionally generate code for runtime argument check. */
6624 1.1 mrg if (gfc_option.rtcheck & GFC_RTCHECK_BITS)
6625 1.1 mrg {
6626 1.1 mrg tree tmp1 = fold_convert (long_integer_type_node, args[1]);
6627 1.1 mrg tree tmp2 = fold_convert (long_integer_type_node, args[2]);
6628 1.1 mrg tree nbits = build_int_cst (long_integer_type_node,
6629 1.1 mrg TYPE_PRECISION (type));
6630 1.1 mrg tree below = fold_build2_loc (input_location, LT_EXPR,
6631 1.1 mrg logical_type_node, args[1],
6632 1.1 mrg build_int_cst (TREE_TYPE (args[1]), 0));
6633 1.1 mrg tree above = fold_build2_loc (input_location, GT_EXPR,
6634 1.1 mrg logical_type_node, tmp1, nbits);
6635 1.1 mrg tree scond = fold_build2_loc (input_location, TRUTH_ORIF_EXPR,
6636 1.1 mrg logical_type_node, below, above);
6637 1.1 mrg gfc_trans_runtime_check (true, false, scond, &se->pre, &expr->where,
6638 1.1 mrg "POS argument (%ld) out of range 0:%ld "
6639 1.1 mrg "in intrinsic IBITS", tmp1, nbits);
6640 1.1 mrg below = fold_build2_loc (input_location, LT_EXPR,
6641 1.1 mrg logical_type_node, args[2],
6642 1.1 mrg build_int_cst (TREE_TYPE (args[2]), 0));
6643 1.1 mrg above = fold_build2_loc (input_location, GT_EXPR,
6644 1.1 mrg logical_type_node, tmp2, nbits);
6645 1.1 mrg scond = fold_build2_loc (input_location, TRUTH_ORIF_EXPR,
6646 1.1 mrg logical_type_node, below, above);
6647 1.1 mrg gfc_trans_runtime_check (true, false, scond, &se->pre, &expr->where,
6648 1.1 mrg "LEN argument (%ld) out of range 0:%ld "
6649 1.1 mrg "in intrinsic IBITS", tmp2, nbits);
6650 1.1 mrg above = fold_build2_loc (input_location, PLUS_EXPR,
6651 1.1 mrg long_integer_type_node, tmp1, tmp2);
6652 1.1 mrg scond = fold_build2_loc (input_location, GT_EXPR,
6653 1.1 mrg logical_type_node, above, nbits);
6654 1.1 mrg gfc_trans_runtime_check (true, false, scond, &se->pre, &expr->where,
6655 1.1 mrg "POS(%ld)+LEN(%ld)>BIT_SIZE(%ld) "
6656 1.1 mrg "in intrinsic IBITS", tmp1, tmp2, nbits);
6657 1.1 mrg }
6658 1.1 mrg
6659 1.1 mrg /* The Fortran standard allows (shift width) LEN <= BIT_SIZE(I), whereas
6660 1.1 mrg gcc requires a shift width < BIT_SIZE(I), so we have to catch this
6661 1.1 mrg special case. See also gfc_conv_intrinsic_ishft (). */
6662 1.1 mrg num_bits = build_int_cst (TREE_TYPE (args[2]), TYPE_PRECISION (type));
6663 1.1 mrg
6664 1.1 mrg mask = build_int_cst (type, -1);
6665 1.1 mrg mask = fold_build2_loc (input_location, LSHIFT_EXPR, type, mask, args[2]);
6666 1.1 mrg cond = fold_build2_loc (input_location, GE_EXPR, logical_type_node, args[2],
6667 1.1 mrg num_bits);
6668 1.1 mrg mask = fold_build3_loc (input_location, COND_EXPR, type, cond,
6669 1.1 mrg build_int_cst (type, 0), mask);
6670 1.1 mrg mask = fold_build1_loc (input_location, BIT_NOT_EXPR, type, mask);
6671 1.1 mrg
6672 1.1 mrg tmp = fold_build2_loc (input_location, RSHIFT_EXPR, type, args[0], args[1]);
6673 1.1 mrg
6674 1.1 mrg se->expr = fold_build2_loc (input_location, BIT_AND_EXPR, type, tmp, mask);
6675 1.1 mrg }
6676 1.1 mrg
6677 1.1 mrg static void
6678 1.1 mrg gfc_conv_intrinsic_shift (gfc_se * se, gfc_expr * expr, bool right_shift,
6679 1.1 mrg bool arithmetic)
6680 1.1 mrg {
6681 1.1 mrg tree args[2], type, num_bits, cond;
6682 1.1 mrg tree bigshift;
6683 1.1 mrg
6684 1.1 mrg gfc_conv_intrinsic_function_args (se, expr, args, 2);
6685 1.1 mrg
6686 1.1 mrg args[0] = gfc_evaluate_now (args[0], &se->pre);
6687 1.1 mrg args[1] = gfc_evaluate_now (args[1], &se->pre);
6688 1.1 mrg type = TREE_TYPE (args[0]);
6689 1.1 mrg
6690 1.1 mrg if (!arithmetic)
6691 1.1 mrg args[0] = fold_convert (unsigned_type_for (type), args[0]);
6692 1.1 mrg else
6693 1.1 mrg gcc_assert (right_shift);
6694 1.1 mrg
6695 1.1 mrg se->expr = fold_build2_loc (input_location,
6696 1.1 mrg right_shift ? RSHIFT_EXPR : LSHIFT_EXPR,
6697 1.1 mrg TREE_TYPE (args[0]), args[0], args[1]);
6698 1.1 mrg
6699 1.1 mrg if (!arithmetic)
6700 1.1 mrg se->expr = fold_convert (type, se->expr);
6701 1.1 mrg
6702 1.1 mrg if (!arithmetic)
6703 1.1 mrg bigshift = build_int_cst (type, 0);
6704 1.1 mrg else
6705 1.1 mrg {
6706 1.1 mrg tree nonneg = fold_build2_loc (input_location, GE_EXPR,
6707 1.1 mrg logical_type_node, args[0],
6708 1.1 mrg build_int_cst (TREE_TYPE (args[0]), 0));
6709 1.1 mrg bigshift = fold_build3_loc (input_location, COND_EXPR, type, nonneg,
6710 1.1 mrg build_int_cst (type, 0),
6711 1.1 mrg build_int_cst (type, -1));
6712 1.1 mrg }
6713 1.1 mrg
6714 1.1 mrg /* The Fortran standard allows shift widths <= BIT_SIZE(I), whereas
6715 1.1 mrg gcc requires a shift width < BIT_SIZE(I), so we have to catch this
6716 1.1 mrg special case. */
6717 1.1 mrg num_bits = build_int_cst (TREE_TYPE (args[1]), TYPE_PRECISION (type));
6718 1.1 mrg
6719 1.1 mrg /* Optionally generate code for runtime argument check. */
6720 1.1 mrg if (gfc_option.rtcheck & GFC_RTCHECK_BITS)
6721 1.1 mrg {
6722 1.1 mrg tree below = fold_build2_loc (input_location, LT_EXPR,
6723 1.1 mrg logical_type_node, args[1],
6724 1.1 mrg build_int_cst (TREE_TYPE (args[1]), 0));
6725 1.1 mrg tree above = fold_build2_loc (input_location, GT_EXPR,
6726 1.1 mrg logical_type_node, args[1], num_bits);
6727 1.1 mrg tree scond = fold_build2_loc (input_location, TRUTH_ORIF_EXPR,
6728 1.1 mrg logical_type_node, below, above);
6729 1.1 mrg size_t len_name = strlen (expr->value.function.isym->name);
6730 1.1 mrg char *name = XALLOCAVEC (char, len_name + 1);
6731 1.1 mrg for (size_t i = 0; i < len_name; i++)
6732 1.1 mrg name[i] = TOUPPER (expr->value.function.isym->name[i]);
6733 1.1 mrg name[len_name] = '\0';
6734 1.1 mrg tree iname = gfc_build_addr_expr (pchar_type_node,
6735 1.1 mrg gfc_build_cstring_const (name));
6736 1.1 mrg gfc_trans_runtime_check (true, false, scond, &se->pre, &expr->where,
6737 1.1 mrg "SHIFT argument (%ld) out of range 0:%ld "
6738 1.1 mrg "in intrinsic %s",
6739 1.1 mrg fold_convert (long_integer_type_node, args[1]),
6740 1.1 mrg fold_convert (long_integer_type_node, num_bits),
6741 1.1 mrg iname);
6742 1.1 mrg }
6743 1.1 mrg
6744 1.1 mrg cond = fold_build2_loc (input_location, GE_EXPR, logical_type_node,
6745 1.1 mrg args[1], num_bits);
6746 1.1 mrg
6747 1.1 mrg se->expr = fold_build3_loc (input_location, COND_EXPR, type, cond,
6748 1.1 mrg bigshift, se->expr);
6749 1.1 mrg }
6750 1.1 mrg
6751 1.1 mrg /* ISHFT (I, SHIFT) = (abs (shift) >= BIT_SIZE (i))
6752 1.1 mrg ? 0
6753 1.1 mrg : ((shift >= 0) ? i << shift : i >> -shift)
6754 1.1 mrg where all shifts are logical shifts. */
6755 1.1 mrg static void
6756 1.1 mrg gfc_conv_intrinsic_ishft (gfc_se * se, gfc_expr * expr)
6757 1.1 mrg {
6758 1.1 mrg tree args[2];
6759 1.1 mrg tree type;
6760 1.1 mrg tree utype;
6761 1.1 mrg tree tmp;
6762 1.1 mrg tree width;
6763 1.1 mrg tree num_bits;
6764 1.1 mrg tree cond;
6765 1.1 mrg tree lshift;
6766 1.1 mrg tree rshift;
6767 1.1 mrg
6768 1.1 mrg gfc_conv_intrinsic_function_args (se, expr, args, 2);
6769 1.1 mrg
6770 1.1 mrg args[0] = gfc_evaluate_now (args[0], &se->pre);
6771 1.1 mrg args[1] = gfc_evaluate_now (args[1], &se->pre);
6772 1.1 mrg
6773 1.1 mrg type = TREE_TYPE (args[0]);
6774 1.1 mrg utype = unsigned_type_for (type);
6775 1.1 mrg
6776 1.1 mrg width = fold_build1_loc (input_location, ABS_EXPR, TREE_TYPE (args[1]),
6777 1.1 mrg args[1]);
6778 1.1 mrg
6779 1.1 mrg /* Left shift if positive. */
6780 1.1 mrg lshift = fold_build2_loc (input_location, LSHIFT_EXPR, type, args[0], width);
6781 1.1 mrg
6782 1.1 mrg /* Right shift if negative.
6783 1.1 mrg We convert to an unsigned type because we want a logical shift.
6784 1.1 mrg The standard doesn't define the case of shifting negative
6785 1.1 mrg numbers, and we try to be compatible with other compilers, most
6786 1.1 mrg notably g77, here. */
6787 1.1 mrg rshift = fold_convert (type, fold_build2_loc (input_location, RSHIFT_EXPR,
6788 1.1 mrg utype, convert (utype, args[0]), width));
6789 1.1 mrg
6790 1.1 mrg tmp = fold_build2_loc (input_location, GE_EXPR, logical_type_node, args[1],
6791 1.1 mrg build_int_cst (TREE_TYPE (args[1]), 0));
6792 1.1 mrg tmp = fold_build3_loc (input_location, COND_EXPR, type, tmp, lshift, rshift);
6793 1.1 mrg
6794 1.1 mrg /* The Fortran standard allows shift widths <= BIT_SIZE(I), whereas
6795 1.1 mrg gcc requires a shift width < BIT_SIZE(I), so we have to catch this
6796 1.1 mrg special case. */
6797 1.1 mrg num_bits = build_int_cst (TREE_TYPE (args[1]), TYPE_PRECISION (type));
6798 1.1 mrg
6799 1.1 mrg /* Optionally generate code for runtime argument check. */
6800 1.1 mrg if (gfc_option.rtcheck & GFC_RTCHECK_BITS)
6801 1.1 mrg {
6802 1.1 mrg tree outside = fold_build2_loc (input_location, GT_EXPR,
6803 1.1 mrg logical_type_node, width, num_bits);
6804 1.1 mrg gfc_trans_runtime_check (true, false, outside, &se->pre, &expr->where,
6805 1.1 mrg "SHIFT argument (%ld) out of range -%ld:%ld "
6806 1.1 mrg "in intrinsic ISHFT",
6807 1.1 mrg fold_convert (long_integer_type_node, args[1]),
6808 1.1 mrg fold_convert (long_integer_type_node, num_bits),
6809 1.1 mrg fold_convert (long_integer_type_node, num_bits));
6810 1.1 mrg }
6811 1.1 mrg
6812 1.1 mrg cond = fold_build2_loc (input_location, GE_EXPR, logical_type_node, width,
6813 1.1 mrg num_bits);
6814 1.1 mrg se->expr = fold_build3_loc (input_location, COND_EXPR, type, cond,
6815 1.1 mrg build_int_cst (type, 0), tmp);
6816 1.1 mrg }
6817 1.1 mrg
6818 1.1 mrg
6819 1.1 mrg /* Circular shift. AKA rotate or barrel shift. */
6820 1.1 mrg
6821 1.1 mrg static void
6822 1.1 mrg gfc_conv_intrinsic_ishftc (gfc_se * se, gfc_expr * expr)
6823 1.1 mrg {
6824 1.1 mrg tree *args;
6825 1.1 mrg tree type;
6826 1.1 mrg tree tmp;
6827 1.1 mrg tree lrot;
6828 1.1 mrg tree rrot;
6829 1.1 mrg tree zero;
6830 1.1 mrg tree nbits;
6831 1.1 mrg unsigned int num_args;
6832 1.1 mrg
6833 1.1 mrg num_args = gfc_intrinsic_argument_list_length (expr);
6834 1.1 mrg args = XALLOCAVEC (tree, num_args);
6835 1.1 mrg
6836 1.1 mrg gfc_conv_intrinsic_function_args (se, expr, args, num_args);
6837 1.1 mrg
6838 1.1 mrg type = TREE_TYPE (args[0]);
6839 1.1 mrg nbits = build_int_cst (long_integer_type_node, TYPE_PRECISION (type));
6840 1.1 mrg
6841 1.1 mrg if (num_args == 3)
6842 1.1 mrg {
6843 1.1 mrg /* Use a library function for the 3 parameter version. */
6844 1.1 mrg tree int4type = gfc_get_int_type (4);
6845 1.1 mrg
6846 1.1 mrg /* We convert the first argument to at least 4 bytes, and
6847 1.1 mrg convert back afterwards. This removes the need for library
6848 1.1 mrg functions for all argument sizes, and function will be
6849 1.1 mrg aligned to at least 32 bits, so there's no loss. */
6850 1.1 mrg if (expr->ts.kind < 4)
6851 1.1 mrg args[0] = convert (int4type, args[0]);
6852 1.1 mrg
6853 1.1 mrg /* Convert the SHIFT and SIZE args to INTEGER*4 otherwise we would
6854 1.1 mrg need loads of library functions. They cannot have values >
6855 1.1 mrg BIT_SIZE (I) so the conversion is safe. */
6856 1.1 mrg args[1] = convert (int4type, args[1]);
6857 1.1 mrg args[2] = convert (int4type, args[2]);
6858 1.1 mrg
6859 1.1 mrg /* Optionally generate code for runtime argument check. */
6860 1.1 mrg if (gfc_option.rtcheck & GFC_RTCHECK_BITS)
6861 1.1 mrg {
6862 1.1 mrg tree size = fold_convert (long_integer_type_node, args[2]);
6863 1.1 mrg tree below = fold_build2_loc (input_location, LE_EXPR,
6864 1.1 mrg logical_type_node, size,
6865 1.1 mrg build_int_cst (TREE_TYPE (args[1]), 0));
6866 1.1 mrg tree above = fold_build2_loc (input_location, GT_EXPR,
6867 1.1 mrg logical_type_node, size, nbits);
6868 1.1 mrg tree scond = fold_build2_loc (input_location, TRUTH_ORIF_EXPR,
6869 1.1 mrg logical_type_node, below, above);
6870 1.1 mrg gfc_trans_runtime_check (true, false, scond, &se->pre, &expr->where,
6871 1.1 mrg "SIZE argument (%ld) out of range 1:%ld "
6872 1.1 mrg "in intrinsic ISHFTC", size, nbits);
6873 1.1 mrg tree width = fold_convert (long_integer_type_node, args[1]);
6874 1.1 mrg width = fold_build1_loc (input_location, ABS_EXPR,
6875 1.1 mrg long_integer_type_node, width);
6876 1.1 mrg scond = fold_build2_loc (input_location, GT_EXPR,
6877 1.1 mrg logical_type_node, width, size);
6878 1.1 mrg gfc_trans_runtime_check (true, false, scond, &se->pre, &expr->where,
6879 1.1 mrg "SHIFT argument (%ld) out of range -%ld:%ld "
6880 1.1 mrg "in intrinsic ISHFTC",
6881 1.1 mrg fold_convert (long_integer_type_node, args[1]),
6882 1.1 mrg size, size);
6883 1.1 mrg }
6884 1.1 mrg
6885 1.1 mrg switch (expr->ts.kind)
6886 1.1 mrg {
6887 1.1 mrg case 1:
6888 1.1 mrg case 2:
6889 1.1 mrg case 4:
6890 1.1 mrg tmp = gfor_fndecl_math_ishftc4;
6891 1.1 mrg break;
6892 1.1 mrg case 8:
6893 1.1 mrg tmp = gfor_fndecl_math_ishftc8;
6894 1.1 mrg break;
6895 1.1 mrg case 16:
6896 1.1 mrg tmp = gfor_fndecl_math_ishftc16;
6897 1.1 mrg break;
6898 1.1 mrg default:
6899 1.1 mrg gcc_unreachable ();
6900 1.1 mrg }
6901 1.1 mrg se->expr = build_call_expr_loc (input_location,
6902 1.1 mrg tmp, 3, args[0], args[1], args[2]);
6903 1.1 mrg /* Convert the result back to the original type, if we extended
6904 1.1 mrg the first argument's width above. */
6905 1.1 mrg if (expr->ts.kind < 4)
6906 1.1 mrg se->expr = convert (type, se->expr);
6907 1.1 mrg
6908 1.1 mrg return;
6909 1.1 mrg }
6910 1.1 mrg
6911 1.1 mrg /* Evaluate arguments only once. */
6912 1.1 mrg args[0] = gfc_evaluate_now (args[0], &se->pre);
6913 1.1 mrg args[1] = gfc_evaluate_now (args[1], &se->pre);
6914 1.1 mrg
6915 1.1 mrg /* Optionally generate code for runtime argument check. */
6916 1.1 mrg if (gfc_option.rtcheck & GFC_RTCHECK_BITS)
6917 1.1 mrg {
6918 1.1 mrg tree width = fold_convert (long_integer_type_node, args[1]);
6919 1.1 mrg width = fold_build1_loc (input_location, ABS_EXPR,
6920 1.1 mrg long_integer_type_node, width);
6921 1.1 mrg tree outside = fold_build2_loc (input_location, GT_EXPR,
6922 1.1 mrg logical_type_node, width, nbits);
6923 1.1 mrg gfc_trans_runtime_check (true, false, outside, &se->pre, &expr->where,
6924 1.1 mrg "SHIFT argument (%ld) out of range -%ld:%ld "
6925 1.1 mrg "in intrinsic ISHFTC",
6926 1.1 mrg fold_convert (long_integer_type_node, args[1]),
6927 1.1 mrg nbits, nbits);
6928 1.1 mrg }
6929 1.1 mrg
6930 1.1 mrg /* Rotate left if positive. */
6931 1.1 mrg lrot = fold_build2_loc (input_location, LROTATE_EXPR, type, args[0], args[1]);
6932 1.1 mrg
6933 1.1 mrg /* Rotate right if negative. */
6934 1.1 mrg tmp = fold_build1_loc (input_location, NEGATE_EXPR, TREE_TYPE (args[1]),
6935 1.1 mrg args[1]);
6936 1.1 mrg rrot = fold_build2_loc (input_location,RROTATE_EXPR, type, args[0], tmp);
6937 1.1 mrg
6938 1.1 mrg zero = build_int_cst (TREE_TYPE (args[1]), 0);
6939 1.1 mrg tmp = fold_build2_loc (input_location, GT_EXPR, logical_type_node, args[1],
6940 1.1 mrg zero);
6941 1.1 mrg rrot = fold_build3_loc (input_location, COND_EXPR, type, tmp, lrot, rrot);
6942 1.1 mrg
6943 1.1 mrg /* Do nothing if shift == 0. */
6944 1.1 mrg tmp = fold_build2_loc (input_location, EQ_EXPR, logical_type_node, args[1],
6945 1.1 mrg zero);
6946 1.1 mrg se->expr = fold_build3_loc (input_location, COND_EXPR, type, tmp, args[0],
6947 1.1 mrg rrot);
6948 1.1 mrg }
6949 1.1 mrg
6950 1.1 mrg
6951 1.1 mrg /* LEADZ (i) = (i == 0) ? BIT_SIZE (i)
6952 1.1 mrg : __builtin_clz(i) - (BIT_SIZE('int') - BIT_SIZE(i))
6953 1.1 mrg
6954 1.1 mrg The conditional expression is necessary because the result of LEADZ(0)
6955 1.1 mrg is defined, but the result of __builtin_clz(0) is undefined for most
6956 1.1 mrg targets.
6957 1.1 mrg
6958 1.1 mrg For INTEGER kinds smaller than the C 'int' type, we have to subtract the
6959 1.1 mrg difference in bit size between the argument of LEADZ and the C int. */
6960 1.1 mrg
6961 1.1 mrg static void
6962 1.1 mrg gfc_conv_intrinsic_leadz (gfc_se * se, gfc_expr * expr)
6963 1.1 mrg {
6964 1.1 mrg tree arg;
6965 1.1 mrg tree arg_type;
6966 1.1 mrg tree cond;
6967 1.1 mrg tree result_type;
6968 1.1 mrg tree leadz;
6969 1.1 mrg tree bit_size;
6970 1.1 mrg tree tmp;
6971 1.1 mrg tree func;
6972 1.1 mrg int s, argsize;
6973 1.1 mrg
6974 1.1 mrg gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
6975 1.1 mrg argsize = TYPE_PRECISION (TREE_TYPE (arg));
6976 1.1 mrg
6977 1.1 mrg /* Which variant of __builtin_clz* should we call? */
6978 1.1 mrg if (argsize <= INT_TYPE_SIZE)
6979 1.1 mrg {
6980 1.1 mrg arg_type = unsigned_type_node;
6981 1.1 mrg func = builtin_decl_explicit (BUILT_IN_CLZ);
6982 1.1 mrg }
6983 1.1 mrg else if (argsize <= LONG_TYPE_SIZE)
6984 1.1 mrg {
6985 1.1 mrg arg_type = long_unsigned_type_node;
6986 1.1 mrg func = builtin_decl_explicit (BUILT_IN_CLZL);
6987 1.1 mrg }
6988 1.1 mrg else if (argsize <= LONG_LONG_TYPE_SIZE)
6989 1.1 mrg {
6990 1.1 mrg arg_type = long_long_unsigned_type_node;
6991 1.1 mrg func = builtin_decl_explicit (BUILT_IN_CLZLL);
6992 1.1 mrg }
6993 1.1 mrg else
6994 1.1 mrg {
6995 1.1 mrg gcc_assert (argsize == 2 * LONG_LONG_TYPE_SIZE);
6996 1.1 mrg arg_type = gfc_build_uint_type (argsize);
6997 1.1 mrg func = NULL_TREE;
6998 1.1 mrg }
6999 1.1 mrg
7000 1.1 mrg /* Convert the actual argument twice: first, to the unsigned type of the
7001 1.1 mrg same size; then, to the proper argument type for the built-in
7002 1.1 mrg function. But the return type is of the default INTEGER kind. */
7003 1.1 mrg arg = fold_convert (gfc_build_uint_type (argsize), arg);
7004 1.1 mrg arg = fold_convert (arg_type, arg);
7005 1.1 mrg arg = gfc_evaluate_now (arg, &se->pre);
7006 1.1 mrg result_type = gfc_get_int_type (gfc_default_integer_kind);
7007 1.1 mrg
7008 1.1 mrg /* Compute LEADZ for the case i .ne. 0. */
7009 1.1 mrg if (func)
7010 1.1 mrg {
7011 1.1 mrg s = TYPE_PRECISION (arg_type) - argsize;
7012 1.1 mrg tmp = fold_convert (result_type,
7013 1.1 mrg build_call_expr_loc (input_location, func,
7014 1.1 mrg 1, arg));
7015 1.1 mrg leadz = fold_build2_loc (input_location, MINUS_EXPR, result_type,
7016 1.1 mrg tmp, build_int_cst (result_type, s));
7017 1.1 mrg }
7018 1.1 mrg else
7019 1.1 mrg {
7020 1.1 mrg /* We end up here if the argument type is larger than 'long long'.
7021 1.1 mrg We generate this code:
7022 1.1 mrg
7023 1.1 mrg if (x & (ULL_MAX << ULL_SIZE) != 0)
7024 1.1 mrg return clzll ((unsigned long long) (x >> ULLSIZE));
7025 1.1 mrg else
7026 1.1 mrg return ULL_SIZE + clzll ((unsigned long long) x);
7027 1.1 mrg where ULL_MAX is the largest value that a ULL_MAX can hold
7028 1.1 mrg (0xFFFFFFFFFFFFFFFF for a 64-bit long long type), and ULLSIZE
7029 1.1 mrg is the bit-size of the long long type (64 in this example). */
7030 1.1 mrg tree ullsize, ullmax, tmp1, tmp2, btmp;
7031 1.1 mrg
7032 1.1 mrg ullsize = build_int_cst (result_type, LONG_LONG_TYPE_SIZE);
7033 1.1 mrg ullmax = fold_build1_loc (input_location, BIT_NOT_EXPR,
7034 1.1 mrg long_long_unsigned_type_node,
7035 1.1 mrg build_int_cst (long_long_unsigned_type_node,
7036 1.1 mrg 0));
7037 1.1 mrg
7038 1.1 mrg cond = fold_build2_loc (input_location, LSHIFT_EXPR, arg_type,
7039 1.1 mrg fold_convert (arg_type, ullmax), ullsize);
7040 1.1 mrg cond = fold_build2_loc (input_location, BIT_AND_EXPR, arg_type,
7041 1.1 mrg arg, cond);
7042 1.1 mrg cond = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
7043 1.1 mrg cond, build_int_cst (arg_type, 0));
7044 1.1 mrg
7045 1.1 mrg tmp1 = fold_build2_loc (input_location, RSHIFT_EXPR, arg_type,
7046 1.1 mrg arg, ullsize);
7047 1.1 mrg tmp1 = fold_convert (long_long_unsigned_type_node, tmp1);
7048 1.1 mrg btmp = builtin_decl_explicit (BUILT_IN_CLZLL);
7049 1.1 mrg tmp1 = fold_convert (result_type,
7050 1.1 mrg build_call_expr_loc (input_location, btmp, 1, tmp1));
7051 1.1 mrg
7052 1.1 mrg tmp2 = fold_convert (long_long_unsigned_type_node, arg);
7053 1.1 mrg btmp = builtin_decl_explicit (BUILT_IN_CLZLL);
7054 1.1 mrg tmp2 = fold_convert (result_type,
7055 1.1 mrg build_call_expr_loc (input_location, btmp, 1, tmp2));
7056 1.1 mrg tmp2 = fold_build2_loc (input_location, PLUS_EXPR, result_type,
7057 1.1 mrg tmp2, ullsize);
7058 1.1 mrg
7059 1.1 mrg leadz = fold_build3_loc (input_location, COND_EXPR, result_type,
7060 1.1 mrg cond, tmp1, tmp2);
7061 1.1 mrg }
7062 1.1 mrg
7063 1.1 mrg /* Build BIT_SIZE. */
7064 1.1 mrg bit_size = build_int_cst (result_type, argsize);
7065 1.1 mrg
7066 1.1 mrg cond = fold_build2_loc (input_location, EQ_EXPR, logical_type_node,
7067 1.1 mrg arg, build_int_cst (arg_type, 0));
7068 1.1 mrg se->expr = fold_build3_loc (input_location, COND_EXPR, result_type, cond,
7069 1.1 mrg bit_size, leadz);
7070 1.1 mrg }
7071 1.1 mrg
7072 1.1 mrg
7073 1.1 mrg /* TRAILZ(i) = (i == 0) ? BIT_SIZE (i) : __builtin_ctz(i)
7074 1.1 mrg
7075 1.1 mrg The conditional expression is necessary because the result of TRAILZ(0)
7076 1.1 mrg is defined, but the result of __builtin_ctz(0) is undefined for most
7077 1.1 mrg targets. */
7078 1.1 mrg
7079 1.1 mrg static void
7080 1.1 mrg gfc_conv_intrinsic_trailz (gfc_se * se, gfc_expr *expr)
7081 1.1 mrg {
7082 1.1 mrg tree arg;
7083 1.1 mrg tree arg_type;
7084 1.1 mrg tree cond;
7085 1.1 mrg tree result_type;
7086 1.1 mrg tree trailz;
7087 1.1 mrg tree bit_size;
7088 1.1 mrg tree func;
7089 1.1 mrg int argsize;
7090 1.1 mrg
7091 1.1 mrg gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
7092 1.1 mrg argsize = TYPE_PRECISION (TREE_TYPE (arg));
7093 1.1 mrg
7094 1.1 mrg /* Which variant of __builtin_ctz* should we call? */
7095 1.1 mrg if (argsize <= INT_TYPE_SIZE)
7096 1.1 mrg {
7097 1.1 mrg arg_type = unsigned_type_node;
7098 1.1 mrg func = builtin_decl_explicit (BUILT_IN_CTZ);
7099 1.1 mrg }
7100 1.1 mrg else if (argsize <= LONG_TYPE_SIZE)
7101 1.1 mrg {
7102 1.1 mrg arg_type = long_unsigned_type_node;
7103 1.1 mrg func = builtin_decl_explicit (BUILT_IN_CTZL);
7104 1.1 mrg }
7105 1.1 mrg else if (argsize <= LONG_LONG_TYPE_SIZE)
7106 1.1 mrg {
7107 1.1 mrg arg_type = long_long_unsigned_type_node;
7108 1.1 mrg func = builtin_decl_explicit (BUILT_IN_CTZLL);
7109 1.1 mrg }
7110 1.1 mrg else
7111 1.1 mrg {
7112 1.1 mrg gcc_assert (argsize == 2 * LONG_LONG_TYPE_SIZE);
7113 1.1 mrg arg_type = gfc_build_uint_type (argsize);
7114 1.1 mrg func = NULL_TREE;
7115 1.1 mrg }
7116 1.1 mrg
7117 1.1 mrg /* Convert the actual argument twice: first, to the unsigned type of the
7118 1.1 mrg same size; then, to the proper argument type for the built-in
7119 1.1 mrg function. But the return type is of the default INTEGER kind. */
7120 1.1 mrg arg = fold_convert (gfc_build_uint_type (argsize), arg);
7121 1.1 mrg arg = fold_convert (arg_type, arg);
7122 1.1 mrg arg = gfc_evaluate_now (arg, &se->pre);
7123 1.1 mrg result_type = gfc_get_int_type (gfc_default_integer_kind);
7124 1.1 mrg
7125 1.1 mrg /* Compute TRAILZ for the case i .ne. 0. */
7126 1.1 mrg if (func)
7127 1.1 mrg trailz = fold_convert (result_type, build_call_expr_loc (input_location,
7128 1.1 mrg func, 1, arg));
7129 1.1 mrg else
7130 1.1 mrg {
7131 1.1 mrg /* We end up here if the argument type is larger than 'long long'.
7132 1.1 mrg We generate this code:
7133 1.1 mrg
7134 1.1 mrg if ((x & ULL_MAX) == 0)
7135 1.1 mrg return ULL_SIZE + ctzll ((unsigned long long) (x >> ULLSIZE));
7136 1.1 mrg else
7137 1.1 mrg return ctzll ((unsigned long long) x);
7138 1.1 mrg
7139 1.1 mrg where ULL_MAX is the largest value that a ULL_MAX can hold
7140 1.1 mrg (0xFFFFFFFFFFFFFFFF for a 64-bit long long type), and ULLSIZE
7141 1.1 mrg is the bit-size of the long long type (64 in this example). */
7142 1.1 mrg tree ullsize, ullmax, tmp1, tmp2, btmp;
7143 1.1 mrg
7144 1.1 mrg ullsize = build_int_cst (result_type, LONG_LONG_TYPE_SIZE);
7145 1.1 mrg ullmax = fold_build1_loc (input_location, BIT_NOT_EXPR,
7146 1.1 mrg long_long_unsigned_type_node,
7147 1.1 mrg build_int_cst (long_long_unsigned_type_node, 0));
7148 1.1 mrg
7149 1.1 mrg cond = fold_build2_loc (input_location, BIT_AND_EXPR, arg_type, arg,
7150 1.1 mrg fold_convert (arg_type, ullmax));
7151 1.1 mrg cond = fold_build2_loc (input_location, EQ_EXPR, logical_type_node, cond,
7152 1.1 mrg build_int_cst (arg_type, 0));
7153 1.1 mrg
7154 1.1 mrg tmp1 = fold_build2_loc (input_location, RSHIFT_EXPR, arg_type,
7155 1.1 mrg arg, ullsize);
7156 1.1 mrg tmp1 = fold_convert (long_long_unsigned_type_node, tmp1);
7157 1.1 mrg btmp = builtin_decl_explicit (BUILT_IN_CTZLL);
7158 1.1 mrg tmp1 = fold_convert (result_type,
7159 1.1 mrg build_call_expr_loc (input_location, btmp, 1, tmp1));
7160 1.1 mrg tmp1 = fold_build2_loc (input_location, PLUS_EXPR, result_type,
7161 1.1 mrg tmp1, ullsize);
7162 1.1 mrg
7163 1.1 mrg tmp2 = fold_convert (long_long_unsigned_type_node, arg);
7164 1.1 mrg btmp = builtin_decl_explicit (BUILT_IN_CTZLL);
7165 1.1 mrg tmp2 = fold_convert (result_type,
7166 1.1 mrg build_call_expr_loc (input_location, btmp, 1, tmp2));
7167 1.1 mrg
7168 1.1 mrg trailz = fold_build3_loc (input_location, COND_EXPR, result_type,
7169 1.1 mrg cond, tmp1, tmp2);
7170 1.1 mrg }
7171 1.1 mrg
7172 1.1 mrg /* Build BIT_SIZE. */
7173 1.1 mrg bit_size = build_int_cst (result_type, argsize);
7174 1.1 mrg
7175 1.1 mrg cond = fold_build2_loc (input_location, EQ_EXPR, logical_type_node,
7176 1.1 mrg arg, build_int_cst (arg_type, 0));
7177 1.1 mrg se->expr = fold_build3_loc (input_location, COND_EXPR, result_type, cond,
7178 1.1 mrg bit_size, trailz);
7179 1.1 mrg }
7180 1.1 mrg
7181 1.1 mrg /* Using __builtin_popcount for POPCNT and __builtin_parity for POPPAR;
7182 1.1 mrg for types larger than "long long", we call the long long built-in for
7183 1.1 mrg the lower and higher bits and combine the result. */
7184 1.1 mrg
7185 1.1 mrg static void
7186 1.1 mrg gfc_conv_intrinsic_popcnt_poppar (gfc_se * se, gfc_expr *expr, int parity)
7187 1.1 mrg {
7188 1.1 mrg tree arg;
7189 1.1 mrg tree arg_type;
7190 1.1 mrg tree result_type;
7191 1.1 mrg tree func;
7192 1.1 mrg int argsize;
7193 1.1 mrg
7194 1.1 mrg gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
7195 1.1 mrg argsize = TYPE_PRECISION (TREE_TYPE (arg));
7196 1.1 mrg result_type = gfc_get_int_type (gfc_default_integer_kind);
7197 1.1 mrg
7198 1.1 mrg /* Which variant of the builtin should we call? */
7199 1.1 mrg if (argsize <= INT_TYPE_SIZE)
7200 1.1 mrg {
7201 1.1 mrg arg_type = unsigned_type_node;
7202 1.1 mrg func = builtin_decl_explicit (parity
7203 1.1 mrg ? BUILT_IN_PARITY
7204 1.1 mrg : BUILT_IN_POPCOUNT);
7205 1.1 mrg }
7206 1.1 mrg else if (argsize <= LONG_TYPE_SIZE)
7207 1.1 mrg {
7208 1.1 mrg arg_type = long_unsigned_type_node;
7209 1.1 mrg func = builtin_decl_explicit (parity
7210 1.1 mrg ? BUILT_IN_PARITYL
7211 1.1 mrg : BUILT_IN_POPCOUNTL);
7212 1.1 mrg }
7213 1.1 mrg else if (argsize <= LONG_LONG_TYPE_SIZE)
7214 1.1 mrg {
7215 1.1 mrg arg_type = long_long_unsigned_type_node;
7216 1.1 mrg func = builtin_decl_explicit (parity
7217 1.1 mrg ? BUILT_IN_PARITYLL
7218 1.1 mrg : BUILT_IN_POPCOUNTLL);
7219 1.1 mrg }
7220 1.1 mrg else
7221 1.1 mrg {
7222 1.1 mrg /* Our argument type is larger than 'long long', which mean none
7223 1.1 mrg of the POPCOUNT builtins covers it. We thus call the 'long long'
7224 1.1 mrg variant multiple times, and add the results. */
7225 1.1 mrg tree utype, arg2, call1, call2;
7226 1.1 mrg
7227 1.1 mrg /* For now, we only cover the case where argsize is twice as large
7228 1.1 mrg as 'long long'. */
7229 1.1 mrg gcc_assert (argsize == 2 * LONG_LONG_TYPE_SIZE);
7230 1.1 mrg
7231 1.1 mrg func = builtin_decl_explicit (parity
7232 1.1 mrg ? BUILT_IN_PARITYLL
7233 1.1 mrg : BUILT_IN_POPCOUNTLL);
7234 1.1 mrg
7235 1.1 mrg /* Convert it to an integer, and store into a variable. */
7236 1.1 mrg utype = gfc_build_uint_type (argsize);
7237 1.1 mrg arg = fold_convert (utype, arg);
7238 1.1 mrg arg = gfc_evaluate_now (arg, &se->pre);
7239 1.1 mrg
7240 1.1 mrg /* Call the builtin twice. */
7241 1.1 mrg call1 = build_call_expr_loc (input_location, func, 1,
7242 1.1 mrg fold_convert (long_long_unsigned_type_node,
7243 1.1 mrg arg));
7244 1.1 mrg
7245 1.1 mrg arg2 = fold_build2_loc (input_location, RSHIFT_EXPR, utype, arg,
7246 1.1 mrg build_int_cst (utype, LONG_LONG_TYPE_SIZE));
7247 1.1 mrg call2 = build_call_expr_loc (input_location, func, 1,
7248 1.1 mrg fold_convert (long_long_unsigned_type_node,
7249 1.1 mrg arg2));
7250 1.1 mrg
7251 1.1 mrg /* Combine the results. */
7252 1.1 mrg if (parity)
7253 1.1 mrg se->expr = fold_build2_loc (input_location, BIT_XOR_EXPR,
7254 1.1 mrg integer_type_node, call1, call2);
7255 1.1 mrg else
7256 1.1 mrg se->expr = fold_build2_loc (input_location, PLUS_EXPR,
7257 1.1 mrg integer_type_node, call1, call2);
7258 1.1 mrg
7259 1.1 mrg se->expr = convert (result_type, se->expr);
7260 1.1 mrg return;
7261 1.1 mrg }
7262 1.1 mrg
7263 1.1 mrg /* Convert the actual argument twice: first, to the unsigned type of the
7264 1.1 mrg same size; then, to the proper argument type for the built-in
7265 1.1 mrg function. */
7266 1.1 mrg arg = fold_convert (gfc_build_uint_type (argsize), arg);
7267 1.1 mrg arg = fold_convert (arg_type, arg);
7268 1.1 mrg
7269 1.1 mrg se->expr = fold_convert (result_type,
7270 1.1 mrg build_call_expr_loc (input_location, func, 1, arg));
7271 1.1 mrg }
7272 1.1 mrg
7273 1.1 mrg
7274 1.1 mrg /* Process an intrinsic with unspecified argument-types that has an optional
7275 1.1 mrg argument (which could be of type character), e.g. EOSHIFT. For those, we
7276 1.1 mrg need to append the string length of the optional argument if it is not
7277 1.1 mrg present and the type is really character.
7278 1.1 mrg primary specifies the position (starting at 1) of the non-optional argument
7279 1.1 mrg specifying the type and optional gives the position of the optional
7280 1.1 mrg argument in the arglist. */
7281 1.1 mrg
7282 1.1 mrg static void
7283 1.1 mrg conv_generic_with_optional_char_arg (gfc_se* se, gfc_expr* expr,
7284 1.1 mrg unsigned primary, unsigned optional)
7285 1.1 mrg {
7286 1.1 mrg gfc_actual_arglist* prim_arg;
7287 1.1 mrg gfc_actual_arglist* opt_arg;
7288 1.1 mrg unsigned cur_pos;
7289 1.1 mrg gfc_actual_arglist* arg;
7290 1.1 mrg gfc_symbol* sym;
7291 1.1 mrg vec<tree, va_gc> *append_args;
7292 1.1 mrg
7293 1.1 mrg /* Find the two arguments given as position. */
7294 1.1 mrg cur_pos = 0;
7295 1.1 mrg prim_arg = NULL;
7296 1.1 mrg opt_arg = NULL;
7297 1.1 mrg for (arg = expr->value.function.actual; arg; arg = arg->next)
7298 1.1 mrg {
7299 1.1 mrg ++cur_pos;
7300 1.1 mrg
7301 1.1 mrg if (cur_pos == primary)
7302 1.1 mrg prim_arg = arg;
7303 1.1 mrg if (cur_pos == optional)
7304 1.1 mrg opt_arg = arg;
7305 1.1 mrg
7306 1.1 mrg if (cur_pos >= primary && cur_pos >= optional)
7307 1.1 mrg break;
7308 1.1 mrg }
7309 1.1 mrg gcc_assert (prim_arg);
7310 1.1 mrg gcc_assert (prim_arg->expr);
7311 1.1 mrg gcc_assert (opt_arg);
7312 1.1 mrg
7313 1.1 mrg /* If we do have type CHARACTER and the optional argument is really absent,
7314 1.1 mrg append a dummy 0 as string length. */
7315 1.1 mrg append_args = NULL;
7316 1.1 mrg if (prim_arg->expr->ts.type == BT_CHARACTER && !opt_arg->expr)
7317 1.1 mrg {
7318 1.1 mrg tree dummy;
7319 1.1 mrg
7320 1.1 mrg dummy = build_int_cst (gfc_charlen_type_node, 0);
7321 1.1 mrg vec_alloc (append_args, 1);
7322 1.1 mrg append_args->quick_push (dummy);
7323 1.1 mrg }
7324 1.1 mrg
7325 1.1 mrg /* Build the call itself. */
7326 1.1 mrg gcc_assert (!se->ignore_optional);
7327 1.1 mrg sym = gfc_get_symbol_for_expr (expr, false);
7328 1.1 mrg gfc_conv_procedure_call (se, sym, expr->value.function.actual, expr,
7329 1.1 mrg append_args);
7330 1.1 mrg gfc_free_symbol (sym);
7331 1.1 mrg }
7332 1.1 mrg
7333 1.1 mrg /* The length of a character string. */
7334 1.1 mrg static void
7335 1.1 mrg gfc_conv_intrinsic_len (gfc_se * se, gfc_expr * expr)
7336 1.1 mrg {
7337 1.1 mrg tree len;
7338 1.1 mrg tree type;
7339 1.1 mrg tree decl;
7340 1.1 mrg gfc_symbol *sym;
7341 1.1 mrg gfc_se argse;
7342 1.1 mrg gfc_expr *arg;
7343 1.1 mrg
7344 1.1 mrg gcc_assert (!se->ss);
7345 1.1 mrg
7346 1.1 mrg arg = expr->value.function.actual->expr;
7347 1.1 mrg
7348 1.1 mrg type = gfc_typenode_for_spec (&expr->ts);
7349 1.1 mrg switch (arg->expr_type)
7350 1.1 mrg {
7351 1.1 mrg case EXPR_CONSTANT:
7352 1.1 mrg len = build_int_cst (gfc_charlen_type_node, arg->value.character.length);
7353 1.1 mrg break;
7354 1.1 mrg
7355 1.1 mrg case EXPR_ARRAY:
7356 1.1 mrg /* Obtain the string length from the function used by
7357 1.1 mrg trans-array.cc(gfc_trans_array_constructor). */
7358 1.1 mrg len = NULL_TREE;
7359 1.1 mrg get_array_ctor_strlen (&se->pre, arg->value.constructor, &len);
7360 1.1 mrg break;
7361 1.1 mrg
7362 1.1 mrg case EXPR_VARIABLE:
7363 1.1 mrg if (arg->ref == NULL
7364 1.1 mrg || (arg->ref->next == NULL && arg->ref->type == REF_ARRAY))
7365 1.1 mrg {
7366 1.1 mrg /* This doesn't catch all cases.
7367 1.1 mrg See http://gcc.gnu.org/ml/fortran/2004-06/msg00165.html
7368 1.1 mrg and the surrounding thread. */
7369 1.1 mrg sym = arg->symtree->n.sym;
7370 1.1 mrg decl = gfc_get_symbol_decl (sym);
7371 1.1 mrg if (decl == current_function_decl && sym->attr.function
7372 1.1 mrg && (sym->result == sym))
7373 1.1 mrg decl = gfc_get_fake_result_decl (sym, 0);
7374 1.1 mrg
7375 1.1 mrg len = sym->ts.u.cl->backend_decl;
7376 1.1 mrg gcc_assert (len);
7377 1.1 mrg break;
7378 1.1 mrg }
7379 1.1 mrg
7380 1.1 mrg /* Fall through. */
7381 1.1 mrg
7382 1.1 mrg default:
7383 1.1 mrg gfc_init_se (&argse, se);
7384 1.1 mrg if (arg->rank == 0)
7385 1.1 mrg gfc_conv_expr (&argse, arg);
7386 1.1 mrg else
7387 1.1 mrg gfc_conv_expr_descriptor (&argse, arg);
7388 1.1 mrg gfc_add_block_to_block (&se->pre, &argse.pre);
7389 1.1 mrg gfc_add_block_to_block (&se->post, &argse.post);
7390 1.1 mrg len = argse.string_length;
7391 1.1 mrg break;
7392 1.1 mrg }
7393 1.1 mrg se->expr = convert (type, len);
7394 1.1 mrg }
7395 1.1 mrg
7396 1.1 mrg /* The length of a character string not including trailing blanks. */
7397 1.1 mrg static void
7398 1.1 mrg gfc_conv_intrinsic_len_trim (gfc_se * se, gfc_expr * expr)
7399 1.1 mrg {
7400 1.1 mrg int kind = expr->value.function.actual->expr->ts.kind;
7401 1.1 mrg tree args[2], type, fndecl;
7402 1.1 mrg
7403 1.1 mrg gfc_conv_intrinsic_function_args (se, expr, args, 2);
7404 1.1 mrg type = gfc_typenode_for_spec (&expr->ts);
7405 1.1 mrg
7406 1.1 mrg if (kind == 1)
7407 1.1 mrg fndecl = gfor_fndecl_string_len_trim;
7408 1.1 mrg else if (kind == 4)
7409 1.1 mrg fndecl = gfor_fndecl_string_len_trim_char4;
7410 1.1 mrg else
7411 1.1 mrg gcc_unreachable ();
7412 1.1 mrg
7413 1.1 mrg se->expr = build_call_expr_loc (input_location,
7414 1.1 mrg fndecl, 2, args[0], args[1]);
7415 1.1 mrg se->expr = convert (type, se->expr);
7416 1.1 mrg }
7417 1.1 mrg
7418 1.1 mrg
7419 1.1 mrg /* Returns the starting position of a substring within a string. */
7420 1.1 mrg
7421 1.1 mrg static void
7422 1.1 mrg gfc_conv_intrinsic_index_scan_verify (gfc_se * se, gfc_expr * expr,
7423 1.1 mrg tree function)
7424 1.1 mrg {
7425 1.1 mrg tree logical4_type_node = gfc_get_logical_type (4);
7426 1.1 mrg tree type;
7427 1.1 mrg tree fndecl;
7428 1.1 mrg tree *args;
7429 1.1 mrg unsigned int num_args;
7430 1.1 mrg
7431 1.1 mrg args = XALLOCAVEC (tree, 5);
7432 1.1 mrg
7433 1.1 mrg /* Get number of arguments; characters count double due to the
7434 1.1 mrg string length argument. Kind= is not passed to the library
7435 1.1 mrg and thus ignored. */
7436 1.1 mrg if (expr->value.function.actual->next->next->expr == NULL)
7437 1.1 mrg num_args = 4;
7438 1.1 mrg else
7439 1.1 mrg num_args = 5;
7440 1.1 mrg
7441 1.1 mrg gfc_conv_intrinsic_function_args (se, expr, args, num_args);
7442 1.1 mrg type = gfc_typenode_for_spec (&expr->ts);
7443 1.1 mrg
7444 1.1 mrg if (num_args == 4)
7445 1.1 mrg args[4] = build_int_cst (logical4_type_node, 0);
7446 1.1 mrg else
7447 1.1 mrg args[4] = convert (logical4_type_node, args[4]);
7448 1.1 mrg
7449 1.1 mrg fndecl = build_addr (function);
7450 1.1 mrg se->expr = build_call_array_loc (input_location,
7451 1.1 mrg TREE_TYPE (TREE_TYPE (function)), fndecl,
7452 1.1 mrg 5, args);
7453 1.1 mrg se->expr = convert (type, se->expr);
7454 1.1 mrg
7455 1.1 mrg }
7456 1.1 mrg
7457 1.1 mrg /* The ascii value for a single character. */
7458 1.1 mrg static void
7459 1.1 mrg gfc_conv_intrinsic_ichar (gfc_se * se, gfc_expr * expr)
7460 1.1 mrg {
7461 1.1 mrg tree args[3], type, pchartype;
7462 1.1 mrg int nargs;
7463 1.1 mrg
7464 1.1 mrg nargs = gfc_intrinsic_argument_list_length (expr);
7465 1.1 mrg gfc_conv_intrinsic_function_args (se, expr, args, nargs);
7466 1.1 mrg gcc_assert (POINTER_TYPE_P (TREE_TYPE (args[1])));
7467 1.1 mrg pchartype = gfc_get_pchar_type (expr->value.function.actual->expr->ts.kind);
7468 1.1 mrg args[1] = fold_build1_loc (input_location, NOP_EXPR, pchartype, args[1]);
7469 1.1 mrg type = gfc_typenode_for_spec (&expr->ts);
7470 1.1 mrg
7471 1.1 mrg se->expr = build_fold_indirect_ref_loc (input_location,
7472 1.1 mrg args[1]);
7473 1.1 mrg se->expr = convert (type, se->expr);
7474 1.1 mrg }
7475 1.1 mrg
7476 1.1 mrg
7477 1.1 mrg /* Intrinsic ISNAN calls __builtin_isnan. */
7478 1.1 mrg
7479 1.1 mrg static void
7480 1.1 mrg gfc_conv_intrinsic_isnan (gfc_se * se, gfc_expr * expr)
7481 1.1 mrg {
7482 1.1 mrg tree arg;
7483 1.1 mrg
7484 1.1 mrg gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
7485 1.1 mrg se->expr = build_call_expr_loc (input_location,
7486 1.1 mrg builtin_decl_explicit (BUILT_IN_ISNAN),
7487 1.1 mrg 1, arg);
7488 1.1 mrg STRIP_TYPE_NOPS (se->expr);
7489 1.1 mrg se->expr = fold_convert (gfc_typenode_for_spec (&expr->ts), se->expr);
7490 1.1 mrg }
7491 1.1 mrg
7492 1.1 mrg
7493 1.1 mrg /* Intrinsics IS_IOSTAT_END and IS_IOSTAT_EOR just need to compare
7494 1.1 mrg their argument against a constant integer value. */
7495 1.1 mrg
7496 1.1 mrg static void
7497 1.1 mrg gfc_conv_has_intvalue (gfc_se * se, gfc_expr * expr, const int value)
7498 1.1 mrg {
7499 1.1 mrg tree arg;
7500 1.1 mrg
7501 1.1 mrg gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
7502 1.1 mrg se->expr = fold_build2_loc (input_location, EQ_EXPR,
7503 1.1 mrg gfc_typenode_for_spec (&expr->ts),
7504 1.1 mrg arg, build_int_cst (TREE_TYPE (arg), value));
7505 1.1 mrg }
7506 1.1 mrg
7507 1.1 mrg
7508 1.1 mrg
7509 1.1 mrg /* MERGE (tsource, fsource, mask) = mask ? tsource : fsource. */
7510 1.1 mrg
7511 1.1 mrg static void
7512 1.1 mrg gfc_conv_intrinsic_merge (gfc_se * se, gfc_expr * expr)
7513 1.1 mrg {
7514 1.1 mrg tree tsource;
7515 1.1 mrg tree fsource;
7516 1.1 mrg tree mask;
7517 1.1 mrg tree type;
7518 1.1 mrg tree len, len2;
7519 1.1 mrg tree *args;
7520 1.1 mrg unsigned int num_args;
7521 1.1 mrg
7522 1.1 mrg num_args = gfc_intrinsic_argument_list_length (expr);
7523 1.1 mrg args = XALLOCAVEC (tree, num_args);
7524 1.1 mrg
7525 1.1 mrg gfc_conv_intrinsic_function_args (se, expr, args, num_args);
7526 1.1 mrg if (expr->ts.type != BT_CHARACTER)
7527 1.1 mrg {
7528 1.1 mrg tsource = args[0];
7529 1.1 mrg fsource = args[1];
7530 1.1 mrg mask = args[2];
7531 1.1 mrg }
7532 1.1 mrg else
7533 1.1 mrg {
7534 1.1 mrg /* We do the same as in the non-character case, but the argument
7535 1.1 mrg list is different because of the string length arguments. We
7536 1.1 mrg also have to set the string length for the result. */
7537 1.1 mrg len = args[0];
7538 1.1 mrg tsource = args[1];
7539 1.1 mrg len2 = args[2];
7540 1.1 mrg fsource = args[3];
7541 1.1 mrg mask = args[4];
7542 1.1 mrg
7543 1.1 mrg gfc_trans_same_strlen_check ("MERGE intrinsic", &expr->where, len, len2,
7544 1.1 mrg &se->pre);
7545 1.1 mrg se->string_length = len;
7546 1.1 mrg }
7547 1.1 mrg type = TREE_TYPE (tsource);
7548 1.1 mrg se->expr = fold_build3_loc (input_location, COND_EXPR, type, mask, tsource,
7549 1.1 mrg fold_convert (type, fsource));
7550 1.1 mrg }
7551 1.1 mrg
7552 1.1 mrg
7553 1.1 mrg /* MERGE_BITS (I, J, MASK) = (I & MASK) | (I & (~MASK)). */
7554 1.1 mrg
7555 1.1 mrg static void
7556 1.1 mrg gfc_conv_intrinsic_merge_bits (gfc_se * se, gfc_expr * expr)
7557 1.1 mrg {
7558 1.1 mrg tree args[3], mask, type;
7559 1.1 mrg
7560 1.1 mrg gfc_conv_intrinsic_function_args (se, expr, args, 3);
7561 1.1 mrg mask = gfc_evaluate_now (args[2], &se->pre);
7562 1.1 mrg
7563 1.1 mrg type = TREE_TYPE (args[0]);
7564 1.1 mrg gcc_assert (TREE_TYPE (args[1]) == type);
7565 1.1 mrg gcc_assert (TREE_TYPE (mask) == type);
7566 1.1 mrg
7567 1.1 mrg args[0] = fold_build2_loc (input_location, BIT_AND_EXPR, type, args[0], mask);
7568 1.1 mrg args[1] = fold_build2_loc (input_location, BIT_AND_EXPR, type, args[1],
7569 1.1 mrg fold_build1_loc (input_location, BIT_NOT_EXPR,
7570 1.1 mrg type, mask));
7571 1.1 mrg se->expr = fold_build2_loc (input_location, BIT_IOR_EXPR, type,
7572 1.1 mrg args[0], args[1]);
7573 1.1 mrg }
7574 1.1 mrg
7575 1.1 mrg
7576 1.1 mrg /* MASKL(n) = n == 0 ? 0 : (~0) << (BIT_SIZE - n)
7577 1.1 mrg MASKR(n) = n == BIT_SIZE ? ~0 : ~((~0) << n) */
7578 1.1 mrg
7579 1.1 mrg static void
7580 1.1 mrg gfc_conv_intrinsic_mask (gfc_se * se, gfc_expr * expr, int left)
7581 1.1 mrg {
7582 1.1 mrg tree arg, allones, type, utype, res, cond, bitsize;
7583 1.1 mrg int i;
7584 1.1 mrg
7585 1.1 mrg gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
7586 1.1 mrg arg = gfc_evaluate_now (arg, &se->pre);
7587 1.1 mrg
7588 1.1 mrg type = gfc_get_int_type (expr->ts.kind);
7589 1.1 mrg utype = unsigned_type_for (type);
7590 1.1 mrg
7591 1.1 mrg i = gfc_validate_kind (BT_INTEGER, expr->ts.kind, false);
7592 1.1 mrg bitsize = build_int_cst (TREE_TYPE (arg), gfc_integer_kinds[i].bit_size);
7593 1.1 mrg
7594 1.1 mrg allones = fold_build1_loc (input_location, BIT_NOT_EXPR, utype,
7595 1.1 mrg build_int_cst (utype, 0));
7596 1.1 mrg
7597 1.1 mrg if (left)
7598 1.1 mrg {
7599 1.1 mrg /* Left-justified mask. */
7600 1.1 mrg res = fold_build2_loc (input_location, MINUS_EXPR, TREE_TYPE (arg),
7601 1.1 mrg bitsize, arg);
7602 1.1 mrg res = fold_build2_loc (input_location, LSHIFT_EXPR, utype, allones,
7603 1.1 mrg fold_convert (utype, res));
7604 1.1 mrg
7605 1.1 mrg /* Special case arg == 0, because SHIFT_EXPR wants a shift strictly
7606 1.1 mrg smaller than type width. */
7607 1.1 mrg cond = fold_build2_loc (input_location, EQ_EXPR, logical_type_node, arg,
7608 1.1 mrg build_int_cst (TREE_TYPE (arg), 0));
7609 1.1 mrg res = fold_build3_loc (input_location, COND_EXPR, utype, cond,
7610 1.1 mrg build_int_cst (utype, 0), res);
7611 1.1 mrg }
7612 1.1 mrg else
7613 1.1 mrg {
7614 1.1 mrg /* Right-justified mask. */
7615 1.1 mrg res = fold_build2_loc (input_location, LSHIFT_EXPR, utype, allones,
7616 1.1 mrg fold_convert (utype, arg));
7617 1.1 mrg res = fold_build1_loc (input_location, BIT_NOT_EXPR, utype, res);
7618 1.1 mrg
7619 1.1 mrg /* Special case agr == bit_size, because SHIFT_EXPR wants a shift
7620 1.1 mrg strictly smaller than type width. */
7621 1.1 mrg cond = fold_build2_loc (input_location, EQ_EXPR, logical_type_node,
7622 1.1 mrg arg, bitsize);
7623 1.1 mrg res = fold_build3_loc (input_location, COND_EXPR, utype,
7624 1.1 mrg cond, allones, res);
7625 1.1 mrg }
7626 1.1 mrg
7627 1.1 mrg se->expr = fold_convert (type, res);
7628 1.1 mrg }
7629 1.1 mrg
7630 1.1 mrg
7631 1.1 mrg /* FRACTION (s) is translated into:
7632 1.1 mrg isfinite (s) ? frexp (s, &dummy_int) : NaN */
7633 1.1 mrg static void
7634 1.1 mrg gfc_conv_intrinsic_fraction (gfc_se * se, gfc_expr * expr)
7635 1.1 mrg {
7636 1.1 mrg tree arg, type, tmp, res, frexp, cond;
7637 1.1 mrg
7638 1.1 mrg frexp = gfc_builtin_decl_for_float_kind (BUILT_IN_FREXP, expr->ts.kind);
7639 1.1 mrg
7640 1.1 mrg type = gfc_typenode_for_spec (&expr->ts);
7641 1.1 mrg gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
7642 1.1 mrg arg = gfc_evaluate_now (arg, &se->pre);
7643 1.1 mrg
7644 1.1 mrg cond = build_call_expr_loc (input_location,
7645 1.1 mrg builtin_decl_explicit (BUILT_IN_ISFINITE),
7646 1.1 mrg 1, arg);
7647 1.1 mrg
7648 1.1 mrg tmp = gfc_create_var (integer_type_node, NULL);
7649 1.1 mrg res = build_call_expr_loc (input_location, frexp, 2,
7650 1.1 mrg fold_convert (type, arg),
7651 1.1 mrg gfc_build_addr_expr (NULL_TREE, tmp));
7652 1.1 mrg res = fold_convert (type, res);
7653 1.1 mrg
7654 1.1 mrg se->expr = fold_build3_loc (input_location, COND_EXPR, type,
7655 1.1 mrg cond, res, gfc_build_nan (type, ""));
7656 1.1 mrg }
7657 1.1 mrg
7658 1.1 mrg
7659 1.1 mrg /* NEAREST (s, dir) is translated into
7660 1.1 mrg tmp = copysign (HUGE_VAL, dir);
7661 1.1 mrg return nextafter (s, tmp);
7662 1.1 mrg */
7663 1.1 mrg static void
7664 1.1 mrg gfc_conv_intrinsic_nearest (gfc_se * se, gfc_expr * expr)
7665 1.1 mrg {
7666 1.1 mrg tree args[2], type, tmp, nextafter, copysign, huge_val;
7667 1.1 mrg
7668 1.1 mrg nextafter = gfc_builtin_decl_for_float_kind (BUILT_IN_NEXTAFTER, expr->ts.kind);
7669 1.1 mrg copysign = gfc_builtin_decl_for_float_kind (BUILT_IN_COPYSIGN, expr->ts.kind);
7670 1.1 mrg
7671 1.1 mrg type = gfc_typenode_for_spec (&expr->ts);
7672 1.1 mrg gfc_conv_intrinsic_function_args (se, expr, args, 2);
7673 1.1 mrg
7674 1.1 mrg huge_val = gfc_build_inf_or_huge (type, expr->ts.kind);
7675 1.1 mrg tmp = build_call_expr_loc (input_location, copysign, 2, huge_val,
7676 1.1 mrg fold_convert (type, args[1]));
7677 1.1 mrg se->expr = build_call_expr_loc (input_location, nextafter, 2,
7678 1.1 mrg fold_convert (type, args[0]), tmp);
7679 1.1 mrg se->expr = fold_convert (type, se->expr);
7680 1.1 mrg }
7681 1.1 mrg
7682 1.1 mrg
7683 1.1 mrg /* SPACING (s) is translated into
7684 1.1 mrg int e;
7685 1.1 mrg if (!isfinite (s))
7686 1.1 mrg res = NaN;
7687 1.1 mrg else if (s == 0)
7688 1.1 mrg res = tiny;
7689 1.1 mrg else
7690 1.1 mrg {
7691 1.1 mrg frexp (s, &e);
7692 1.1 mrg e = e - prec;
7693 1.1 mrg e = MAX_EXPR (e, emin);
7694 1.1 mrg res = scalbn (1., e);
7695 1.1 mrg }
7696 1.1 mrg return res;
7697 1.1 mrg
7698 1.1 mrg where prec is the precision of s, gfc_real_kinds[k].digits,
7699 1.1 mrg emin is min_exponent - 1, gfc_real_kinds[k].min_exponent - 1,
7700 1.1 mrg and tiny is tiny(s), gfc_real_kinds[k].tiny. */
7701 1.1 mrg
7702 1.1 mrg static void
7703 1.1 mrg gfc_conv_intrinsic_spacing (gfc_se * se, gfc_expr * expr)
7704 1.1 mrg {
7705 1.1 mrg tree arg, type, prec, emin, tiny, res, e;
7706 1.1 mrg tree cond, nan, tmp, frexp, scalbn;
7707 1.1 mrg int k;
7708 1.1 mrg stmtblock_t block;
7709 1.1 mrg
7710 1.1 mrg k = gfc_validate_kind (BT_REAL, expr->ts.kind, false);
7711 1.1 mrg prec = build_int_cst (integer_type_node, gfc_real_kinds[k].digits);
7712 1.1 mrg emin = build_int_cst (integer_type_node, gfc_real_kinds[k].min_exponent - 1);
7713 1.1 mrg tiny = gfc_conv_mpfr_to_tree (gfc_real_kinds[k].tiny, expr->ts.kind, 0);
7714 1.1 mrg
7715 1.1 mrg frexp = gfc_builtin_decl_for_float_kind (BUILT_IN_FREXP, expr->ts.kind);
7716 1.1 mrg scalbn = gfc_builtin_decl_for_float_kind (BUILT_IN_SCALBN, expr->ts.kind);
7717 1.1 mrg
7718 1.1 mrg gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
7719 1.1 mrg arg = gfc_evaluate_now (arg, &se->pre);
7720 1.1 mrg
7721 1.1 mrg type = gfc_typenode_for_spec (&expr->ts);
7722 1.1 mrg e = gfc_create_var (integer_type_node, NULL);
7723 1.1 mrg res = gfc_create_var (type, NULL);
7724 1.1 mrg
7725 1.1 mrg
7726 1.1 mrg /* Build the block for s /= 0. */
7727 1.1 mrg gfc_start_block (&block);
7728 1.1 mrg tmp = build_call_expr_loc (input_location, frexp, 2, arg,
7729 1.1 mrg gfc_build_addr_expr (NULL_TREE, e));
7730 1.1 mrg gfc_add_expr_to_block (&block, tmp);
7731 1.1 mrg
7732 1.1 mrg tmp = fold_build2_loc (input_location, MINUS_EXPR, integer_type_node, e,
7733 1.1 mrg prec);
7734 1.1 mrg gfc_add_modify (&block, e, fold_build2_loc (input_location, MAX_EXPR,
7735 1.1 mrg integer_type_node, tmp, emin));
7736 1.1 mrg
7737 1.1 mrg tmp = build_call_expr_loc (input_location, scalbn, 2,
7738 1.1 mrg build_real_from_int_cst (type, integer_one_node), e);
7739 1.1 mrg gfc_add_modify (&block, res, tmp);
7740 1.1 mrg
7741 1.1 mrg /* Finish by building the IF statement for value zero. */
7742 1.1 mrg cond = fold_build2_loc (input_location, EQ_EXPR, logical_type_node, arg,
7743 1.1 mrg build_real_from_int_cst (type, integer_zero_node));
7744 1.1 mrg tmp = build3_v (COND_EXPR, cond, build2_v (MODIFY_EXPR, res, tiny),
7745 1.1 mrg gfc_finish_block (&block));
7746 1.1 mrg
7747 1.1 mrg /* And deal with infinities and NaNs. */
7748 1.1 mrg cond = build_call_expr_loc (input_location,
7749 1.1 mrg builtin_decl_explicit (BUILT_IN_ISFINITE),
7750 1.1 mrg 1, arg);
7751 1.1 mrg nan = gfc_build_nan (type, "");
7752 1.1 mrg tmp = build3_v (COND_EXPR, cond, tmp, build2_v (MODIFY_EXPR, res, nan));
7753 1.1 mrg
7754 1.1 mrg gfc_add_expr_to_block (&se->pre, tmp);
7755 1.1 mrg se->expr = res;
7756 1.1 mrg }
7757 1.1 mrg
7758 1.1 mrg
7759 1.1 mrg /* RRSPACING (s) is translated into
7760 1.1 mrg int e;
7761 1.1 mrg real x;
7762 1.1 mrg x = fabs (s);
7763 1.1 mrg if (isfinite (x))
7764 1.1 mrg {
7765 1.1 mrg if (x != 0)
7766 1.1 mrg {
7767 1.1 mrg frexp (s, &e);
7768 1.1 mrg x = scalbn (x, precision - e);
7769 1.1 mrg }
7770 1.1 mrg }
7771 1.1 mrg else
7772 1.1 mrg x = NaN;
7773 1.1 mrg return x;
7774 1.1 mrg
7775 1.1 mrg where precision is gfc_real_kinds[k].digits. */
7776 1.1 mrg
7777 1.1 mrg static void
7778 1.1 mrg gfc_conv_intrinsic_rrspacing (gfc_se * se, gfc_expr * expr)
7779 1.1 mrg {
7780 1.1 mrg tree arg, type, e, x, cond, nan, stmt, tmp, frexp, scalbn, fabs;
7781 1.1 mrg int prec, k;
7782 1.1 mrg stmtblock_t block;
7783 1.1 mrg
7784 1.1 mrg k = gfc_validate_kind (BT_REAL, expr->ts.kind, false);
7785 1.1 mrg prec = gfc_real_kinds[k].digits;
7786 1.1 mrg
7787 1.1 mrg frexp = gfc_builtin_decl_for_float_kind (BUILT_IN_FREXP, expr->ts.kind);
7788 1.1 mrg scalbn = gfc_builtin_decl_for_float_kind (BUILT_IN_SCALBN, expr->ts.kind);
7789 1.1 mrg fabs = gfc_builtin_decl_for_float_kind (BUILT_IN_FABS, expr->ts.kind);
7790 1.1 mrg
7791 1.1 mrg type = gfc_typenode_for_spec (&expr->ts);
7792 1.1 mrg gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
7793 1.1 mrg arg = gfc_evaluate_now (arg, &se->pre);
7794 1.1 mrg
7795 1.1 mrg e = gfc_create_var (integer_type_node, NULL);
7796 1.1 mrg x = gfc_create_var (type, NULL);
7797 1.1 mrg gfc_add_modify (&se->pre, x,
7798 1.1 mrg build_call_expr_loc (input_location, fabs, 1, arg));
7799 1.1 mrg
7800 1.1 mrg
7801 1.1 mrg gfc_start_block (&block);
7802 1.1 mrg tmp = build_call_expr_loc (input_location, frexp, 2, arg,
7803 1.1 mrg gfc_build_addr_expr (NULL_TREE, e));
7804 1.1 mrg gfc_add_expr_to_block (&block, tmp);
7805 1.1 mrg
7806 1.1 mrg tmp = fold_build2_loc (input_location, MINUS_EXPR, integer_type_node,
7807 1.1 mrg build_int_cst (integer_type_node, prec), e);
7808 1.1 mrg tmp = build_call_expr_loc (input_location, scalbn, 2, x, tmp);
7809 1.1 mrg gfc_add_modify (&block, x, tmp);
7810 1.1 mrg stmt = gfc_finish_block (&block);
7811 1.1 mrg
7812 1.1 mrg /* if (x != 0) */
7813 1.1 mrg cond = fold_build2_loc (input_location, NE_EXPR, logical_type_node, x,
7814 1.1 mrg build_real_from_int_cst (type, integer_zero_node));
7815 1.1 mrg tmp = build3_v (COND_EXPR, cond, stmt, build_empty_stmt (input_location));
7816 1.1 mrg
7817 1.1 mrg /* And deal with infinities and NaNs. */
7818 1.1 mrg cond = build_call_expr_loc (input_location,
7819 1.1 mrg builtin_decl_explicit (BUILT_IN_ISFINITE),
7820 1.1 mrg 1, x);
7821 1.1 mrg nan = gfc_build_nan (type, "");
7822 1.1 mrg tmp = build3_v (COND_EXPR, cond, tmp, build2_v (MODIFY_EXPR, x, nan));
7823 1.1 mrg
7824 1.1 mrg gfc_add_expr_to_block (&se->pre, tmp);
7825 1.1 mrg se->expr = fold_convert (type, x);
7826 1.1 mrg }
7827 1.1 mrg
7828 1.1 mrg
7829 1.1 mrg /* SCALE (s, i) is translated into scalbn (s, i). */
7830 1.1 mrg static void
7831 1.1 mrg gfc_conv_intrinsic_scale (gfc_se * se, gfc_expr * expr)
7832 1.1 mrg {
7833 1.1 mrg tree args[2], type, scalbn;
7834 1.1 mrg
7835 1.1 mrg scalbn = gfc_builtin_decl_for_float_kind (BUILT_IN_SCALBN, expr->ts.kind);
7836 1.1 mrg
7837 1.1 mrg type = gfc_typenode_for_spec (&expr->ts);
7838 1.1 mrg gfc_conv_intrinsic_function_args (se, expr, args, 2);
7839 1.1 mrg se->expr = build_call_expr_loc (input_location, scalbn, 2,
7840 1.1 mrg fold_convert (type, args[0]),
7841 1.1 mrg fold_convert (integer_type_node, args[1]));
7842 1.1 mrg se->expr = fold_convert (type, se->expr);
7843 1.1 mrg }
7844 1.1 mrg
7845 1.1 mrg
7846 1.1 mrg /* SET_EXPONENT (s, i) is translated into
7847 1.1 mrg isfinite(s) ? scalbn (frexp (s, &dummy_int), i) : NaN */
7848 1.1 mrg static void
7849 1.1 mrg gfc_conv_intrinsic_set_exponent (gfc_se * se, gfc_expr * expr)
7850 1.1 mrg {
7851 1.1 mrg tree args[2], type, tmp, frexp, scalbn, cond, nan, res;
7852 1.1 mrg
7853 1.1 mrg frexp = gfc_builtin_decl_for_float_kind (BUILT_IN_FREXP, expr->ts.kind);
7854 1.1 mrg scalbn = gfc_builtin_decl_for_float_kind (BUILT_IN_SCALBN, expr->ts.kind);
7855 1.1 mrg
7856 1.1 mrg type = gfc_typenode_for_spec (&expr->ts);
7857 1.1 mrg gfc_conv_intrinsic_function_args (se, expr, args, 2);
7858 1.1 mrg args[0] = gfc_evaluate_now (args[0], &se->pre);
7859 1.1 mrg
7860 1.1 mrg tmp = gfc_create_var (integer_type_node, NULL);
7861 1.1 mrg tmp = build_call_expr_loc (input_location, frexp, 2,
7862 1.1 mrg fold_convert (type, args[0]),
7863 1.1 mrg gfc_build_addr_expr (NULL_TREE, tmp));
7864 1.1 mrg res = build_call_expr_loc (input_location, scalbn, 2, tmp,
7865 1.1 mrg fold_convert (integer_type_node, args[1]));
7866 1.1 mrg res = fold_convert (type, res);
7867 1.1 mrg
7868 1.1 mrg /* Call to isfinite */
7869 1.1 mrg cond = build_call_expr_loc (input_location,
7870 1.1 mrg builtin_decl_explicit (BUILT_IN_ISFINITE),
7871 1.1 mrg 1, args[0]);
7872 1.1 mrg nan = gfc_build_nan (type, "");
7873 1.1 mrg
7874 1.1 mrg se->expr = fold_build3_loc (input_location, COND_EXPR, type, cond,
7875 1.1 mrg res, nan);
7876 1.1 mrg }
7877 1.1 mrg
7878 1.1 mrg
7879 1.1 mrg static void
7880 1.1 mrg gfc_conv_intrinsic_size (gfc_se * se, gfc_expr * expr)
7881 1.1 mrg {
7882 1.1 mrg gfc_actual_arglist *actual;
7883 1.1 mrg tree arg1;
7884 1.1 mrg tree type;
7885 1.1 mrg tree size;
7886 1.1 mrg gfc_se argse;
7887 1.1 mrg gfc_expr *e;
7888 1.1 mrg gfc_symbol *sym = NULL;
7889 1.1 mrg
7890 1.1 mrg gfc_init_se (&argse, NULL);
7891 1.1 mrg actual = expr->value.function.actual;
7892 1.1 mrg
7893 1.1 mrg if (actual->expr->ts.type == BT_CLASS)
7894 1.1 mrg gfc_add_class_array_ref (actual->expr);
7895 1.1 mrg
7896 1.1 mrg e = actual->expr;
7897 1.1 mrg
7898 1.1 mrg /* These are emerging from the interface mapping, when a class valued
7899 1.1 mrg function appears as the rhs in a realloc on assign statement, where
7900 1.1 mrg the size of the result is that of one of the actual arguments. */
7901 1.1 mrg if (e->expr_type == EXPR_VARIABLE
7902 1.1 mrg && e->symtree->n.sym->ns == NULL /* This is distinctive! */
7903 1.1 mrg && e->symtree->n.sym->ts.type == BT_CLASS
7904 1.1 mrg && e->ref && e->ref->type == REF_COMPONENT
7905 1.1 mrg && strcmp (e->ref->u.c.component->name, "_data") == 0)
7906 1.1 mrg sym = e->symtree->n.sym;
7907 1.1 mrg
7908 1.1 mrg if ((gfc_option.rtcheck & GFC_RTCHECK_POINTER)
7909 1.1 mrg && e
7910 1.1 mrg && (e->expr_type == EXPR_VARIABLE || e->expr_type == EXPR_FUNCTION))
7911 1.1 mrg {
7912 1.1 mrg symbol_attribute attr;
7913 1.1 mrg char *msg;
7914 1.1 mrg tree temp;
7915 1.1 mrg tree cond;
7916 1.1 mrg
7917 1.1 mrg if (e->symtree->n.sym && IS_CLASS_ARRAY (e->symtree->n.sym))
7918 1.1 mrg {
7919 1.1 mrg attr = CLASS_DATA (e->symtree->n.sym)->attr;
7920 1.1 mrg attr.pointer = attr.class_pointer;
7921 1.1 mrg }
7922 1.1 mrg else
7923 1.1 mrg attr = gfc_expr_attr (e);
7924 1.1 mrg
7925 1.1 mrg if (attr.allocatable)
7926 1.1 mrg msg = xasprintf ("Allocatable argument '%s' is not allocated",
7927 1.1 mrg e->symtree->n.sym->name);
7928 1.1 mrg else if (attr.pointer)
7929 1.1 mrg msg = xasprintf ("Pointer argument '%s' is not associated",
7930 1.1 mrg e->symtree->n.sym->name);
7931 1.1 mrg else
7932 1.1 mrg goto end_arg_check;
7933 1.1 mrg
7934 1.1 mrg if (sym)
7935 1.1 mrg {
7936 1.1 mrg temp = gfc_class_data_get (sym->backend_decl);
7937 1.1 mrg temp = gfc_conv_descriptor_data_get (temp);
7938 1.1 mrg }
7939 1.1 mrg else
7940 1.1 mrg {
7941 1.1 mrg argse.descriptor_only = 1;
7942 1.1 mrg gfc_conv_expr_descriptor (&argse, actual->expr);
7943 1.1 mrg temp = gfc_conv_descriptor_data_get (argse.expr);
7944 1.1 mrg }
7945 1.1 mrg
7946 1.1 mrg cond = fold_build2_loc (input_location, EQ_EXPR,
7947 1.1 mrg logical_type_node, temp,
7948 1.1 mrg fold_convert (TREE_TYPE (temp),
7949 1.1 mrg null_pointer_node));
7950 1.1 mrg gfc_trans_runtime_check (true, false, cond, &argse.pre, &e->where, msg);
7951 1.1 mrg
7952 1.1 mrg free (msg);
7953 1.1 mrg }
7954 1.1 mrg end_arg_check:
7955 1.1 mrg
7956 1.1 mrg argse.data_not_needed = 1;
7957 1.1 mrg if (gfc_is_class_array_function (e))
7958 1.1 mrg {
7959 1.1 mrg /* For functions that return a class array conv_expr_descriptor is not
7960 1.1 mrg able to get the descriptor right. Therefore this special case. */
7961 1.1 mrg gfc_conv_expr_reference (&argse, e);
7962 1.1 mrg argse.expr = gfc_class_data_get (argse.expr);
7963 1.1 mrg }
7964 1.1 mrg else if (sym && sym->backend_decl)
7965 1.1 mrg {
7966 1.1 mrg gcc_assert (GFC_CLASS_TYPE_P (TREE_TYPE (sym->backend_decl)));
7967 1.1 mrg argse.expr = gfc_class_data_get (sym->backend_decl);
7968 1.1 mrg }
7969 1.1 mrg else
7970 1.1 mrg gfc_conv_expr_descriptor (&argse, actual->expr);
7971 1.1 mrg gfc_add_block_to_block (&se->pre, &argse.pre);
7972 1.1 mrg gfc_add_block_to_block (&se->post, &argse.post);
7973 1.1 mrg arg1 = argse.expr;
7974 1.1 mrg
7975 1.1 mrg actual = actual->next;
7976 1.1 mrg if (actual->expr)
7977 1.1 mrg {
7978 1.1 mrg stmtblock_t block;
7979 1.1 mrg gfc_init_block (&block);
7980 1.1 mrg gfc_init_se (&argse, NULL);
7981 1.1 mrg gfc_conv_expr_type (&argse, actual->expr,
7982 1.1 mrg gfc_array_index_type);
7983 1.1 mrg gfc_add_block_to_block (&block, &argse.pre);
7984 1.1 mrg tree tmp = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
7985 1.1 mrg argse.expr, gfc_index_one_node);
7986 1.1 mrg size = gfc_tree_array_size (&block, arg1, e, tmp);
7987 1.1 mrg
7988 1.1 mrg /* Unusually, for an intrinsic, size does not exclude
7989 1.1 mrg an optional arg2, so we must test for it. */
7990 1.1 mrg if (actual->expr->expr_type == EXPR_VARIABLE
7991 1.1 mrg && actual->expr->symtree->n.sym->attr.dummy
7992 1.1 mrg && actual->expr->symtree->n.sym->attr.optional)
7993 1.1 mrg {
7994 1.1 mrg tree cond;
7995 1.1 mrg stmtblock_t block2;
7996 1.1 mrg gfc_init_block (&block2);
7997 1.1 mrg gfc_init_se (&argse, NULL);
7998 1.1 mrg argse.want_pointer = 1;
7999 1.1 mrg argse.data_not_needed = 1;
8000 1.1 mrg gfc_conv_expr (&argse, actual->expr);
8001 1.1 mrg gfc_add_block_to_block (&se->pre, &argse.pre);
8002 1.1 mrg cond = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
8003 1.1 mrg argse.expr, null_pointer_node);
8004 1.1 mrg cond = gfc_evaluate_now (cond, &se->pre);
8005 1.1 mrg /* 'block2' contains the arg2 absent case, 'block' the arg2 present
8006 1.1 mrg case; size_var can be used in both blocks. */
8007 1.1 mrg tree size_var = gfc_create_var (TREE_TYPE (size), "size");
8008 1.1 mrg tmp = fold_build2_loc (input_location, MODIFY_EXPR,
8009 1.1 mrg TREE_TYPE (size_var), size_var, size);
8010 1.1 mrg gfc_add_expr_to_block (&block, tmp);
8011 1.1 mrg size = gfc_tree_array_size (&block2, arg1, e, NULL_TREE);
8012 1.1 mrg tmp = fold_build2_loc (input_location, MODIFY_EXPR,
8013 1.1 mrg TREE_TYPE (size_var), size_var, size);
8014 1.1 mrg gfc_add_expr_to_block (&block2, tmp);
8015 1.1 mrg tmp = build3_v (COND_EXPR, cond, gfc_finish_block (&block),
8016 1.1 mrg gfc_finish_block (&block2));
8017 1.1 mrg gfc_add_expr_to_block (&se->pre, tmp);
8018 1.1 mrg size = size_var;
8019 1.1 mrg }
8020 1.1 mrg else
8021 1.1 mrg gfc_add_block_to_block (&se->pre, &block);
8022 1.1 mrg }
8023 1.1 mrg else
8024 1.1 mrg size = gfc_tree_array_size (&se->pre, arg1, e, NULL_TREE);
8025 1.1 mrg type = gfc_typenode_for_spec (&expr->ts);
8026 1.1 mrg se->expr = convert (type, size);
8027 1.1 mrg }
8028 1.1 mrg
8029 1.1 mrg
8030 1.1 mrg /* Helper function to compute the size of a character variable,
8031 1.1 mrg excluding the terminating null characters. The result has
8032 1.1 mrg gfc_array_index_type type. */
8033 1.1 mrg
8034 1.1 mrg tree
8035 1.1 mrg size_of_string_in_bytes (int kind, tree string_length)
8036 1.1 mrg {
8037 1.1 mrg tree bytesize;
8038 1.1 mrg int i = gfc_validate_kind (BT_CHARACTER, kind, false);
8039 1.1 mrg
8040 1.1 mrg bytesize = build_int_cst (gfc_array_index_type,
8041 1.1 mrg gfc_character_kinds[i].bit_size / 8);
8042 1.1 mrg
8043 1.1 mrg return fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
8044 1.1 mrg bytesize,
8045 1.1 mrg fold_convert (gfc_array_index_type, string_length));
8046 1.1 mrg }
8047 1.1 mrg
8048 1.1 mrg
8049 1.1 mrg static void
8050 1.1 mrg gfc_conv_intrinsic_sizeof (gfc_se *se, gfc_expr *expr)
8051 1.1 mrg {
8052 1.1 mrg gfc_expr *arg;
8053 1.1 mrg gfc_se argse;
8054 1.1 mrg tree source_bytes;
8055 1.1 mrg tree tmp;
8056 1.1 mrg tree lower;
8057 1.1 mrg tree upper;
8058 1.1 mrg tree byte_size;
8059 1.1 mrg tree field;
8060 1.1 mrg int n;
8061 1.1 mrg
8062 1.1 mrg gfc_init_se (&argse, NULL);
8063 1.1 mrg arg = expr->value.function.actual->expr;
8064 1.1 mrg
8065 1.1 mrg if (arg->rank || arg->ts.type == BT_ASSUMED)
8066 1.1 mrg gfc_conv_expr_descriptor (&argse, arg);
8067 1.1 mrg else
8068 1.1 mrg gfc_conv_expr_reference (&argse, arg);
8069 1.1 mrg
8070 1.1 mrg if (arg->ts.type == BT_ASSUMED)
8071 1.1 mrg {
8072 1.1 mrg /* This only works if an array descriptor has been passed; thus, extract
8073 1.1 mrg the size from the descriptor. */
8074 1.1 mrg gcc_assert (TYPE_PRECISION (gfc_array_index_type)
8075 1.1 mrg == TYPE_PRECISION (size_type_node));
8076 1.1 mrg tmp = arg->symtree->n.sym->backend_decl;
8077 1.1 mrg tmp = DECL_LANG_SPECIFIC (tmp)
8078 1.1 mrg && GFC_DECL_SAVED_DESCRIPTOR (tmp) != NULL_TREE
8079 1.1 mrg ? GFC_DECL_SAVED_DESCRIPTOR (tmp) : tmp;
8080 1.1 mrg if (POINTER_TYPE_P (TREE_TYPE (tmp)))
8081 1.1 mrg tmp = build_fold_indirect_ref_loc (input_location, tmp);
8082 1.1 mrg
8083 1.1 mrg tmp = gfc_conv_descriptor_dtype (tmp);
8084 1.1 mrg field = gfc_advance_chain (TYPE_FIELDS (get_dtype_type_node ()),
8085 1.1 mrg GFC_DTYPE_ELEM_LEN);
8086 1.1 mrg tmp = fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (field),
8087 1.1 mrg tmp, field, NULL_TREE);
8088 1.1 mrg
8089 1.1 mrg byte_size = fold_convert (gfc_array_index_type, tmp);
8090 1.1 mrg }
8091 1.1 mrg else if (arg->ts.type == BT_CLASS)
8092 1.1 mrg {
8093 1.1 mrg /* Conv_expr_descriptor returns a component_ref to _data component of the
8094 1.1 mrg class object. The class object may be a non-pointer object, e.g.
8095 1.1 mrg located on the stack, or a memory location pointed to, e.g. a
8096 1.1 mrg parameter, i.e., an indirect_ref. */
8097 1.1 mrg if (POINTER_TYPE_P (TREE_TYPE (argse.expr))
8098 1.1 mrg && GFC_CLASS_TYPE_P (TREE_TYPE (TREE_TYPE (argse.expr))))
8099 1.1 mrg byte_size
8100 1.1 mrg = gfc_class_vtab_size_get (build_fold_indirect_ref (argse.expr));
8101 1.1 mrg else if (GFC_CLASS_TYPE_P (TREE_TYPE (argse.expr)))
8102 1.1 mrg byte_size = gfc_class_vtab_size_get (argse.expr);
8103 1.1 mrg else if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (argse.expr))
8104 1.1 mrg && TREE_CODE (argse.expr) == COMPONENT_REF)
8105 1.1 mrg byte_size = gfc_class_vtab_size_get (TREE_OPERAND (argse.expr, 0));
8106 1.1 mrg else if (arg->rank > 0
8107 1.1 mrg || (arg->rank == 0
8108 1.1 mrg && arg->ref && arg->ref->type == REF_COMPONENT))
8109 1.1 mrg /* The scalarizer added an additional temp. To get the class' vptr
8110 1.1 mrg one has to look at the original backend_decl. */
8111 1.1 mrg byte_size = gfc_class_vtab_size_get (
8112 1.1 mrg GFC_DECL_SAVED_DESCRIPTOR (arg->symtree->n.sym->backend_decl));
8113 1.1 mrg else
8114 1.1 mrg gcc_unreachable ();
8115 1.1 mrg }
8116 1.1 mrg else
8117 1.1 mrg {
8118 1.1 mrg if (arg->ts.type == BT_CHARACTER)
8119 1.1 mrg byte_size = size_of_string_in_bytes (arg->ts.kind, argse.string_length);
8120 1.1 mrg else
8121 1.1 mrg {
8122 1.1 mrg if (arg->rank == 0)
8123 1.1 mrg byte_size = TREE_TYPE (build_fold_indirect_ref_loc (input_location,
8124 1.1 mrg argse.expr));
8125 1.1 mrg else
8126 1.1 mrg byte_size = gfc_get_element_type (TREE_TYPE (argse.expr));
8127 1.1 mrg byte_size = fold_convert (gfc_array_index_type,
8128 1.1 mrg size_in_bytes (byte_size));
8129 1.1 mrg }
8130 1.1 mrg }
8131 1.1 mrg
8132 1.1 mrg if (arg->rank == 0)
8133 1.1 mrg se->expr = byte_size;
8134 1.1 mrg else
8135 1.1 mrg {
8136 1.1 mrg source_bytes = gfc_create_var (gfc_array_index_type, "bytes");
8137 1.1 mrg gfc_add_modify (&argse.pre, source_bytes, byte_size);
8138 1.1 mrg
8139 1.1 mrg if (arg->rank == -1)
8140 1.1 mrg {
8141 1.1 mrg tree cond, loop_var, exit_label;
8142 1.1 mrg stmtblock_t body;
8143 1.1 mrg
8144 1.1 mrg tmp = fold_convert (gfc_array_index_type,
8145 1.1 mrg gfc_conv_descriptor_rank (argse.expr));
8146 1.1 mrg loop_var = gfc_create_var (gfc_array_index_type, "i");
8147 1.1 mrg gfc_add_modify (&argse.pre, loop_var, gfc_index_zero_node);
8148 1.1 mrg exit_label = gfc_build_label_decl (NULL_TREE);
8149 1.1 mrg
8150 1.1 mrg /* Create loop:
8151 1.1 mrg for (;;)
8152 1.1 mrg {
8153 1.1 mrg if (i >= rank)
8154 1.1 mrg goto exit;
8155 1.1 mrg source_bytes = source_bytes * array.dim[i].extent;
8156 1.1 mrg i = i + 1;
8157 1.1 mrg }
8158 1.1 mrg exit: */
8159 1.1 mrg gfc_start_block (&body);
8160 1.1 mrg cond = fold_build2_loc (input_location, GE_EXPR, logical_type_node,
8161 1.1 mrg loop_var, tmp);
8162 1.1 mrg tmp = build1_v (GOTO_EXPR, exit_label);
8163 1.1 mrg tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node,
8164 1.1 mrg cond, tmp, build_empty_stmt (input_location));
8165 1.1 mrg gfc_add_expr_to_block (&body, tmp);
8166 1.1 mrg
8167 1.1 mrg lower = gfc_conv_descriptor_lbound_get (argse.expr, loop_var);
8168 1.1 mrg upper = gfc_conv_descriptor_ubound_get (argse.expr, loop_var);
8169 1.1 mrg tmp = gfc_conv_array_extent_dim (lower, upper, NULL);
8170 1.1 mrg tmp = fold_build2_loc (input_location, MULT_EXPR,
8171 1.1 mrg gfc_array_index_type, tmp, source_bytes);
8172 1.1 mrg gfc_add_modify (&body, source_bytes, tmp);
8173 1.1 mrg
8174 1.1 mrg tmp = fold_build2_loc (input_location, PLUS_EXPR,
8175 1.1 mrg gfc_array_index_type, loop_var,
8176 1.1 mrg gfc_index_one_node);
8177 1.1 mrg gfc_add_modify_loc (input_location, &body, loop_var, tmp);
8178 1.1 mrg
8179 1.1 mrg tmp = gfc_finish_block (&body);
8180 1.1 mrg
8181 1.1 mrg tmp = fold_build1_loc (input_location, LOOP_EXPR, void_type_node,
8182 1.1 mrg tmp);
8183 1.1 mrg gfc_add_expr_to_block (&argse.pre, tmp);
8184 1.1 mrg
8185 1.1 mrg tmp = build1_v (LABEL_EXPR, exit_label);
8186 1.1 mrg gfc_add_expr_to_block (&argse.pre, tmp);
8187 1.1 mrg }
8188 1.1 mrg else
8189 1.1 mrg {
8190 1.1 mrg /* Obtain the size of the array in bytes. */
8191 1.1 mrg for (n = 0; n < arg->rank; n++)
8192 1.1 mrg {
8193 1.1 mrg tree idx;
8194 1.1 mrg idx = gfc_rank_cst[n];
8195 1.1 mrg lower = gfc_conv_descriptor_lbound_get (argse.expr, idx);
8196 1.1 mrg upper = gfc_conv_descriptor_ubound_get (argse.expr, idx);
8197 1.1 mrg tmp = gfc_conv_array_extent_dim (lower, upper, NULL);
8198 1.1 mrg tmp = fold_build2_loc (input_location, MULT_EXPR,
8199 1.1 mrg gfc_array_index_type, tmp, source_bytes);
8200 1.1 mrg gfc_add_modify (&argse.pre, source_bytes, tmp);
8201 1.1 mrg }
8202 1.1 mrg }
8203 1.1 mrg se->expr = source_bytes;
8204 1.1 mrg }
8205 1.1 mrg
8206 1.1 mrg gfc_add_block_to_block (&se->pre, &argse.pre);
8207 1.1 mrg }
8208 1.1 mrg
8209 1.1 mrg
8210 1.1 mrg static void
8211 1.1 mrg gfc_conv_intrinsic_storage_size (gfc_se *se, gfc_expr *expr)
8212 1.1 mrg {
8213 1.1 mrg gfc_expr *arg;
8214 1.1 mrg gfc_se argse;
8215 1.1 mrg tree type, result_type, tmp;
8216 1.1 mrg
8217 1.1 mrg arg = expr->value.function.actual->expr;
8218 1.1 mrg
8219 1.1 mrg gfc_init_se (&argse, NULL);
8220 1.1 mrg result_type = gfc_get_int_type (expr->ts.kind);
8221 1.1 mrg
8222 1.1 mrg if (arg->rank == 0)
8223 1.1 mrg {
8224 1.1 mrg if (arg->ts.type == BT_CLASS)
8225 1.1 mrg {
8226 1.1 mrg gfc_add_vptr_component (arg);
8227 1.1 mrg gfc_add_size_component (arg);
8228 1.1 mrg gfc_conv_expr (&argse, arg);
8229 1.1 mrg tmp = fold_convert (result_type, argse.expr);
8230 1.1 mrg goto done;
8231 1.1 mrg }
8232 1.1 mrg
8233 1.1 mrg gfc_conv_expr_reference (&argse, arg);
8234 1.1 mrg type = TREE_TYPE (build_fold_indirect_ref_loc (input_location,
8235 1.1 mrg argse.expr));
8236 1.1 mrg }
8237 1.1 mrg else
8238 1.1 mrg {
8239 1.1 mrg argse.want_pointer = 0;
8240 1.1 mrg gfc_conv_expr_descriptor (&argse, arg);
8241 1.1 mrg if (arg->ts.type == BT_CLASS)
8242 1.1 mrg {
8243 1.1 mrg if (arg->rank > 0)
8244 1.1 mrg tmp = gfc_class_vtab_size_get (
8245 1.1 mrg GFC_DECL_SAVED_DESCRIPTOR (arg->symtree->n.sym->backend_decl));
8246 1.1 mrg else
8247 1.1 mrg tmp = gfc_class_vtab_size_get (TREE_OPERAND (argse.expr, 0));
8248 1.1 mrg tmp = fold_convert (result_type, tmp);
8249 1.1 mrg goto done;
8250 1.1 mrg }
8251 1.1 mrg type = gfc_get_element_type (TREE_TYPE (argse.expr));
8252 1.1 mrg }
8253 1.1 mrg
8254 1.1 mrg /* Obtain the argument's word length. */
8255 1.1 mrg if (arg->ts.type == BT_CHARACTER)
8256 1.1 mrg tmp = size_of_string_in_bytes (arg->ts.kind, argse.string_length);
8257 1.1 mrg else
8258 1.1 mrg tmp = size_in_bytes (type);
8259 1.1 mrg tmp = fold_convert (result_type, tmp);
8260 1.1 mrg
8261 1.1 mrg done:
8262 1.1 mrg se->expr = fold_build2_loc (input_location, MULT_EXPR, result_type, tmp,
8263 1.1 mrg build_int_cst (result_type, BITS_PER_UNIT));
8264 1.1 mrg gfc_add_block_to_block (&se->pre, &argse.pre);
8265 1.1 mrg }
8266 1.1 mrg
8267 1.1 mrg
8268 1.1 mrg /* Intrinsic string comparison functions. */
8269 1.1 mrg
8270 1.1 mrg static void
8271 1.1 mrg gfc_conv_intrinsic_strcmp (gfc_se * se, gfc_expr * expr, enum tree_code op)
8272 1.1 mrg {
8273 1.1 mrg tree args[4];
8274 1.1 mrg
8275 1.1 mrg gfc_conv_intrinsic_function_args (se, expr, args, 4);
8276 1.1 mrg
8277 1.1 mrg se->expr
8278 1.1 mrg = gfc_build_compare_string (args[0], args[1], args[2], args[3],
8279 1.1 mrg expr->value.function.actual->expr->ts.kind,
8280 1.1 mrg op);
8281 1.1 mrg se->expr = fold_build2_loc (input_location, op,
8282 1.1 mrg gfc_typenode_for_spec (&expr->ts), se->expr,
8283 1.1 mrg build_int_cst (TREE_TYPE (se->expr), 0));
8284 1.1 mrg }
8285 1.1 mrg
8286 1.1 mrg /* Generate a call to the adjustl/adjustr library function. */
8287 1.1 mrg static void
8288 1.1 mrg gfc_conv_intrinsic_adjust (gfc_se * se, gfc_expr * expr, tree fndecl)
8289 1.1 mrg {
8290 1.1 mrg tree args[3];
8291 1.1 mrg tree len;
8292 1.1 mrg tree type;
8293 1.1 mrg tree var;
8294 1.1 mrg tree tmp;
8295 1.1 mrg
8296 1.1 mrg gfc_conv_intrinsic_function_args (se, expr, &args[1], 2);
8297 1.1 mrg len = args[1];
8298 1.1 mrg
8299 1.1 mrg type = TREE_TYPE (args[2]);
8300 1.1 mrg var = gfc_conv_string_tmp (se, type, len);
8301 1.1 mrg args[0] = var;
8302 1.1 mrg
8303 1.1 mrg tmp = build_call_expr_loc (input_location,
8304 1.1 mrg fndecl, 3, args[0], args[1], args[2]);
8305 1.1 mrg gfc_add_expr_to_block (&se->pre, tmp);
8306 1.1 mrg se->expr = var;
8307 1.1 mrg se->string_length = len;
8308 1.1 mrg }
8309 1.1 mrg
8310 1.1 mrg
8311 1.1 mrg /* Generate code for the TRANSFER intrinsic:
8312 1.1 mrg For scalar results:
8313 1.1 mrg DEST = TRANSFER (SOURCE, MOLD)
8314 1.1 mrg where:
8315 1.1 mrg typeof<DEST> = typeof<MOLD>
8316 1.1 mrg and:
8317 1.1 mrg MOLD is scalar.
8318 1.1 mrg
8319 1.1 mrg For array results:
8320 1.1 mrg DEST(1:N) = TRANSFER (SOURCE, MOLD[, SIZE])
8321 1.1 mrg where:
8322 1.1 mrg typeof<DEST> = typeof<MOLD>
8323 1.1 mrg and:
8324 1.1 mrg N = min (sizeof (SOURCE(:)), sizeof (DEST(:)),
8325 1.1 mrg sizeof (DEST(0) * SIZE). */
8326 1.1 mrg static void
8327 1.1 mrg gfc_conv_intrinsic_transfer (gfc_se * se, gfc_expr * expr)
8328 1.1 mrg {
8329 1.1 mrg tree tmp;
8330 1.1 mrg tree tmpdecl;
8331 1.1 mrg tree ptr;
8332 1.1 mrg tree extent;
8333 1.1 mrg tree source;
8334 1.1 mrg tree source_type;
8335 1.1 mrg tree source_bytes;
8336 1.1 mrg tree mold_type;
8337 1.1 mrg tree dest_word_len;
8338 1.1 mrg tree size_words;
8339 1.1 mrg tree size_bytes;
8340 1.1 mrg tree upper;
8341 1.1 mrg tree lower;
8342 1.1 mrg tree stmt;
8343 1.1 mrg tree class_ref = NULL_TREE;
8344 1.1 mrg gfc_actual_arglist *arg;
8345 1.1 mrg gfc_se argse;
8346 1.1 mrg gfc_array_info *info;
8347 1.1 mrg stmtblock_t block;
8348 1.1 mrg int n;
8349 1.1 mrg bool scalar_mold;
8350 1.1 mrg gfc_expr *source_expr, *mold_expr, *class_expr;
8351 1.1 mrg
8352 1.1 mrg info = NULL;
8353 1.1 mrg if (se->loop)
8354 1.1 mrg info = &se->ss->info->data.array;
8355 1.1 mrg
8356 1.1 mrg /* Convert SOURCE. The output from this stage is:-
8357 1.1 mrg source_bytes = length of the source in bytes
8358 1.1 mrg source = pointer to the source data. */
8359 1.1 mrg arg = expr->value.function.actual;
8360 1.1 mrg source_expr = arg->expr;
8361 1.1 mrg
8362 1.1 mrg /* Ensure double transfer through LOGICAL preserves all
8363 1.1 mrg the needed bits. */
8364 1.1 mrg if (arg->expr->expr_type == EXPR_FUNCTION
8365 1.1 mrg && arg->expr->value.function.esym == NULL
8366 1.1 mrg && arg->expr->value.function.isym != NULL
8367 1.1 mrg && arg->expr->value.function.isym->id == GFC_ISYM_TRANSFER
8368 1.1 mrg && arg->expr->ts.type == BT_LOGICAL
8369 1.1 mrg && expr->ts.type != arg->expr->ts.type)
8370 1.1 mrg arg->expr->value.function.name = "__transfer_in_transfer";
8371 1.1 mrg
8372 1.1 mrg gfc_init_se (&argse, NULL);
8373 1.1 mrg
8374 1.1 mrg source_bytes = gfc_create_var (gfc_array_index_type, NULL);
8375 1.1 mrg
8376 1.1 mrg /* Obtain the pointer to source and the length of source in bytes. */
8377 1.1 mrg if (arg->expr->rank == 0)
8378 1.1 mrg {
8379 1.1 mrg gfc_conv_expr_reference (&argse, arg->expr);
8380 1.1 mrg if (arg->expr->ts.type == BT_CLASS)
8381 1.1 mrg {
8382 1.1 mrg tmp = build_fold_indirect_ref_loc (input_location, argse.expr);
8383 1.1 mrg if (GFC_CLASS_TYPE_P (TREE_TYPE (tmp)))
8384 1.1 mrg source = gfc_class_data_get (tmp);
8385 1.1 mrg else
8386 1.1 mrg {
8387 1.1 mrg /* Array elements are evaluated as a reference to the data.
8388 1.1 mrg To obtain the vptr for the element size, the argument
8389 1.1 mrg expression must be stripped to the class reference and
8390 1.1 mrg re-evaluated. The pre and post blocks are not needed. */
8391 1.1 mrg gcc_assert (arg->expr->expr_type == EXPR_VARIABLE);
8392 1.1 mrg source = argse.expr;
8393 1.1 mrg class_expr = gfc_find_and_cut_at_last_class_ref (arg->expr);
8394 1.1 mrg gfc_init_se (&argse, NULL);
8395 1.1 mrg gfc_conv_expr (&argse, class_expr);
8396 1.1 mrg class_ref = argse.expr;
8397 1.1 mrg }
8398 1.1 mrg }
8399 1.1 mrg else
8400 1.1 mrg source = argse.expr;
8401 1.1 mrg
8402 1.1 mrg /* Obtain the source word length. */
8403 1.1 mrg switch (arg->expr->ts.type)
8404 1.1 mrg {
8405 1.1 mrg case BT_CHARACTER:
8406 1.1 mrg tmp = size_of_string_in_bytes (arg->expr->ts.kind,
8407 1.1 mrg argse.string_length);
8408 1.1 mrg break;
8409 1.1 mrg case BT_CLASS:
8410 1.1 mrg if (class_ref != NULL_TREE)
8411 1.1 mrg tmp = gfc_class_vtab_size_get (class_ref);
8412 1.1 mrg else
8413 1.1 mrg tmp = gfc_class_vtab_size_get (argse.expr);
8414 1.1 mrg break;
8415 1.1 mrg default:
8416 1.1 mrg source_type = TREE_TYPE (build_fold_indirect_ref_loc (input_location,
8417 1.1 mrg source));
8418 1.1 mrg tmp = fold_convert (gfc_array_index_type,
8419 1.1 mrg size_in_bytes (source_type));
8420 1.1 mrg break;
8421 1.1 mrg }
8422 1.1 mrg }
8423 1.1 mrg else
8424 1.1 mrg {
8425 1.1 mrg argse.want_pointer = 0;
8426 1.1 mrg gfc_conv_expr_descriptor (&argse, arg->expr);
8427 1.1 mrg source = gfc_conv_descriptor_data_get (argse.expr);
8428 1.1 mrg source_type = gfc_get_element_type (TREE_TYPE (argse.expr));
8429 1.1 mrg
8430 1.1 mrg /* Repack the source if not simply contiguous. */
8431 1.1 mrg if (!gfc_is_simply_contiguous (arg->expr, false, true))
8432 1.1 mrg {
8433 1.1 mrg tmp = gfc_build_addr_expr (NULL_TREE, argse.expr);
8434 1.1 mrg
8435 1.1 mrg if (warn_array_temporaries)
8436 1.1 mrg gfc_warning (OPT_Warray_temporaries,
8437 1.1 mrg "Creating array temporary at %L", &expr->where);
8438 1.1 mrg
8439 1.1 mrg source = build_call_expr_loc (input_location,
8440 1.1 mrg gfor_fndecl_in_pack, 1, tmp);
8441 1.1 mrg source = gfc_evaluate_now (source, &argse.pre);
8442 1.1 mrg
8443 1.1 mrg /* Free the temporary. */
8444 1.1 mrg gfc_start_block (&block);
8445 1.1 mrg tmp = gfc_call_free (source);
8446 1.1 mrg gfc_add_expr_to_block (&block, tmp);
8447 1.1 mrg stmt = gfc_finish_block (&block);
8448 1.1 mrg
8449 1.1 mrg /* Clean up if it was repacked. */
8450 1.1 mrg gfc_init_block (&block);
8451 1.1 mrg tmp = gfc_conv_array_data (argse.expr);
8452 1.1 mrg tmp = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
8453 1.1 mrg source, tmp);
8454 1.1 mrg tmp = build3_v (COND_EXPR, tmp, stmt,
8455 1.1 mrg build_empty_stmt (input_location));
8456 1.1 mrg gfc_add_expr_to_block (&block, tmp);
8457 1.1 mrg gfc_add_block_to_block (&block, &se->post);
8458 1.1 mrg gfc_init_block (&se->post);
8459 1.1 mrg gfc_add_block_to_block (&se->post, &block);
8460 1.1 mrg }
8461 1.1 mrg
8462 1.1 mrg /* Obtain the source word length. */
8463 1.1 mrg if (arg->expr->ts.type == BT_CHARACTER)
8464 1.1 mrg tmp = size_of_string_in_bytes (arg->expr->ts.kind,
8465 1.1 mrg argse.string_length);
8466 1.1 mrg else
8467 1.1 mrg tmp = fold_convert (gfc_array_index_type,
8468 1.1 mrg size_in_bytes (source_type));
8469 1.1 mrg
8470 1.1 mrg /* Obtain the size of the array in bytes. */
8471 1.1 mrg extent = gfc_create_var (gfc_array_index_type, NULL);
8472 1.1 mrg for (n = 0; n < arg->expr->rank; n++)
8473 1.1 mrg {
8474 1.1 mrg tree idx;
8475 1.1 mrg idx = gfc_rank_cst[n];
8476 1.1 mrg gfc_add_modify (&argse.pre, source_bytes, tmp);
8477 1.1 mrg lower = gfc_conv_descriptor_lbound_get (argse.expr, idx);
8478 1.1 mrg upper = gfc_conv_descriptor_ubound_get (argse.expr, idx);
8479 1.1 mrg tmp = fold_build2_loc (input_location, MINUS_EXPR,
8480 1.1 mrg gfc_array_index_type, upper, lower);
8481 1.1 mrg gfc_add_modify (&argse.pre, extent, tmp);
8482 1.1 mrg tmp = fold_build2_loc (input_location, PLUS_EXPR,
8483 1.1 mrg gfc_array_index_type, extent,
8484 1.1 mrg gfc_index_one_node);
8485 1.1 mrg tmp = fold_build2_loc (input_location, MULT_EXPR,
8486 1.1 mrg gfc_array_index_type, tmp, source_bytes);
8487 1.1 mrg }
8488 1.1 mrg }
8489 1.1 mrg
8490 1.1 mrg gfc_add_modify (&argse.pre, source_bytes, tmp);
8491 1.1 mrg gfc_add_block_to_block (&se->pre, &argse.pre);
8492 1.1 mrg gfc_add_block_to_block (&se->post, &argse.post);
8493 1.1 mrg
8494 1.1 mrg /* Now convert MOLD. The outputs are:
8495 1.1 mrg mold_type = the TREE type of MOLD
8496 1.1 mrg dest_word_len = destination word length in bytes. */
8497 1.1 mrg arg = arg->next;
8498 1.1 mrg mold_expr = arg->expr;
8499 1.1 mrg
8500 1.1 mrg gfc_init_se (&argse, NULL);
8501 1.1 mrg
8502 1.1 mrg scalar_mold = arg->expr->rank == 0;
8503 1.1 mrg
8504 1.1 mrg if (arg->expr->rank == 0)
8505 1.1 mrg {
8506 1.1 mrg gfc_conv_expr_reference (&argse, arg->expr);
8507 1.1 mrg mold_type = TREE_TYPE (build_fold_indirect_ref_loc (input_location,
8508 1.1 mrg argse.expr));
8509 1.1 mrg }
8510 1.1 mrg else
8511 1.1 mrg {
8512 1.1 mrg gfc_init_se (&argse, NULL);
8513 1.1 mrg argse.want_pointer = 0;
8514 1.1 mrg gfc_conv_expr_descriptor (&argse, arg->expr);
8515 1.1 mrg mold_type = gfc_get_element_type (TREE_TYPE (argse.expr));
8516 1.1 mrg }
8517 1.1 mrg
8518 1.1 mrg gfc_add_block_to_block (&se->pre, &argse.pre);
8519 1.1 mrg gfc_add_block_to_block (&se->post, &argse.post);
8520 1.1 mrg
8521 1.1 mrg if (strcmp (expr->value.function.name, "__transfer_in_transfer") == 0)
8522 1.1 mrg {
8523 1.1 mrg /* If this TRANSFER is nested in another TRANSFER, use a type
8524 1.1 mrg that preserves all bits. */
8525 1.1 mrg if (arg->expr->ts.type == BT_LOGICAL)
8526 1.1 mrg mold_type = gfc_get_int_type (arg->expr->ts.kind);
8527 1.1 mrg }
8528 1.1 mrg
8529 1.1 mrg /* Obtain the destination word length. */
8530 1.1 mrg switch (arg->expr->ts.type)
8531 1.1 mrg {
8532 1.1 mrg case BT_CHARACTER:
8533 1.1 mrg tmp = size_of_string_in_bytes (arg->expr->ts.kind, argse.string_length);
8534 1.1 mrg mold_type = gfc_get_character_type_len (arg->expr->ts.kind,
8535 1.1 mrg argse.string_length);
8536 1.1 mrg break;
8537 1.1 mrg case BT_CLASS:
8538 1.1 mrg tmp = gfc_class_vtab_size_get (argse.expr);
8539 1.1 mrg break;
8540 1.1 mrg default:
8541 1.1 mrg tmp = fold_convert (gfc_array_index_type, size_in_bytes (mold_type));
8542 1.1 mrg break;
8543 1.1 mrg }
8544 1.1 mrg dest_word_len = gfc_create_var (gfc_array_index_type, NULL);
8545 1.1 mrg gfc_add_modify (&se->pre, dest_word_len, tmp);
8546 1.1 mrg
8547 1.1 mrg /* Finally convert SIZE, if it is present. */
8548 1.1 mrg arg = arg->next;
8549 1.1 mrg size_words = gfc_create_var (gfc_array_index_type, NULL);
8550 1.1 mrg
8551 1.1 mrg if (arg->expr)
8552 1.1 mrg {
8553 1.1 mrg gfc_init_se (&argse, NULL);
8554 1.1 mrg gfc_conv_expr_reference (&argse, arg->expr);
8555 1.1 mrg tmp = convert (gfc_array_index_type,
8556 1.1 mrg build_fold_indirect_ref_loc (input_location,
8557 1.1 mrg argse.expr));
8558 1.1 mrg gfc_add_block_to_block (&se->pre, &argse.pre);
8559 1.1 mrg gfc_add_block_to_block (&se->post, &argse.post);
8560 1.1 mrg }
8561 1.1 mrg else
8562 1.1 mrg tmp = NULL_TREE;
8563 1.1 mrg
8564 1.1 mrg /* Separate array and scalar results. */
8565 1.1 mrg if (scalar_mold && tmp == NULL_TREE)
8566 1.1 mrg goto scalar_transfer;
8567 1.1 mrg
8568 1.1 mrg size_bytes = gfc_create_var (gfc_array_index_type, NULL);
8569 1.1 mrg if (tmp != NULL_TREE)
8570 1.1 mrg tmp = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
8571 1.1 mrg tmp, dest_word_len);
8572 1.1 mrg else
8573 1.1 mrg tmp = source_bytes;
8574 1.1 mrg
8575 1.1 mrg gfc_add_modify (&se->pre, size_bytes, tmp);
8576 1.1 mrg gfc_add_modify (&se->pre, size_words,
8577 1.1 mrg fold_build2_loc (input_location, CEIL_DIV_EXPR,
8578 1.1 mrg gfc_array_index_type,
8579 1.1 mrg size_bytes, dest_word_len));
8580 1.1 mrg
8581 1.1 mrg /* Evaluate the bounds of the result. If the loop range exists, we have
8582 1.1 mrg to check if it is too large. If so, we modify loop->to be consistent
8583 1.1 mrg with min(size, size(source)). Otherwise, size is made consistent with
8584 1.1 mrg the loop range, so that the right number of bytes is transferred.*/
8585 1.1 mrg n = se->loop->order[0];
8586 1.1 mrg if (se->loop->to[n] != NULL_TREE)
8587 1.1 mrg {
8588 1.1 mrg tmp = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
8589 1.1 mrg se->loop->to[n], se->loop->from[n]);
8590 1.1 mrg tmp = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
8591 1.1 mrg tmp, gfc_index_one_node);
8592 1.1 mrg tmp = fold_build2_loc (input_location, MIN_EXPR, gfc_array_index_type,
8593 1.1 mrg tmp, size_words);
8594 1.1 mrg gfc_add_modify (&se->pre, size_words, tmp);
8595 1.1 mrg gfc_add_modify (&se->pre, size_bytes,
8596 1.1 mrg fold_build2_loc (input_location, MULT_EXPR,
8597 1.1 mrg gfc_array_index_type,
8598 1.1 mrg size_words, dest_word_len));
8599 1.1 mrg upper = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
8600 1.1 mrg size_words, se->loop->from[n]);
8601 1.1 mrg upper = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
8602 1.1 mrg upper, gfc_index_one_node);
8603 1.1 mrg }
8604 1.1 mrg else
8605 1.1 mrg {
8606 1.1 mrg upper = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
8607 1.1 mrg size_words, gfc_index_one_node);
8608 1.1 mrg se->loop->from[n] = gfc_index_zero_node;
8609 1.1 mrg }
8610 1.1 mrg
8611 1.1 mrg se->loop->to[n] = upper;
8612 1.1 mrg
8613 1.1 mrg /* Build a destination descriptor, using the pointer, source, as the
8614 1.1 mrg data field. */
8615 1.1 mrg gfc_trans_create_temp_array (&se->pre, &se->post, se->ss, mold_type,
8616 1.1 mrg NULL_TREE, false, true, false, &expr->where);
8617 1.1 mrg
8618 1.1 mrg /* Cast the pointer to the result. */
8619 1.1 mrg tmp = gfc_conv_descriptor_data_get (info->descriptor);
8620 1.1 mrg tmp = fold_convert (pvoid_type_node, tmp);
8621 1.1 mrg
8622 1.1 mrg /* Use memcpy to do the transfer. */
8623 1.1 mrg tmp
8624 1.1 mrg = build_call_expr_loc (input_location,
8625 1.1 mrg builtin_decl_explicit (BUILT_IN_MEMCPY), 3, tmp,
8626 1.1 mrg fold_convert (pvoid_type_node, source),
8627 1.1 mrg fold_convert (size_type_node,
8628 1.1 mrg fold_build2_loc (input_location,
8629 1.1 mrg MIN_EXPR,
8630 1.1 mrg gfc_array_index_type,
8631 1.1 mrg size_bytes,
8632 1.1 mrg source_bytes)));
8633 1.1 mrg gfc_add_expr_to_block (&se->pre, tmp);
8634 1.1 mrg
8635 1.1 mrg se->expr = info->descriptor;
8636 1.1 mrg if (expr->ts.type == BT_CHARACTER)
8637 1.1 mrg {
8638 1.1 mrg tmp = fold_convert (gfc_charlen_type_node,
8639 1.1 mrg TYPE_SIZE_UNIT (gfc_get_char_type (expr->ts.kind)));
8640 1.1 mrg se->string_length = fold_build2_loc (input_location, TRUNC_DIV_EXPR,
8641 1.1 mrg gfc_charlen_type_node,
8642 1.1 mrg dest_word_len, tmp);
8643 1.1 mrg }
8644 1.1 mrg
8645 1.1 mrg return;
8646 1.1 mrg
8647 1.1 mrg /* Deal with scalar results. */
8648 1.1 mrg scalar_transfer:
8649 1.1 mrg extent = fold_build2_loc (input_location, MIN_EXPR, gfc_array_index_type,
8650 1.1 mrg dest_word_len, source_bytes);
8651 1.1 mrg extent = fold_build2_loc (input_location, MAX_EXPR, gfc_array_index_type,
8652 1.1 mrg extent, gfc_index_zero_node);
8653 1.1 mrg
8654 1.1 mrg if (expr->ts.type == BT_CHARACTER)
8655 1.1 mrg {
8656 1.1 mrg tree direct, indirect, free;
8657 1.1 mrg
8658 1.1 mrg ptr = convert (gfc_get_pchar_type (expr->ts.kind), source);
8659 1.1 mrg tmpdecl = gfc_create_var (gfc_get_pchar_type (expr->ts.kind),
8660 1.1 mrg "transfer");
8661 1.1 mrg
8662 1.1 mrg /* If source is longer than the destination, use a pointer to
8663 1.1 mrg the source directly. */
8664 1.1 mrg gfc_init_block (&block);
8665 1.1 mrg gfc_add_modify (&block, tmpdecl, ptr);
8666 1.1 mrg direct = gfc_finish_block (&block);
8667 1.1 mrg
8668 1.1 mrg /* Otherwise, allocate a string with the length of the destination
8669 1.1 mrg and copy the source into it. */
8670 1.1 mrg gfc_init_block (&block);
8671 1.1 mrg tmp = gfc_get_pchar_type (expr->ts.kind);
8672 1.1 mrg tmp = gfc_call_malloc (&block, tmp, dest_word_len);
8673 1.1 mrg gfc_add_modify (&block, tmpdecl,
8674 1.1 mrg fold_convert (TREE_TYPE (ptr), tmp));
8675 1.1 mrg tmp = build_call_expr_loc (input_location,
8676 1.1 mrg builtin_decl_explicit (BUILT_IN_MEMCPY), 3,
8677 1.1 mrg fold_convert (pvoid_type_node, tmpdecl),
8678 1.1 mrg fold_convert (pvoid_type_node, ptr),
8679 1.1 mrg fold_convert (size_type_node, extent));
8680 1.1 mrg gfc_add_expr_to_block (&block, tmp);
8681 1.1 mrg indirect = gfc_finish_block (&block);
8682 1.1 mrg
8683 1.1 mrg /* Wrap it up with the condition. */
8684 1.1 mrg tmp = fold_build2_loc (input_location, LE_EXPR, logical_type_node,
8685 1.1 mrg dest_word_len, source_bytes);
8686 1.1 mrg tmp = build3_v (COND_EXPR, tmp, direct, indirect);
8687 1.1 mrg gfc_add_expr_to_block (&se->pre, tmp);
8688 1.1 mrg
8689 1.1 mrg /* Free the temporary string, if necessary. */
8690 1.1 mrg free = gfc_call_free (tmpdecl);
8691 1.1 mrg tmp = fold_build2_loc (input_location, GT_EXPR, logical_type_node,
8692 1.1 mrg dest_word_len, source_bytes);
8693 1.1 mrg tmp = build3_v (COND_EXPR, tmp, free, build_empty_stmt (input_location));
8694 1.1 mrg gfc_add_expr_to_block (&se->post, tmp);
8695 1.1 mrg
8696 1.1 mrg se->expr = tmpdecl;
8697 1.1 mrg tmp = fold_convert (gfc_charlen_type_node,
8698 1.1 mrg TYPE_SIZE_UNIT (gfc_get_char_type (expr->ts.kind)));
8699 1.1 mrg se->string_length = fold_build2_loc (input_location, TRUNC_DIV_EXPR,
8700 1.1 mrg gfc_charlen_type_node,
8701 1.1 mrg dest_word_len, tmp);
8702 1.1 mrg }
8703 1.1 mrg else
8704 1.1 mrg {
8705 1.1 mrg tmpdecl = gfc_create_var (mold_type, "transfer");
8706 1.1 mrg
8707 1.1 mrg ptr = convert (build_pointer_type (mold_type), source);
8708 1.1 mrg
8709 1.1 mrg /* For CLASS results, allocate the needed memory first. */
8710 1.1 mrg if (mold_expr->ts.type == BT_CLASS)
8711 1.1 mrg {
8712 1.1 mrg tree cdata;
8713 1.1 mrg cdata = gfc_class_data_get (tmpdecl);
8714 1.1 mrg tmp = gfc_call_malloc (&se->pre, TREE_TYPE (cdata), dest_word_len);
8715 1.1 mrg gfc_add_modify (&se->pre, cdata, tmp);
8716 1.1 mrg }
8717 1.1 mrg
8718 1.1 mrg /* Use memcpy to do the transfer. */
8719 1.1 mrg if (mold_expr->ts.type == BT_CLASS)
8720 1.1 mrg tmp = gfc_class_data_get (tmpdecl);
8721 1.1 mrg else
8722 1.1 mrg tmp = gfc_build_addr_expr (NULL_TREE, tmpdecl);
8723 1.1 mrg
8724 1.1 mrg tmp = build_call_expr_loc (input_location,
8725 1.1 mrg builtin_decl_explicit (BUILT_IN_MEMCPY), 3,
8726 1.1 mrg fold_convert (pvoid_type_node, tmp),
8727 1.1 mrg fold_convert (pvoid_type_node, ptr),
8728 1.1 mrg fold_convert (size_type_node, extent));
8729 1.1 mrg gfc_add_expr_to_block (&se->pre, tmp);
8730 1.1 mrg
8731 1.1 mrg /* For CLASS results, set the _vptr. */
8732 1.1 mrg if (mold_expr->ts.type == BT_CLASS)
8733 1.1 mrg {
8734 1.1 mrg tree vptr;
8735 1.1 mrg gfc_symbol *vtab;
8736 1.1 mrg vptr = gfc_class_vptr_get (tmpdecl);
8737 1.1 mrg vtab = gfc_find_derived_vtab (source_expr->ts.u.derived);
8738 1.1 mrg gcc_assert (vtab);
8739 1.1 mrg tmp = gfc_build_addr_expr (NULL_TREE, gfc_get_symbol_decl (vtab));
8740 1.1 mrg gfc_add_modify (&se->pre, vptr, fold_convert (TREE_TYPE (vptr), tmp));
8741 1.1 mrg }
8742 1.1 mrg
8743 1.1 mrg se->expr = tmpdecl;
8744 1.1 mrg }
8745 1.1 mrg }
8746 1.1 mrg
8747 1.1 mrg
8748 1.1 mrg /* Generate a call to caf_is_present. */
8749 1.1 mrg
8750 1.1 mrg static tree
8751 1.1 mrg trans_caf_is_present (gfc_se *se, gfc_expr *expr)
8752 1.1 mrg {
8753 1.1 mrg tree caf_reference, caf_decl, token, image_index;
8754 1.1 mrg
8755 1.1 mrg /* Compile the reference chain. */
8756 1.1 mrg caf_reference = conv_expr_ref_to_caf_ref (&se->pre, expr);
8757 1.1 mrg gcc_assert (caf_reference != NULL_TREE);
8758 1.1 mrg
8759 1.1 mrg caf_decl = gfc_get_tree_for_caf_expr (expr);
8760 1.1 mrg if (TREE_CODE (TREE_TYPE (caf_decl)) == REFERENCE_TYPE)
8761 1.1 mrg caf_decl = build_fold_indirect_ref_loc (input_location, caf_decl);
8762 1.1 mrg image_index = gfc_caf_get_image_index (&se->pre, expr, caf_decl);
8763 1.1 mrg gfc_get_caf_token_offset (se, &token, NULL, caf_decl, NULL,
8764 1.1 mrg expr);
8765 1.1 mrg
8766 1.1 mrg return build_call_expr_loc (input_location, gfor_fndecl_caf_is_present,
8767 1.1 mrg 3, token, image_index, caf_reference);
8768 1.1 mrg }
8769 1.1 mrg
8770 1.1 mrg
8771 1.1 mrg /* Test whether this ref-chain refs this image only. */
8772 1.1 mrg
8773 1.1 mrg static bool
8774 1.1 mrg caf_this_image_ref (gfc_ref *ref)
8775 1.1 mrg {
8776 1.1 mrg for ( ; ref; ref = ref->next)
8777 1.1 mrg if (ref->type == REF_ARRAY && ref->u.ar.codimen)
8778 1.1 mrg return ref->u.ar.dimen_type[ref->u.ar.dimen] == DIMEN_THIS_IMAGE;
8779 1.1 mrg
8780 1.1 mrg return false;
8781 1.1 mrg }
8782 1.1 mrg
8783 1.1 mrg
8784 1.1 mrg /* Generate code for the ALLOCATED intrinsic.
8785 1.1 mrg Generate inline code that directly check the address of the argument. */
8786 1.1 mrg
8787 1.1 mrg static void
8788 1.1 mrg gfc_conv_allocated (gfc_se *se, gfc_expr *expr)
8789 1.1 mrg {
8790 1.1 mrg gfc_se arg1se;
8791 1.1 mrg tree tmp;
8792 1.1 mrg bool coindexed_caf_comp = false;
8793 1.1 mrg gfc_expr *e = expr->value.function.actual->expr;
8794 1.1 mrg
8795 1.1 mrg gfc_init_se (&arg1se, NULL);
8796 1.1 mrg if (e->ts.type == BT_CLASS)
8797 1.1 mrg {
8798 1.1 mrg /* Make sure that class array expressions have both a _data
8799 1.1 mrg component reference and an array reference.... */
8800 1.1 mrg if (CLASS_DATA (e)->attr.dimension)
8801 1.1 mrg gfc_add_class_array_ref (e);
8802 1.1 mrg /* .... whilst scalars only need the _data component. */
8803 1.1 mrg else
8804 1.1 mrg gfc_add_data_component (e);
8805 1.1 mrg }
8806 1.1 mrg
8807 1.1 mrg /* When 'e' references an allocatable component in a coarray, then call
8808 1.1 mrg the caf-library function caf_is_present (). */
8809 1.1 mrg if (flag_coarray == GFC_FCOARRAY_LIB && e->expr_type == EXPR_FUNCTION
8810 1.1 mrg && e->value.function.isym
8811 1.1 mrg && e->value.function.isym->id == GFC_ISYM_CAF_GET)
8812 1.1 mrg {
8813 1.1 mrg e = e->value.function.actual->expr;
8814 1.1 mrg if (gfc_expr_attr (e).codimension)
8815 1.1 mrg {
8816 1.1 mrg /* Last partref is the coindexed coarray. As coarrays are collectively
8817 1.1 mrg (de)allocated, the allocation status must be the same as the one of
8818 1.1 mrg the local allocation. Convert to local access. */
8819 1.1 mrg for (gfc_ref *ref = e->ref; ref; ref = ref->next)
8820 1.1 mrg if (ref->type == REF_ARRAY && ref->u.ar.codimen)
8821 1.1 mrg {
8822 1.1 mrg for (int i = ref->u.ar.dimen;
8823 1.1 mrg i < ref->u.ar.dimen + ref->u.ar.codimen; ++i)
8824 1.1 mrg ref->u.ar.dimen_type[i] = DIMEN_THIS_IMAGE;
8825 1.1 mrg break;
8826 1.1 mrg }
8827 1.1 mrg }
8828 1.1 mrg else if (!caf_this_image_ref (e->ref))
8829 1.1 mrg coindexed_caf_comp = true;
8830 1.1 mrg }
8831 1.1 mrg if (coindexed_caf_comp)
8832 1.1 mrg tmp = trans_caf_is_present (se, e);
8833 1.1 mrg else
8834 1.1 mrg {
8835 1.1 mrg if (e->rank == 0)
8836 1.1 mrg {
8837 1.1 mrg /* Allocatable scalar. */
8838 1.1 mrg arg1se.want_pointer = 1;
8839 1.1 mrg gfc_conv_expr (&arg1se, e);
8840 1.1 mrg tmp = arg1se.expr;
8841 1.1 mrg }
8842 1.1 mrg else
8843 1.1 mrg {
8844 1.1 mrg /* Allocatable array. */
8845 1.1 mrg arg1se.descriptor_only = 1;
8846 1.1 mrg gfc_conv_expr_descriptor (&arg1se, e);
8847 1.1 mrg tmp = gfc_conv_descriptor_data_get (arg1se.expr);
8848 1.1 mrg }
8849 1.1 mrg
8850 1.1 mrg tmp = fold_build2_loc (input_location, NE_EXPR, logical_type_node, tmp,
8851 1.1 mrg fold_convert (TREE_TYPE (tmp), null_pointer_node));
8852 1.1 mrg }
8853 1.1 mrg
8854 1.1 mrg /* Components of pointer array references sometimes come back with a pre block. */
8855 1.1 mrg if (arg1se.pre.head)
8856 1.1 mrg gfc_add_block_to_block (&se->pre, &arg1se.pre);
8857 1.1 mrg
8858 1.1 mrg se->expr = convert (gfc_typenode_for_spec (&expr->ts), tmp);
8859 1.1 mrg }
8860 1.1 mrg
8861 1.1 mrg
8862 1.1 mrg /* Generate code for the ASSOCIATED intrinsic.
8863 1.1 mrg If both POINTER and TARGET are arrays, generate a call to library function
8864 1.1 mrg _gfor_associated, and pass descriptors of POINTER and TARGET to it.
8865 1.1 mrg In other cases, generate inline code that directly compare the address of
8866 1.1 mrg POINTER with the address of TARGET. */
8867 1.1 mrg
8868 1.1 mrg static void
8869 1.1 mrg gfc_conv_associated (gfc_se *se, gfc_expr *expr)
8870 1.1 mrg {
8871 1.1 mrg gfc_actual_arglist *arg1;
8872 1.1 mrg gfc_actual_arglist *arg2;
8873 1.1 mrg gfc_se arg1se;
8874 1.1 mrg gfc_se arg2se;
8875 1.1 mrg tree tmp2;
8876 1.1 mrg tree tmp;
8877 1.1 mrg tree nonzero_arraylen = NULL_TREE;
8878 1.1 mrg gfc_ss *ss;
8879 1.1 mrg bool scalar;
8880 1.1 mrg
8881 1.1 mrg gfc_init_se (&arg1se, NULL);
8882 1.1 mrg gfc_init_se (&arg2se, NULL);
8883 1.1 mrg arg1 = expr->value.function.actual;
8884 1.1 mrg arg2 = arg1->next;
8885 1.1 mrg
8886 1.1 mrg /* Check whether the expression is a scalar or not; we cannot use
8887 1.1 mrg arg1->expr->rank as it can be nonzero for proc pointers. */
8888 1.1 mrg ss = gfc_walk_expr (arg1->expr);
8889 1.1 mrg scalar = ss == gfc_ss_terminator;
8890 1.1 mrg if (!scalar)
8891 1.1 mrg gfc_free_ss_chain (ss);
8892 1.1 mrg
8893 1.1 mrg if (!arg2->expr)
8894 1.1 mrg {
8895 1.1 mrg /* No optional target. */
8896 1.1 mrg if (scalar)
8897 1.1 mrg {
8898 1.1 mrg /* A pointer to a scalar. */
8899 1.1 mrg arg1se.want_pointer = 1;
8900 1.1 mrg gfc_conv_expr (&arg1se, arg1->expr);
8901 1.1 mrg if (arg1->expr->symtree->n.sym->attr.proc_pointer
8902 1.1 mrg && arg1->expr->symtree->n.sym->attr.dummy)
8903 1.1 mrg arg1se.expr = build_fold_indirect_ref_loc (input_location,
8904 1.1 mrg arg1se.expr);
8905 1.1 mrg if (arg1->expr->ts.type == BT_CLASS)
8906 1.1 mrg {
8907 1.1 mrg tmp2 = gfc_class_data_get (arg1se.expr);
8908 1.1 mrg if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (tmp2)))
8909 1.1 mrg tmp2 = gfc_conv_descriptor_data_get (tmp2);
8910 1.1 mrg }
8911 1.1 mrg else
8912 1.1 mrg tmp2 = arg1se.expr;
8913 1.1 mrg }
8914 1.1 mrg else
8915 1.1 mrg {
8916 1.1 mrg /* A pointer to an array. */
8917 1.1 mrg gfc_conv_expr_descriptor (&arg1se, arg1->expr);
8918 1.1 mrg tmp2 = gfc_conv_descriptor_data_get (arg1se.expr);
8919 1.1 mrg }
8920 1.1 mrg gfc_add_block_to_block (&se->pre, &arg1se.pre);
8921 1.1 mrg gfc_add_block_to_block (&se->post, &arg1se.post);
8922 1.1 mrg tmp = fold_build2_loc (input_location, NE_EXPR, logical_type_node, tmp2,
8923 1.1 mrg fold_convert (TREE_TYPE (tmp2), null_pointer_node));
8924 1.1 mrg se->expr = tmp;
8925 1.1 mrg }
8926 1.1 mrg else
8927 1.1 mrg {
8928 1.1 mrg /* An optional target. */
8929 1.1 mrg if (arg2->expr->ts.type == BT_CLASS
8930 1.1 mrg && arg2->expr->expr_type != EXPR_FUNCTION)
8931 1.1 mrg gfc_add_data_component (arg2->expr);
8932 1.1 mrg
8933 1.1 mrg if (scalar)
8934 1.1 mrg {
8935 1.1 mrg /* A pointer to a scalar. */
8936 1.1 mrg arg1se.want_pointer = 1;
8937 1.1 mrg gfc_conv_expr (&arg1se, arg1->expr);
8938 1.1 mrg if (arg1->expr->symtree->n.sym->attr.proc_pointer
8939 1.1 mrg && arg1->expr->symtree->n.sym->attr.dummy)
8940 1.1 mrg arg1se.expr = build_fold_indirect_ref_loc (input_location,
8941 1.1 mrg arg1se.expr);
8942 1.1 mrg if (arg1->expr->ts.type == BT_CLASS)
8943 1.1 mrg arg1se.expr = gfc_class_data_get (arg1se.expr);
8944 1.1 mrg
8945 1.1 mrg arg2se.want_pointer = 1;
8946 1.1 mrg gfc_conv_expr (&arg2se, arg2->expr);
8947 1.1 mrg if (arg2->expr->symtree->n.sym->attr.proc_pointer
8948 1.1 mrg && arg2->expr->symtree->n.sym->attr.dummy)
8949 1.1 mrg arg2se.expr = build_fold_indirect_ref_loc (input_location,
8950 1.1 mrg arg2se.expr);
8951 1.1 mrg if (arg2->expr->ts.type == BT_CLASS)
8952 1.1 mrg {
8953 1.1 mrg arg2se.expr = gfc_evaluate_now (arg2se.expr, &arg2se.pre);
8954 1.1 mrg arg2se.expr = gfc_class_data_get (arg2se.expr);
8955 1.1 mrg }
8956 1.1 mrg gfc_add_block_to_block (&se->pre, &arg1se.pre);
8957 1.1 mrg gfc_add_block_to_block (&se->post, &arg1se.post);
8958 1.1 mrg gfc_add_block_to_block (&se->pre, &arg2se.pre);
8959 1.1 mrg gfc_add_block_to_block (&se->post, &arg2se.post);
8960 1.1 mrg tmp = fold_build2_loc (input_location, EQ_EXPR, logical_type_node,
8961 1.1 mrg arg1se.expr, arg2se.expr);
8962 1.1 mrg tmp2 = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
8963 1.1 mrg arg1se.expr, null_pointer_node);
8964 1.1 mrg se->expr = fold_build2_loc (input_location, TRUTH_AND_EXPR,
8965 1.1 mrg logical_type_node, tmp, tmp2);
8966 1.1 mrg }
8967 1.1 mrg else
8968 1.1 mrg {
8969 1.1 mrg /* An array pointer of zero length is not associated if target is
8970 1.1 mrg present. */
8971 1.1 mrg arg1se.descriptor_only = 1;
8972 1.1 mrg gfc_conv_expr_lhs (&arg1se, arg1->expr);
8973 1.1 mrg if (arg1->expr->rank == -1)
8974 1.1 mrg {
8975 1.1 mrg tmp = gfc_conv_descriptor_rank (arg1se.expr);
8976 1.1 mrg tmp = fold_build2_loc (input_location, MINUS_EXPR,
8977 1.1 mrg TREE_TYPE (tmp), tmp,
8978 1.1 mrg build_int_cst (TREE_TYPE (tmp), 1));
8979 1.1 mrg }
8980 1.1 mrg else
8981 1.1 mrg tmp = gfc_rank_cst[arg1->expr->rank - 1];
8982 1.1 mrg tmp = gfc_conv_descriptor_stride_get (arg1se.expr, tmp);
8983 1.1 mrg if (arg2->expr->rank != 0)
8984 1.1 mrg nonzero_arraylen = fold_build2_loc (input_location, NE_EXPR,
8985 1.1 mrg logical_type_node, tmp,
8986 1.1 mrg build_int_cst (TREE_TYPE (tmp), 0));
8987 1.1 mrg
8988 1.1 mrg /* A pointer to an array, call library function _gfor_associated. */
8989 1.1 mrg arg1se.want_pointer = 1;
8990 1.1 mrg gfc_conv_expr_descriptor (&arg1se, arg1->expr);
8991 1.1 mrg gfc_add_block_to_block (&se->pre, &arg1se.pre);
8992 1.1 mrg gfc_add_block_to_block (&se->post, &arg1se.post);
8993 1.1 mrg
8994 1.1 mrg arg2se.want_pointer = 1;
8995 1.1 mrg arg2se.force_no_tmp = 1;
8996 1.1 mrg if (arg2->expr->rank != 0)
8997 1.1 mrg gfc_conv_expr_descriptor (&arg2se, arg2->expr);
8998 1.1 mrg else
8999 1.1 mrg {
9000 1.1 mrg gfc_conv_expr (&arg2se, arg2->expr);
9001 1.1 mrg arg2se.expr
9002 1.1 mrg = gfc_conv_scalar_to_descriptor (&arg2se, arg2se.expr,
9003 1.1 mrg gfc_expr_attr (arg2->expr));
9004 1.1 mrg arg2se.expr = gfc_build_addr_expr (NULL_TREE, arg2se.expr);
9005 1.1 mrg }
9006 1.1 mrg gfc_add_block_to_block (&se->pre, &arg2se.pre);
9007 1.1 mrg gfc_add_block_to_block (&se->post, &arg2se.post);
9008 1.1 mrg se->expr = build_call_expr_loc (input_location,
9009 1.1 mrg gfor_fndecl_associated, 2,
9010 1.1 mrg arg1se.expr, arg2se.expr);
9011 1.1 mrg se->expr = convert (logical_type_node, se->expr);
9012 1.1 mrg if (arg2->expr->rank != 0)
9013 1.1 mrg se->expr = fold_build2_loc (input_location, TRUTH_AND_EXPR,
9014 1.1 mrg logical_type_node, se->expr,
9015 1.1 mrg nonzero_arraylen);
9016 1.1 mrg }
9017 1.1 mrg
9018 1.1 mrg /* If target is present zero character length pointers cannot
9019 1.1 mrg be associated. */
9020 1.1 mrg if (arg1->expr->ts.type == BT_CHARACTER)
9021 1.1 mrg {
9022 1.1 mrg tmp = arg1se.string_length;
9023 1.1 mrg tmp = fold_build2_loc (input_location, NE_EXPR,
9024 1.1 mrg logical_type_node, tmp,
9025 1.1 mrg build_zero_cst (TREE_TYPE (tmp)));
9026 1.1 mrg se->expr = fold_build2_loc (input_location, TRUTH_AND_EXPR,
9027 1.1 mrg logical_type_node, se->expr, tmp);
9028 1.1 mrg }
9029 1.1 mrg }
9030 1.1 mrg
9031 1.1 mrg se->expr = convert (gfc_typenode_for_spec (&expr->ts), se->expr);
9032 1.1 mrg }
9033 1.1 mrg
9034 1.1 mrg
9035 1.1 mrg /* Generate code for the SAME_TYPE_AS intrinsic.
9036 1.1 mrg Generate inline code that directly checks the vindices. */
9037 1.1 mrg
9038 1.1 mrg static void
9039 1.1 mrg gfc_conv_same_type_as (gfc_se *se, gfc_expr *expr)
9040 1.1 mrg {
9041 1.1 mrg gfc_expr *a, *b;
9042 1.1 mrg gfc_se se1, se2;
9043 1.1 mrg tree tmp;
9044 1.1 mrg tree conda = NULL_TREE, condb = NULL_TREE;
9045 1.1 mrg
9046 1.1 mrg gfc_init_se (&se1, NULL);
9047 1.1 mrg gfc_init_se (&se2, NULL);
9048 1.1 mrg
9049 1.1 mrg a = expr->value.function.actual->expr;
9050 1.1 mrg b = expr->value.function.actual->next->expr;
9051 1.1 mrg
9052 1.1 mrg bool unlimited_poly_a = UNLIMITED_POLY (a);
9053 1.1 mrg bool unlimited_poly_b = UNLIMITED_POLY (b);
9054 1.1 mrg if (unlimited_poly_a)
9055 1.1 mrg {
9056 1.1 mrg se1.want_pointer = 1;
9057 1.1 mrg gfc_add_vptr_component (a);
9058 1.1 mrg }
9059 1.1 mrg else if (a->ts.type == BT_CLASS)
9060 1.1 mrg {
9061 1.1 mrg gfc_add_vptr_component (a);
9062 1.1 mrg gfc_add_hash_component (a);
9063 1.1 mrg }
9064 1.1 mrg else if (a->ts.type == BT_DERIVED)
9065 1.1 mrg a = gfc_get_int_expr (gfc_default_integer_kind, NULL,
9066 1.1 mrg a->ts.u.derived->hash_value);
9067 1.1 mrg
9068 1.1 mrg if (unlimited_poly_b)
9069 1.1 mrg {
9070 1.1 mrg se2.want_pointer = 1;
9071 1.1 mrg gfc_add_vptr_component (b);
9072 1.1 mrg }
9073 1.1 mrg else if (b->ts.type == BT_CLASS)
9074 1.1 mrg {
9075 1.1 mrg gfc_add_vptr_component (b);
9076 1.1 mrg gfc_add_hash_component (b);
9077 1.1 mrg }
9078 1.1 mrg else if (b->ts.type == BT_DERIVED)
9079 1.1 mrg b = gfc_get_int_expr (gfc_default_integer_kind, NULL,
9080 1.1 mrg b->ts.u.derived->hash_value);
9081 1.1 mrg
9082 1.1 mrg gfc_conv_expr (&se1, a);
9083 1.1 mrg gfc_conv_expr (&se2, b);
9084 1.1 mrg
9085 1.1 mrg if (unlimited_poly_a)
9086 1.1 mrg {
9087 1.1 mrg conda = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
9088 1.1 mrg se1.expr,
9089 1.1 mrg build_int_cst (TREE_TYPE (se1.expr), 0));
9090 1.1 mrg se1.expr = gfc_vptr_hash_get (se1.expr);
9091 1.1 mrg }
9092 1.1 mrg
9093 1.1 mrg if (unlimited_poly_b)
9094 1.1 mrg {
9095 1.1 mrg condb = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
9096 1.1 mrg se2.expr,
9097 1.1 mrg build_int_cst (TREE_TYPE (se2.expr), 0));
9098 1.1 mrg se2.expr = gfc_vptr_hash_get (se2.expr);
9099 1.1 mrg }
9100 1.1 mrg
9101 1.1 mrg tmp = fold_build2_loc (input_location, EQ_EXPR,
9102 1.1 mrg logical_type_node, se1.expr,
9103 1.1 mrg fold_convert (TREE_TYPE (se1.expr), se2.expr));
9104 1.1 mrg
9105 1.1 mrg if (conda)
9106 1.1 mrg tmp = fold_build2_loc (input_location, TRUTH_ANDIF_EXPR,
9107 1.1 mrg logical_type_node, conda, tmp);
9108 1.1 mrg
9109 1.1 mrg if (condb)
9110 1.1 mrg tmp = fold_build2_loc (input_location, TRUTH_ANDIF_EXPR,
9111 1.1 mrg logical_type_node, condb, tmp);
9112 1.1 mrg
9113 1.1 mrg se->expr = convert (gfc_typenode_for_spec (&expr->ts), tmp);
9114 1.1 mrg }
9115 1.1 mrg
9116 1.1 mrg
9117 1.1 mrg /* Generate code for SELECTED_CHAR_KIND (NAME) intrinsic function. */
9118 1.1 mrg
9119 1.1 mrg static void
9120 1.1 mrg gfc_conv_intrinsic_sc_kind (gfc_se *se, gfc_expr *expr)
9121 1.1 mrg {
9122 1.1 mrg tree args[2];
9123 1.1 mrg
9124 1.1 mrg gfc_conv_intrinsic_function_args (se, expr, args, 2);
9125 1.1 mrg se->expr = build_call_expr_loc (input_location,
9126 1.1 mrg gfor_fndecl_sc_kind, 2, args[0], args[1]);
9127 1.1 mrg se->expr = fold_convert (gfc_typenode_for_spec (&expr->ts), se->expr);
9128 1.1 mrg }
9129 1.1 mrg
9130 1.1 mrg
9131 1.1 mrg /* Generate code for SELECTED_INT_KIND (R) intrinsic function. */
9132 1.1 mrg
9133 1.1 mrg static void
9134 1.1 mrg gfc_conv_intrinsic_si_kind (gfc_se *se, gfc_expr *expr)
9135 1.1 mrg {
9136 1.1 mrg tree arg, type;
9137 1.1 mrg
9138 1.1 mrg gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
9139 1.1 mrg
9140 1.1 mrg /* The argument to SELECTED_INT_KIND is INTEGER(4). */
9141 1.1 mrg type = gfc_get_int_type (4);
9142 1.1 mrg arg = gfc_build_addr_expr (NULL_TREE, fold_convert (type, arg));
9143 1.1 mrg
9144 1.1 mrg /* Convert it to the required type. */
9145 1.1 mrg type = gfc_typenode_for_spec (&expr->ts);
9146 1.1 mrg se->expr = build_call_expr_loc (input_location,
9147 1.1 mrg gfor_fndecl_si_kind, 1, arg);
9148 1.1 mrg se->expr = fold_convert (type, se->expr);
9149 1.1 mrg }
9150 1.1 mrg
9151 1.1 mrg
9152 1.1 mrg /* Generate code for SELECTED_REAL_KIND (P, R, RADIX) intrinsic function. */
9153 1.1 mrg
9154 1.1 mrg static void
9155 1.1 mrg gfc_conv_intrinsic_sr_kind (gfc_se *se, gfc_expr *expr)
9156 1.1 mrg {
9157 1.1 mrg gfc_actual_arglist *actual;
9158 1.1 mrg tree type;
9159 1.1 mrg gfc_se argse;
9160 1.1 mrg vec<tree, va_gc> *args = NULL;
9161 1.1 mrg
9162 1.1 mrg for (actual = expr->value.function.actual; actual; actual = actual->next)
9163 1.1 mrg {
9164 1.1 mrg gfc_init_se (&argse, se);
9165 1.1 mrg
9166 1.1 mrg /* Pass a NULL pointer for an absent arg. */
9167 1.1 mrg if (actual->expr == NULL)
9168 1.1 mrg argse.expr = null_pointer_node;
9169 1.1 mrg else
9170 1.1 mrg {
9171 1.1 mrg gfc_typespec ts;
9172 1.1 mrg gfc_clear_ts (&ts);
9173 1.1 mrg
9174 1.1 mrg if (actual->expr->ts.kind != gfc_c_int_kind)
9175 1.1 mrg {
9176 1.1 mrg /* The arguments to SELECTED_REAL_KIND are INTEGER(4). */
9177 1.1 mrg ts.type = BT_INTEGER;
9178 1.1 mrg ts.kind = gfc_c_int_kind;
9179 1.1 mrg gfc_convert_type (actual->expr, &ts, 2);
9180 1.1 mrg }
9181 1.1 mrg gfc_conv_expr_reference (&argse, actual->expr);
9182 1.1 mrg }
9183 1.1 mrg
9184 1.1 mrg gfc_add_block_to_block (&se->pre, &argse.pre);
9185 1.1 mrg gfc_add_block_to_block (&se->post, &argse.post);
9186 1.1 mrg vec_safe_push (args, argse.expr);
9187 1.1 mrg }
9188 1.1 mrg
9189 1.1 mrg /* Convert it to the required type. */
9190 1.1 mrg type = gfc_typenode_for_spec (&expr->ts);
9191 1.1 mrg se->expr = build_call_expr_loc_vec (input_location,
9192 1.1 mrg gfor_fndecl_sr_kind, args);
9193 1.1 mrg se->expr = fold_convert (type, se->expr);
9194 1.1 mrg }
9195 1.1 mrg
9196 1.1 mrg
9197 1.1 mrg /* Generate code for TRIM (A) intrinsic function. */
9198 1.1 mrg
9199 1.1 mrg static void
9200 1.1 mrg gfc_conv_intrinsic_trim (gfc_se * se, gfc_expr * expr)
9201 1.1 mrg {
9202 1.1 mrg tree var;
9203 1.1 mrg tree len;
9204 1.1 mrg tree addr;
9205 1.1 mrg tree tmp;
9206 1.1 mrg tree cond;
9207 1.1 mrg tree fndecl;
9208 1.1 mrg tree function;
9209 1.1 mrg tree *args;
9210 1.1 mrg unsigned int num_args;
9211 1.1 mrg
9212 1.1 mrg num_args = gfc_intrinsic_argument_list_length (expr) + 2;
9213 1.1 mrg args = XALLOCAVEC (tree, num_args);
9214 1.1 mrg
9215 1.1 mrg var = gfc_create_var (gfc_get_pchar_type (expr->ts.kind), "pstr");
9216 1.1 mrg addr = gfc_build_addr_expr (ppvoid_type_node, var);
9217 1.1 mrg len = gfc_create_var (gfc_charlen_type_node, "len");
9218 1.1 mrg
9219 1.1 mrg gfc_conv_intrinsic_function_args (se, expr, &args[2], num_args - 2);
9220 1.1 mrg args[0] = gfc_build_addr_expr (NULL_TREE, len);
9221 1.1 mrg args[1] = addr;
9222 1.1 mrg
9223 1.1 mrg if (expr->ts.kind == 1)
9224 1.1 mrg function = gfor_fndecl_string_trim;
9225 1.1 mrg else if (expr->ts.kind == 4)
9226 1.1 mrg function = gfor_fndecl_string_trim_char4;
9227 1.1 mrg else
9228 1.1 mrg gcc_unreachable ();
9229 1.1 mrg
9230 1.1 mrg fndecl = build_addr (function);
9231 1.1 mrg tmp = build_call_array_loc (input_location,
9232 1.1 mrg TREE_TYPE (TREE_TYPE (function)), fndecl,
9233 1.1 mrg num_args, args);
9234 1.1 mrg gfc_add_expr_to_block (&se->pre, tmp);
9235 1.1 mrg
9236 1.1 mrg /* Free the temporary afterwards, if necessary. */
9237 1.1 mrg cond = fold_build2_loc (input_location, GT_EXPR, logical_type_node,
9238 1.1 mrg len, build_int_cst (TREE_TYPE (len), 0));
9239 1.1 mrg tmp = gfc_call_free (var);
9240 1.1 mrg tmp = build3_v (COND_EXPR, cond, tmp, build_empty_stmt (input_location));
9241 1.1 mrg gfc_add_expr_to_block (&se->post, tmp);
9242 1.1 mrg
9243 1.1 mrg se->expr = var;
9244 1.1 mrg se->string_length = len;
9245 1.1 mrg }
9246 1.1 mrg
9247 1.1 mrg
9248 1.1 mrg /* Generate code for REPEAT (STRING, NCOPIES) intrinsic function. */
9249 1.1 mrg
9250 1.1 mrg static void
9251 1.1 mrg gfc_conv_intrinsic_repeat (gfc_se * se, gfc_expr * expr)
9252 1.1 mrg {
9253 1.1 mrg tree args[3], ncopies, dest, dlen, src, slen, ncopies_type;
9254 1.1 mrg tree type, cond, tmp, count, exit_label, n, max, largest;
9255 1.1 mrg tree size;
9256 1.1 mrg stmtblock_t block, body;
9257 1.1 mrg int i;
9258 1.1 mrg
9259 1.1 mrg /* We store in charsize the size of a character. */
9260 1.1 mrg i = gfc_validate_kind (BT_CHARACTER, expr->ts.kind, false);
9261 1.1 mrg size = build_int_cst (sizetype, gfc_character_kinds[i].bit_size / 8);
9262 1.1 mrg
9263 1.1 mrg /* Get the arguments. */
9264 1.1 mrg gfc_conv_intrinsic_function_args (se, expr, args, 3);
9265 1.1 mrg slen = fold_convert (sizetype, gfc_evaluate_now (args[0], &se->pre));
9266 1.1 mrg src = args[1];
9267 1.1 mrg ncopies = gfc_evaluate_now (args[2], &se->pre);
9268 1.1 mrg ncopies_type = TREE_TYPE (ncopies);
9269 1.1 mrg
9270 1.1 mrg /* Check that NCOPIES is not negative. */
9271 1.1 mrg cond = fold_build2_loc (input_location, LT_EXPR, logical_type_node, ncopies,
9272 1.1 mrg build_int_cst (ncopies_type, 0));
9273 1.1 mrg gfc_trans_runtime_check (true, false, cond, &se->pre, &expr->where,
9274 1.1 mrg "Argument NCOPIES of REPEAT intrinsic is negative "
9275 1.1 mrg "(its value is %ld)",
9276 1.1 mrg fold_convert (long_integer_type_node, ncopies));
9277 1.1 mrg
9278 1.1 mrg /* If the source length is zero, any non negative value of NCOPIES
9279 1.1 mrg is valid, and nothing happens. */
9280 1.1 mrg n = gfc_create_var (ncopies_type, "ncopies");
9281 1.1 mrg cond = fold_build2_loc (input_location, EQ_EXPR, logical_type_node, slen,
9282 1.1 mrg size_zero_node);
9283 1.1 mrg tmp = fold_build3_loc (input_location, COND_EXPR, ncopies_type, cond,
9284 1.1 mrg build_int_cst (ncopies_type, 0), ncopies);
9285 1.1 mrg gfc_add_modify (&se->pre, n, tmp);
9286 1.1 mrg ncopies = n;
9287 1.1 mrg
9288 1.1 mrg /* Check that ncopies is not too large: ncopies should be less than
9289 1.1 mrg (or equal to) MAX / slen, where MAX is the maximal integer of
9290 1.1 mrg the gfc_charlen_type_node type. If slen == 0, we need a special
9291 1.1 mrg case to avoid the division by zero. */
9292 1.1 mrg max = fold_build2_loc (input_location, TRUNC_DIV_EXPR, sizetype,
9293 1.1 mrg fold_convert (sizetype,
9294 1.1 mrg TYPE_MAX_VALUE (gfc_charlen_type_node)),
9295 1.1 mrg slen);
9296 1.1 mrg largest = TYPE_PRECISION (sizetype) > TYPE_PRECISION (ncopies_type)
9297 1.1 mrg ? sizetype : ncopies_type;
9298 1.1 mrg cond = fold_build2_loc (input_location, GT_EXPR, logical_type_node,
9299 1.1 mrg fold_convert (largest, ncopies),
9300 1.1 mrg fold_convert (largest, max));
9301 1.1 mrg tmp = fold_build2_loc (input_location, EQ_EXPR, logical_type_node, slen,
9302 1.1 mrg size_zero_node);
9303 1.1 mrg cond = fold_build3_loc (input_location, COND_EXPR, logical_type_node, tmp,
9304 1.1 mrg logical_false_node, cond);
9305 1.1 mrg gfc_trans_runtime_check (true, false, cond, &se->pre, &expr->where,
9306 1.1 mrg "Argument NCOPIES of REPEAT intrinsic is too large");
9307 1.1 mrg
9308 1.1 mrg /* Compute the destination length. */
9309 1.1 mrg dlen = fold_build2_loc (input_location, MULT_EXPR, gfc_charlen_type_node,
9310 1.1 mrg fold_convert (gfc_charlen_type_node, slen),
9311 1.1 mrg fold_convert (gfc_charlen_type_node, ncopies));
9312 1.1 mrg type = gfc_get_character_type (expr->ts.kind, expr->ts.u.cl);
9313 1.1 mrg dest = gfc_conv_string_tmp (se, build_pointer_type (type), dlen);
9314 1.1 mrg
9315 1.1 mrg /* Generate the code to do the repeat operation:
9316 1.1 mrg for (i = 0; i < ncopies; i++)
9317 1.1 mrg memmove (dest + (i * slen * size), src, slen*size); */
9318 1.1 mrg gfc_start_block (&block);
9319 1.1 mrg count = gfc_create_var (sizetype, "count");
9320 1.1 mrg gfc_add_modify (&block, count, size_zero_node);
9321 1.1 mrg exit_label = gfc_build_label_decl (NULL_TREE);
9322 1.1 mrg
9323 1.1 mrg /* Start the loop body. */
9324 1.1 mrg gfc_start_block (&body);
9325 1.1 mrg
9326 1.1 mrg /* Exit the loop if count >= ncopies. */
9327 1.1 mrg cond = fold_build2_loc (input_location, GE_EXPR, logical_type_node, count,
9328 1.1 mrg fold_convert (sizetype, ncopies));
9329 1.1 mrg tmp = build1_v (GOTO_EXPR, exit_label);
9330 1.1 mrg TREE_USED (exit_label) = 1;
9331 1.1 mrg tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node, cond, tmp,
9332 1.1 mrg build_empty_stmt (input_location));
9333 1.1 mrg gfc_add_expr_to_block (&body, tmp);
9334 1.1 mrg
9335 1.1 mrg /* Call memmove (dest + (i*slen*size), src, slen*size). */
9336 1.1 mrg tmp = fold_build2_loc (input_location, MULT_EXPR, sizetype, slen,
9337 1.1 mrg count);
9338 1.1 mrg tmp = fold_build2_loc (input_location, MULT_EXPR, sizetype, tmp,
9339 1.1 mrg size);
9340 1.1 mrg tmp = fold_build_pointer_plus_loc (input_location,
9341 1.1 mrg fold_convert (pvoid_type_node, dest), tmp);
9342 1.1 mrg tmp = build_call_expr_loc (input_location,
9343 1.1 mrg builtin_decl_explicit (BUILT_IN_MEMMOVE),
9344 1.1 mrg 3, tmp, src,
9345 1.1 mrg fold_build2_loc (input_location, MULT_EXPR,
9346 1.1 mrg size_type_node, slen, size));
9347 1.1 mrg gfc_add_expr_to_block (&body, tmp);
9348 1.1 mrg
9349 1.1 mrg /* Increment count. */
9350 1.1 mrg tmp = fold_build2_loc (input_location, PLUS_EXPR, sizetype,
9351 1.1 mrg count, size_one_node);
9352 1.1 mrg gfc_add_modify (&body, count, tmp);
9353 1.1 mrg
9354 1.1 mrg /* Build the loop. */
9355 1.1 mrg tmp = build1_v (LOOP_EXPR, gfc_finish_block (&body));
9356 1.1 mrg gfc_add_expr_to_block (&block, tmp);
9357 1.1 mrg
9358 1.1 mrg /* Add the exit label. */
9359 1.1 mrg tmp = build1_v (LABEL_EXPR, exit_label);
9360 1.1 mrg gfc_add_expr_to_block (&block, tmp);
9361 1.1 mrg
9362 1.1 mrg /* Finish the block. */
9363 1.1 mrg tmp = gfc_finish_block (&block);
9364 1.1 mrg gfc_add_expr_to_block (&se->pre, tmp);
9365 1.1 mrg
9366 1.1 mrg /* Set the result value. */
9367 1.1 mrg se->expr = dest;
9368 1.1 mrg se->string_length = dlen;
9369 1.1 mrg }
9370 1.1 mrg
9371 1.1 mrg
9372 1.1 mrg /* Generate code for the IARGC intrinsic. */
9373 1.1 mrg
9374 1.1 mrg static void
9375 1.1 mrg gfc_conv_intrinsic_iargc (gfc_se * se, gfc_expr * expr)
9376 1.1 mrg {
9377 1.1 mrg tree tmp;
9378 1.1 mrg tree fndecl;
9379 1.1 mrg tree type;
9380 1.1 mrg
9381 1.1 mrg /* Call the library function. This always returns an INTEGER(4). */
9382 1.1 mrg fndecl = gfor_fndecl_iargc;
9383 1.1 mrg tmp = build_call_expr_loc (input_location,
9384 1.1 mrg fndecl, 0);
9385 1.1 mrg
9386 1.1 mrg /* Convert it to the required type. */
9387 1.1 mrg type = gfc_typenode_for_spec (&expr->ts);
9388 1.1 mrg tmp = fold_convert (type, tmp);
9389 1.1 mrg
9390 1.1 mrg se->expr = tmp;
9391 1.1 mrg }
9392 1.1 mrg
9393 1.1 mrg
9394 1.1 mrg /* Generate code for the KILL intrinsic. */
9395 1.1 mrg
9396 1.1 mrg static void
9397 1.1 mrg conv_intrinsic_kill (gfc_se *se, gfc_expr *expr)
9398 1.1 mrg {
9399 1.1 mrg tree *args;
9400 1.1 mrg tree int4_type_node = gfc_get_int_type (4);
9401 1.1 mrg tree pid;
9402 1.1 mrg tree sig;
9403 1.1 mrg tree tmp;
9404 1.1 mrg unsigned int num_args;
9405 1.1 mrg
9406 1.1 mrg num_args = gfc_intrinsic_argument_list_length (expr);
9407 1.1 mrg args = XALLOCAVEC (tree, num_args);
9408 1.1 mrg gfc_conv_intrinsic_function_args (se, expr, args, num_args);
9409 1.1 mrg
9410 1.1 mrg /* Convert PID to a INTEGER(4) entity. */
9411 1.1 mrg pid = convert (int4_type_node, args[0]);
9412 1.1 mrg
9413 1.1 mrg /* Convert SIG to a INTEGER(4) entity. */
9414 1.1 mrg sig = convert (int4_type_node, args[1]);
9415 1.1 mrg
9416 1.1 mrg tmp = build_call_expr_loc (input_location, gfor_fndecl_kill, 2, pid, sig);
9417 1.1 mrg
9418 1.1 mrg se->expr = fold_convert (TREE_TYPE (args[0]), tmp);
9419 1.1 mrg }
9420 1.1 mrg
9421 1.1 mrg
9422 1.1 mrg static tree
9423 1.1 mrg conv_intrinsic_kill_sub (gfc_code *code)
9424 1.1 mrg {
9425 1.1 mrg stmtblock_t block;
9426 1.1 mrg gfc_se se, se_stat;
9427 1.1 mrg tree int4_type_node = gfc_get_int_type (4);
9428 1.1 mrg tree pid;
9429 1.1 mrg tree sig;
9430 1.1 mrg tree statp;
9431 1.1 mrg tree tmp;
9432 1.1 mrg
9433 1.1 mrg /* Make the function call. */
9434 1.1 mrg gfc_init_block (&block);
9435 1.1 mrg gfc_init_se (&se, NULL);
9436 1.1 mrg
9437 1.1 mrg /* Convert PID to a INTEGER(4) entity. */
9438 1.1 mrg gfc_conv_expr (&se, code->ext.actual->expr);
9439 1.1 mrg gfc_add_block_to_block (&block, &se.pre);
9440 1.1 mrg pid = fold_convert (int4_type_node, gfc_evaluate_now (se.expr, &block));
9441 1.1 mrg gfc_add_block_to_block (&block, &se.post);
9442 1.1 mrg
9443 1.1 mrg /* Convert SIG to a INTEGER(4) entity. */
9444 1.1 mrg gfc_conv_expr (&se, code->ext.actual->next->expr);
9445 1.1 mrg gfc_add_block_to_block (&block, &se.pre);
9446 1.1 mrg sig = fold_convert (int4_type_node, gfc_evaluate_now (se.expr, &block));
9447 1.1 mrg gfc_add_block_to_block (&block, &se.post);
9448 1.1 mrg
9449 1.1 mrg /* Deal with an optional STATUS. */
9450 1.1 mrg if (code->ext.actual->next->next->expr)
9451 1.1 mrg {
9452 1.1 mrg gfc_init_se (&se_stat, NULL);
9453 1.1 mrg gfc_conv_expr (&se_stat, code->ext.actual->next->next->expr);
9454 1.1 mrg statp = gfc_create_var (gfc_get_int_type (4), "_statp");
9455 1.1 mrg }
9456 1.1 mrg else
9457 1.1 mrg statp = NULL_TREE;
9458 1.1 mrg
9459 1.1 mrg tmp = build_call_expr_loc (input_location, gfor_fndecl_kill_sub, 3, pid, sig,
9460 1.1 mrg statp ? gfc_build_addr_expr (NULL_TREE, statp) : null_pointer_node);
9461 1.1 mrg
9462 1.1 mrg gfc_add_expr_to_block (&block, tmp);
9463 1.1 mrg
9464 1.1 mrg if (statp && statp != se_stat.expr)
9465 1.1 mrg gfc_add_modify (&block, se_stat.expr,
9466 1.1 mrg fold_convert (TREE_TYPE (se_stat.expr), statp));
9467 1.1 mrg
9468 1.1 mrg return gfc_finish_block (&block);
9469 1.1 mrg }
9470 1.1 mrg
9471 1.1 mrg
9472 1.1 mrg
9473 1.1 mrg /* The loc intrinsic returns the address of its argument as
9474 1.1 mrg gfc_index_integer_kind integer. */
9475 1.1 mrg
9476 1.1 mrg static void
9477 1.1 mrg gfc_conv_intrinsic_loc (gfc_se * se, gfc_expr * expr)
9478 1.1 mrg {
9479 1.1 mrg tree temp_var;
9480 1.1 mrg gfc_expr *arg_expr;
9481 1.1 mrg
9482 1.1 mrg gcc_assert (!se->ss);
9483 1.1 mrg
9484 1.1 mrg arg_expr = expr->value.function.actual->expr;
9485 1.1 mrg if (arg_expr->rank == 0)
9486 1.1 mrg {
9487 1.1 mrg if (arg_expr->ts.type == BT_CLASS)
9488 1.1 mrg gfc_add_data_component (arg_expr);
9489 1.1 mrg gfc_conv_expr_reference (se, arg_expr);
9490 1.1 mrg }
9491 1.1 mrg else
9492 1.1 mrg gfc_conv_array_parameter (se, arg_expr, true, NULL, NULL, NULL);
9493 1.1 mrg se->expr = convert (gfc_get_int_type (gfc_index_integer_kind), se->expr);
9494 1.1 mrg
9495 1.1 mrg /* Create a temporary variable for loc return value. Without this,
9496 1.1 mrg we get an error an ICE in gcc/expr.cc(expand_expr_addr_expr_1). */
9497 1.1 mrg temp_var = gfc_create_var (gfc_get_int_type (gfc_index_integer_kind), NULL);
9498 1.1 mrg gfc_add_modify (&se->pre, temp_var, se->expr);
9499 1.1 mrg se->expr = temp_var;
9500 1.1 mrg }
9501 1.1 mrg
9502 1.1 mrg
9503 1.1 mrg /* The following routine generates code for the intrinsic
9504 1.1 mrg functions from the ISO_C_BINDING module:
9505 1.1 mrg * C_LOC
9506 1.1 mrg * C_FUNLOC
9507 1.1 mrg * C_ASSOCIATED */
9508 1.1 mrg
9509 1.1 mrg static void
9510 1.1 mrg conv_isocbinding_function (gfc_se *se, gfc_expr *expr)
9511 1.1 mrg {
9512 1.1 mrg gfc_actual_arglist *arg = expr->value.function.actual;
9513 1.1 mrg
9514 1.1 mrg if (expr->value.function.isym->id == GFC_ISYM_C_LOC)
9515 1.1 mrg {
9516 1.1 mrg if (arg->expr->rank == 0)
9517 1.1 mrg gfc_conv_expr_reference (se, arg->expr);
9518 1.1 mrg else if (gfc_is_simply_contiguous (arg->expr, false, false))
9519 1.1 mrg gfc_conv_array_parameter (se, arg->expr, true, NULL, NULL, NULL);
9520 1.1 mrg else
9521 1.1 mrg {
9522 1.1 mrg gfc_conv_expr_descriptor (se, arg->expr);
9523 1.1 mrg se->expr = gfc_conv_descriptor_data_get (se->expr);
9524 1.1 mrg }
9525 1.1 mrg
9526 1.1 mrg /* TODO -- the following two lines shouldn't be necessary, but if
9527 1.1 mrg they're removed, a bug is exposed later in the code path.
9528 1.1 mrg This workaround was thus introduced, but will have to be
9529 1.1 mrg removed; please see PR 35150 for details about the issue. */
9530 1.1 mrg se->expr = convert (pvoid_type_node, se->expr);
9531 1.1 mrg se->expr = gfc_evaluate_now (se->expr, &se->pre);
9532 1.1 mrg }
9533 1.1 mrg else if (expr->value.function.isym->id == GFC_ISYM_C_FUNLOC)
9534 1.1 mrg gfc_conv_expr_reference (se, arg->expr);
9535 1.1 mrg else if (expr->value.function.isym->id == GFC_ISYM_C_ASSOCIATED)
9536 1.1 mrg {
9537 1.1 mrg gfc_se arg1se;
9538 1.1 mrg gfc_se arg2se;
9539 1.1 mrg
9540 1.1 mrg /* Build the addr_expr for the first argument. The argument is
9541 1.1 mrg already an *address* so we don't need to set want_pointer in
9542 1.1 mrg the gfc_se. */
9543 1.1 mrg gfc_init_se (&arg1se, NULL);
9544 1.1 mrg gfc_conv_expr (&arg1se, arg->expr);
9545 1.1 mrg gfc_add_block_to_block (&se->pre, &arg1se.pre);
9546 1.1 mrg gfc_add_block_to_block (&se->post, &arg1se.post);
9547 1.1 mrg
9548 1.1 mrg /* See if we were given two arguments. */
9549 1.1 mrg if (arg->next->expr == NULL)
9550 1.1 mrg /* Only given one arg so generate a null and do a
9551 1.1 mrg not-equal comparison against the first arg. */
9552 1.1 mrg se->expr = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
9553 1.1 mrg arg1se.expr,
9554 1.1 mrg fold_convert (TREE_TYPE (arg1se.expr),
9555 1.1 mrg null_pointer_node));
9556 1.1 mrg else
9557 1.1 mrg {
9558 1.1 mrg tree eq_expr;
9559 1.1 mrg tree not_null_expr;
9560 1.1 mrg
9561 1.1 mrg /* Given two arguments so build the arg2se from second arg. */
9562 1.1 mrg gfc_init_se (&arg2se, NULL);
9563 1.1 mrg gfc_conv_expr (&arg2se, arg->next->expr);
9564 1.1 mrg gfc_add_block_to_block (&se->pre, &arg2se.pre);
9565 1.1 mrg gfc_add_block_to_block (&se->post, &arg2se.post);
9566 1.1 mrg
9567 1.1 mrg /* Generate test to compare that the two args are equal. */
9568 1.1 mrg eq_expr = fold_build2_loc (input_location, EQ_EXPR, logical_type_node,
9569 1.1 mrg arg1se.expr, arg2se.expr);
9570 1.1 mrg /* Generate test to ensure that the first arg is not null. */
9571 1.1 mrg not_null_expr = fold_build2_loc (input_location, NE_EXPR,
9572 1.1 mrg logical_type_node,
9573 1.1 mrg arg1se.expr, null_pointer_node);
9574 1.1 mrg
9575 1.1 mrg /* Finally, the generated test must check that both arg1 is not
9576 1.1 mrg NULL and that it is equal to the second arg. */
9577 1.1 mrg se->expr = fold_build2_loc (input_location, TRUTH_AND_EXPR,
9578 1.1 mrg logical_type_node,
9579 1.1 mrg not_null_expr, eq_expr);
9580 1.1 mrg }
9581 1.1 mrg }
9582 1.1 mrg else
9583 1.1 mrg gcc_unreachable ();
9584 1.1 mrg }
9585 1.1 mrg
9586 1.1 mrg
9587 1.1 mrg /* The following routine generates code for the intrinsic
9588 1.1 mrg subroutines from the ISO_C_BINDING module:
9589 1.1 mrg * C_F_POINTER
9590 1.1 mrg * C_F_PROCPOINTER. */
9591 1.1 mrg
9592 1.1 mrg static tree
9593 1.1 mrg conv_isocbinding_subroutine (gfc_code *code)
9594 1.1 mrg {
9595 1.1 mrg gfc_se se;
9596 1.1 mrg gfc_se cptrse;
9597 1.1 mrg gfc_se fptrse;
9598 1.1 mrg gfc_se shapese;
9599 1.1 mrg gfc_ss *shape_ss;
9600 1.1 mrg tree desc, dim, tmp, stride, offset;
9601 1.1 mrg stmtblock_t body, block;
9602 1.1 mrg gfc_loopinfo loop;
9603 1.1 mrg gfc_actual_arglist *arg = code->ext.actual;
9604 1.1 mrg
9605 1.1 mrg gfc_init_se (&se, NULL);
9606 1.1 mrg gfc_init_se (&cptrse, NULL);
9607 1.1 mrg gfc_conv_expr (&cptrse, arg->expr);
9608 1.1 mrg gfc_add_block_to_block (&se.pre, &cptrse.pre);
9609 1.1 mrg gfc_add_block_to_block (&se.post, &cptrse.post);
9610 1.1 mrg
9611 1.1 mrg gfc_init_se (&fptrse, NULL);
9612 1.1 mrg if (arg->next->expr->rank == 0)
9613 1.1 mrg {
9614 1.1 mrg fptrse.want_pointer = 1;
9615 1.1 mrg gfc_conv_expr (&fptrse, arg->next->expr);
9616 1.1 mrg gfc_add_block_to_block (&se.pre, &fptrse.pre);
9617 1.1 mrg gfc_add_block_to_block (&se.post, &fptrse.post);
9618 1.1 mrg if (arg->next->expr->symtree->n.sym->attr.proc_pointer
9619 1.1 mrg && arg->next->expr->symtree->n.sym->attr.dummy)
9620 1.1 mrg fptrse.expr = build_fold_indirect_ref_loc (input_location,
9621 1.1 mrg fptrse.expr);
9622 1.1 mrg se.expr = fold_build2_loc (input_location, MODIFY_EXPR,
9623 1.1 mrg TREE_TYPE (fptrse.expr),
9624 1.1 mrg fptrse.expr,
9625 1.1 mrg fold_convert (TREE_TYPE (fptrse.expr),
9626 1.1 mrg cptrse.expr));
9627 1.1 mrg gfc_add_expr_to_block (&se.pre, se.expr);
9628 1.1 mrg gfc_add_block_to_block (&se.pre, &se.post);
9629 1.1 mrg return gfc_finish_block (&se.pre);
9630 1.1 mrg }
9631 1.1 mrg
9632 1.1 mrg gfc_start_block (&block);
9633 1.1 mrg
9634 1.1 mrg /* Get the descriptor of the Fortran pointer. */
9635 1.1 mrg fptrse.descriptor_only = 1;
9636 1.1 mrg gfc_conv_expr_descriptor (&fptrse, arg->next->expr);
9637 1.1 mrg gfc_add_block_to_block (&block, &fptrse.pre);
9638 1.1 mrg desc = fptrse.expr;
9639 1.1 mrg
9640 1.1 mrg /* Set the span field. */
9641 1.1 mrg tmp = TYPE_SIZE_UNIT (gfc_get_element_type (TREE_TYPE (desc)));
9642 1.1 mrg tmp = fold_convert (gfc_array_index_type, tmp);
9643 1.1 mrg gfc_conv_descriptor_span_set (&block, desc, tmp);
9644 1.1 mrg
9645 1.1 mrg /* Set data value, dtype, and offset. */
9646 1.1 mrg tmp = GFC_TYPE_ARRAY_DATAPTR_TYPE (TREE_TYPE (desc));
9647 1.1 mrg gfc_conv_descriptor_data_set (&block, desc, fold_convert (tmp, cptrse.expr));
9648 1.1 mrg gfc_add_modify (&block, gfc_conv_descriptor_dtype (desc),
9649 1.1 mrg gfc_get_dtype (TREE_TYPE (desc)));
9650 1.1 mrg
9651 1.1 mrg /* Start scalarization of the bounds, using the shape argument. */
9652 1.1 mrg
9653 1.1 mrg shape_ss = gfc_walk_expr (arg->next->next->expr);
9654 1.1 mrg gcc_assert (shape_ss != gfc_ss_terminator);
9655 1.1 mrg gfc_init_se (&shapese, NULL);
9656 1.1 mrg
9657 1.1 mrg gfc_init_loopinfo (&loop);
9658 1.1 mrg gfc_add_ss_to_loop (&loop, shape_ss);
9659 1.1 mrg gfc_conv_ss_startstride (&loop);
9660 1.1 mrg gfc_conv_loop_setup (&loop, &arg->next->expr->where);
9661 1.1 mrg gfc_mark_ss_chain_used (shape_ss, 1);
9662 1.1 mrg
9663 1.1 mrg gfc_copy_loopinfo_to_se (&shapese, &loop);
9664 1.1 mrg shapese.ss = shape_ss;
9665 1.1 mrg
9666 1.1 mrg stride = gfc_create_var (gfc_array_index_type, "stride");
9667 1.1 mrg offset = gfc_create_var (gfc_array_index_type, "offset");
9668 1.1 mrg gfc_add_modify (&block, stride, gfc_index_one_node);
9669 1.1 mrg gfc_add_modify (&block, offset, gfc_index_zero_node);
9670 1.1 mrg
9671 1.1 mrg /* Loop body. */
9672 1.1 mrg gfc_start_scalarized_body (&loop, &body);
9673 1.1 mrg
9674 1.1 mrg dim = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
9675 1.1 mrg loop.loopvar[0], loop.from[0]);
9676 1.1 mrg
9677 1.1 mrg /* Set bounds and stride. */
9678 1.1 mrg gfc_conv_descriptor_lbound_set (&body, desc, dim, gfc_index_one_node);
9679 1.1 mrg gfc_conv_descriptor_stride_set (&body, desc, dim, stride);
9680 1.1 mrg
9681 1.1 mrg gfc_conv_expr (&shapese, arg->next->next->expr);
9682 1.1 mrg gfc_add_block_to_block (&body, &shapese.pre);
9683 1.1 mrg gfc_conv_descriptor_ubound_set (&body, desc, dim, shapese.expr);
9684 1.1 mrg gfc_add_block_to_block (&body, &shapese.post);
9685 1.1 mrg
9686 1.1 mrg /* Calculate offset. */
9687 1.1 mrg gfc_add_modify (&body, offset,
9688 1.1 mrg fold_build2_loc (input_location, PLUS_EXPR,
9689 1.1 mrg gfc_array_index_type, offset, stride));
9690 1.1 mrg /* Update stride. */
9691 1.1 mrg gfc_add_modify (&body, stride,
9692 1.1 mrg fold_build2_loc (input_location, MULT_EXPR,
9693 1.1 mrg gfc_array_index_type, stride,
9694 1.1 mrg fold_convert (gfc_array_index_type,
9695 1.1 mrg shapese.expr)));
9696 1.1 mrg /* Finish scalarization loop. */
9697 1.1 mrg gfc_trans_scalarizing_loops (&loop, &body);
9698 1.1 mrg gfc_add_block_to_block (&block, &loop.pre);
9699 1.1 mrg gfc_add_block_to_block (&block, &loop.post);
9700 1.1 mrg gfc_add_block_to_block (&block, &fptrse.post);
9701 1.1 mrg gfc_cleanup_loop (&loop);
9702 1.1 mrg
9703 1.1 mrg gfc_add_modify (&block, offset,
9704 1.1 mrg fold_build1_loc (input_location, NEGATE_EXPR,
9705 1.1 mrg gfc_array_index_type, offset));
9706 1.1 mrg gfc_conv_descriptor_offset_set (&block, desc, offset);
9707 1.1 mrg
9708 1.1 mrg gfc_add_expr_to_block (&se.pre, gfc_finish_block (&block));
9709 1.1 mrg gfc_add_block_to_block (&se.pre, &se.post);
9710 1.1 mrg return gfc_finish_block (&se.pre);
9711 1.1 mrg }
9712 1.1 mrg
9713 1.1 mrg
9714 1.1 mrg /* Save and restore floating-point state. */
9715 1.1 mrg
9716 1.1 mrg tree
9717 1.1 mrg gfc_save_fp_state (stmtblock_t *block)
9718 1.1 mrg {
9719 1.1 mrg tree type, fpstate, tmp;
9720 1.1 mrg
9721 1.1 mrg type = build_array_type (char_type_node,
9722 1.1 mrg build_range_type (size_type_node, size_zero_node,
9723 1.1 mrg size_int (GFC_FPE_STATE_BUFFER_SIZE)));
9724 1.1 mrg fpstate = gfc_create_var (type, "fpstate");
9725 1.1 mrg fpstate = gfc_build_addr_expr (pvoid_type_node, fpstate);
9726 1.1 mrg
9727 1.1 mrg tmp = build_call_expr_loc (input_location, gfor_fndecl_ieee_procedure_entry,
9728 1.1 mrg 1, fpstate);
9729 1.1 mrg gfc_add_expr_to_block (block, tmp);
9730 1.1 mrg
9731 1.1 mrg return fpstate;
9732 1.1 mrg }
9733 1.1 mrg
9734 1.1 mrg
9735 1.1 mrg void
9736 1.1 mrg gfc_restore_fp_state (stmtblock_t *block, tree fpstate)
9737 1.1 mrg {
9738 1.1 mrg tree tmp;
9739 1.1 mrg
9740 1.1 mrg tmp = build_call_expr_loc (input_location, gfor_fndecl_ieee_procedure_exit,
9741 1.1 mrg 1, fpstate);
9742 1.1 mrg gfc_add_expr_to_block (block, tmp);
9743 1.1 mrg }
9744 1.1 mrg
9745 1.1 mrg
9746 1.1 mrg /* Generate code for arguments of IEEE functions. */
9747 1.1 mrg
9748 1.1 mrg static void
9749 1.1 mrg conv_ieee_function_args (gfc_se *se, gfc_expr *expr, tree *argarray,
9750 1.1 mrg int nargs)
9751 1.1 mrg {
9752 1.1 mrg gfc_actual_arglist *actual;
9753 1.1 mrg gfc_expr *e;
9754 1.1 mrg gfc_se argse;
9755 1.1 mrg int arg;
9756 1.1 mrg
9757 1.1 mrg actual = expr->value.function.actual;
9758 1.1 mrg for (arg = 0; arg < nargs; arg++, actual = actual->next)
9759 1.1 mrg {
9760 1.1 mrg gcc_assert (actual);
9761 1.1 mrg e = actual->expr;
9762 1.1 mrg
9763 1.1 mrg gfc_init_se (&argse, se);
9764 1.1 mrg gfc_conv_expr_val (&argse, e);
9765 1.1 mrg
9766 1.1 mrg gfc_add_block_to_block (&se->pre, &argse.pre);
9767 1.1 mrg gfc_add_block_to_block (&se->post, &argse.post);
9768 1.1 mrg argarray[arg] = argse.expr;
9769 1.1 mrg }
9770 1.1 mrg }
9771 1.1 mrg
9772 1.1 mrg
9773 1.1 mrg /* Generate code for intrinsics IEEE_IS_NAN, IEEE_IS_FINITE,
9774 1.1 mrg and IEEE_UNORDERED, which translate directly to GCC type-generic
9775 1.1 mrg built-ins. */
9776 1.1 mrg
9777 1.1 mrg static void
9778 1.1 mrg conv_intrinsic_ieee_builtin (gfc_se * se, gfc_expr * expr,
9779 1.1 mrg enum built_in_function code, int nargs)
9780 1.1 mrg {
9781 1.1 mrg tree args[2];
9782 1.1 mrg gcc_assert ((unsigned) nargs <= sizeof(args)/sizeof(args[0]));
9783 1.1 mrg
9784 1.1 mrg conv_ieee_function_args (se, expr, args, nargs);
9785 1.1 mrg se->expr = build_call_expr_loc_array (input_location,
9786 1.1 mrg builtin_decl_explicit (code),
9787 1.1 mrg nargs, args);
9788 1.1 mrg STRIP_TYPE_NOPS (se->expr);
9789 1.1 mrg se->expr = fold_convert (gfc_typenode_for_spec (&expr->ts), se->expr);
9790 1.1 mrg }
9791 1.1 mrg
9792 1.1 mrg
9793 1.1 mrg /* Generate code for IEEE_IS_NORMAL intrinsic:
9794 1.1 mrg IEEE_IS_NORMAL(x) --> (__builtin_isnormal(x) || x == 0) */
9795 1.1 mrg
9796 1.1 mrg static void
9797 1.1 mrg conv_intrinsic_ieee_is_normal (gfc_se * se, gfc_expr * expr)
9798 1.1 mrg {
9799 1.1 mrg tree arg, isnormal, iszero;
9800 1.1 mrg
9801 1.1 mrg /* Convert arg, evaluate it only once. */
9802 1.1 mrg conv_ieee_function_args (se, expr, &arg, 1);
9803 1.1 mrg arg = gfc_evaluate_now (arg, &se->pre);
9804 1.1 mrg
9805 1.1 mrg isnormal = build_call_expr_loc (input_location,
9806 1.1 mrg builtin_decl_explicit (BUILT_IN_ISNORMAL),
9807 1.1 mrg 1, arg);
9808 1.1 mrg iszero = fold_build2_loc (input_location, EQ_EXPR, logical_type_node, arg,
9809 1.1 mrg build_real_from_int_cst (TREE_TYPE (arg),
9810 1.1 mrg integer_zero_node));
9811 1.1 mrg se->expr = fold_build2_loc (input_location, TRUTH_OR_EXPR,
9812 1.1 mrg logical_type_node, isnormal, iszero);
9813 1.1 mrg se->expr = fold_convert (gfc_typenode_for_spec (&expr->ts), se->expr);
9814 1.1 mrg }
9815 1.1 mrg
9816 1.1 mrg
9817 1.1 mrg /* Generate code for IEEE_IS_NEGATIVE intrinsic:
9818 1.1 mrg IEEE_IS_NEGATIVE(x) --> (__builtin_signbit(x) && !__builtin_isnan(x)) */
9819 1.1 mrg
9820 1.1 mrg static void
9821 1.1 mrg conv_intrinsic_ieee_is_negative (gfc_se * se, gfc_expr * expr)
9822 1.1 mrg {
9823 1.1 mrg tree arg, signbit, isnan;
9824 1.1 mrg
9825 1.1 mrg /* Convert arg, evaluate it only once. */
9826 1.1 mrg conv_ieee_function_args (se, expr, &arg, 1);
9827 1.1 mrg arg = gfc_evaluate_now (arg, &se->pre);
9828 1.1 mrg
9829 1.1 mrg isnan = build_call_expr_loc (input_location,
9830 1.1 mrg builtin_decl_explicit (BUILT_IN_ISNAN),
9831 1.1 mrg 1, arg);
9832 1.1 mrg STRIP_TYPE_NOPS (isnan);
9833 1.1 mrg
9834 1.1 mrg signbit = build_call_expr_loc (input_location,
9835 1.1 mrg builtin_decl_explicit (BUILT_IN_SIGNBIT),
9836 1.1 mrg 1, arg);
9837 1.1 mrg signbit = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
9838 1.1 mrg signbit, integer_zero_node);
9839 1.1 mrg
9840 1.1 mrg se->expr = fold_build2_loc (input_location, TRUTH_AND_EXPR,
9841 1.1 mrg logical_type_node, signbit,
9842 1.1 mrg fold_build1_loc (input_location, TRUTH_NOT_EXPR,
9843 1.1 mrg TREE_TYPE(isnan), isnan));
9844 1.1 mrg
9845 1.1 mrg se->expr = fold_convert (gfc_typenode_for_spec (&expr->ts), se->expr);
9846 1.1 mrg }
9847 1.1 mrg
9848 1.1 mrg
9849 1.1 mrg /* Generate code for IEEE_LOGB and IEEE_RINT. */
9850 1.1 mrg
9851 1.1 mrg static void
9852 1.1 mrg conv_intrinsic_ieee_logb_rint (gfc_se * se, gfc_expr * expr,
9853 1.1 mrg enum built_in_function code)
9854 1.1 mrg {
9855 1.1 mrg tree arg, decl, call, fpstate;
9856 1.1 mrg int argprec;
9857 1.1 mrg
9858 1.1 mrg conv_ieee_function_args (se, expr, &arg, 1);
9859 1.1 mrg argprec = TYPE_PRECISION (TREE_TYPE (arg));
9860 1.1 mrg decl = builtin_decl_for_precision (code, argprec);
9861 1.1 mrg
9862 1.1 mrg /* Save floating-point state. */
9863 1.1 mrg fpstate = gfc_save_fp_state (&se->pre);
9864 1.1 mrg
9865 1.1 mrg /* Make the function call. */
9866 1.1 mrg call = build_call_expr_loc (input_location, decl, 1, arg);
9867 1.1 mrg se->expr = fold_convert (gfc_typenode_for_spec (&expr->ts), call);
9868 1.1 mrg
9869 1.1 mrg /* Restore floating-point state. */
9870 1.1 mrg gfc_restore_fp_state (&se->post, fpstate);
9871 1.1 mrg }
9872 1.1 mrg
9873 1.1 mrg
9874 1.1 mrg /* Generate code for IEEE_REM. */
9875 1.1 mrg
9876 1.1 mrg static void
9877 1.1 mrg conv_intrinsic_ieee_rem (gfc_se * se, gfc_expr * expr)
9878 1.1 mrg {
9879 1.1 mrg tree args[2], decl, call, fpstate;
9880 1.1 mrg int argprec;
9881 1.1 mrg
9882 1.1 mrg conv_ieee_function_args (se, expr, args, 2);
9883 1.1 mrg
9884 1.1 mrg /* If arguments have unequal size, convert them to the larger. */
9885 1.1 mrg if (TYPE_PRECISION (TREE_TYPE (args[0]))
9886 1.1 mrg > TYPE_PRECISION (TREE_TYPE (args[1])))
9887 1.1 mrg args[1] = fold_convert (TREE_TYPE (args[0]), args[1]);
9888 1.1 mrg else if (TYPE_PRECISION (TREE_TYPE (args[1]))
9889 1.1 mrg > TYPE_PRECISION (TREE_TYPE (args[0])))
9890 1.1 mrg args[0] = fold_convert (TREE_TYPE (args[1]), args[0]);
9891 1.1 mrg
9892 1.1 mrg argprec = TYPE_PRECISION (TREE_TYPE (args[0]));
9893 1.1 mrg decl = builtin_decl_for_precision (BUILT_IN_REMAINDER, argprec);
9894 1.1 mrg
9895 1.1 mrg /* Save floating-point state. */
9896 1.1 mrg fpstate = gfc_save_fp_state (&se->pre);
9897 1.1 mrg
9898 1.1 mrg /* Make the function call. */
9899 1.1 mrg call = build_call_expr_loc_array (input_location, decl, 2, args);
9900 1.1 mrg se->expr = fold_convert (TREE_TYPE (args[0]), call);
9901 1.1 mrg
9902 1.1 mrg /* Restore floating-point state. */
9903 1.1 mrg gfc_restore_fp_state (&se->post, fpstate);
9904 1.1 mrg }
9905 1.1 mrg
9906 1.1 mrg
9907 1.1 mrg /* Generate code for IEEE_NEXT_AFTER. */
9908 1.1 mrg
9909 1.1 mrg static void
9910 1.1 mrg conv_intrinsic_ieee_next_after (gfc_se * se, gfc_expr * expr)
9911 1.1 mrg {
9912 1.1 mrg tree args[2], decl, call, fpstate;
9913 1.1 mrg int argprec;
9914 1.1 mrg
9915 1.1 mrg conv_ieee_function_args (se, expr, args, 2);
9916 1.1 mrg
9917 1.1 mrg /* Result has the characteristics of first argument. */
9918 1.1 mrg args[1] = fold_convert (TREE_TYPE (args[0]), args[1]);
9919 1.1 mrg argprec = TYPE_PRECISION (TREE_TYPE (args[0]));
9920 1.1 mrg decl = builtin_decl_for_precision (BUILT_IN_NEXTAFTER, argprec);
9921 1.1 mrg
9922 1.1 mrg /* Save floating-point state. */
9923 1.1 mrg fpstate = gfc_save_fp_state (&se->pre);
9924 1.1 mrg
9925 1.1 mrg /* Make the function call. */
9926 1.1 mrg call = build_call_expr_loc_array (input_location, decl, 2, args);
9927 1.1 mrg se->expr = fold_convert (TREE_TYPE (args[0]), call);
9928 1.1 mrg
9929 1.1 mrg /* Restore floating-point state. */
9930 1.1 mrg gfc_restore_fp_state (&se->post, fpstate);
9931 1.1 mrg }
9932 1.1 mrg
9933 1.1 mrg
9934 1.1 mrg /* Generate code for IEEE_SCALB. */
9935 1.1 mrg
9936 1.1 mrg static void
9937 1.1 mrg conv_intrinsic_ieee_scalb (gfc_se * se, gfc_expr * expr)
9938 1.1 mrg {
9939 1.1 mrg tree args[2], decl, call, huge, type;
9940 1.1 mrg int argprec, n;
9941 1.1 mrg
9942 1.1 mrg conv_ieee_function_args (se, expr, args, 2);
9943 1.1 mrg
9944 1.1 mrg /* Result has the characteristics of first argument. */
9945 1.1 mrg argprec = TYPE_PRECISION (TREE_TYPE (args[0]));
9946 1.1 mrg decl = builtin_decl_for_precision (BUILT_IN_SCALBN, argprec);
9947 1.1 mrg
9948 1.1 mrg if (TYPE_PRECISION (TREE_TYPE (args[1])) > TYPE_PRECISION (integer_type_node))
9949 1.1 mrg {
9950 1.1 mrg /* We need to fold the integer into the range of a C int. */
9951 1.1 mrg args[1] = gfc_evaluate_now (args[1], &se->pre);
9952 1.1 mrg type = TREE_TYPE (args[1]);
9953 1.1 mrg
9954 1.1 mrg n = gfc_validate_kind (BT_INTEGER, gfc_c_int_kind, false);
9955 1.1 mrg huge = gfc_conv_mpz_to_tree (gfc_integer_kinds[n].huge,
9956 1.1 mrg gfc_c_int_kind);
9957 1.1 mrg huge = fold_convert (type, huge);
9958 1.1 mrg args[1] = fold_build2_loc (input_location, MIN_EXPR, type, args[1],
9959 1.1 mrg huge);
9960 1.1 mrg args[1] = fold_build2_loc (input_location, MAX_EXPR, type, args[1],
9961 1.1 mrg fold_build1_loc (input_location, NEGATE_EXPR,
9962 1.1 mrg type, huge));
9963 1.1 mrg }
9964 1.1 mrg
9965 1.1 mrg args[1] = fold_convert (integer_type_node, args[1]);
9966 1.1 mrg
9967 1.1 mrg /* Make the function call. */
9968 1.1 mrg call = build_call_expr_loc_array (input_location, decl, 2, args);
9969 1.1 mrg se->expr = fold_convert (TREE_TYPE (args[0]), call);
9970 1.1 mrg }
9971 1.1 mrg
9972 1.1 mrg
9973 1.1 mrg /* Generate code for IEEE_COPY_SIGN. */
9974 1.1 mrg
9975 1.1 mrg static void
9976 1.1 mrg conv_intrinsic_ieee_copy_sign (gfc_se * se, gfc_expr * expr)
9977 1.1 mrg {
9978 1.1 mrg tree args[2], decl, sign;
9979 1.1 mrg int argprec;
9980 1.1 mrg
9981 1.1 mrg conv_ieee_function_args (se, expr, args, 2);
9982 1.1 mrg
9983 1.1 mrg /* Get the sign of the second argument. */
9984 1.1 mrg sign = build_call_expr_loc (input_location,
9985 1.1 mrg builtin_decl_explicit (BUILT_IN_SIGNBIT),
9986 1.1 mrg 1, args[1]);
9987 1.1 mrg sign = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
9988 1.1 mrg sign, integer_zero_node);
9989 1.1 mrg
9990 1.1 mrg /* Create a value of one, with the right sign. */
9991 1.1 mrg sign = fold_build3_loc (input_location, COND_EXPR, integer_type_node,
9992 1.1 mrg sign,
9993 1.1 mrg fold_build1_loc (input_location, NEGATE_EXPR,
9994 1.1 mrg integer_type_node,
9995 1.1 mrg integer_one_node),
9996 1.1 mrg integer_one_node);
9997 1.1 mrg args[1] = fold_convert (TREE_TYPE (args[0]), sign);
9998 1.1 mrg
9999 1.1 mrg argprec = TYPE_PRECISION (TREE_TYPE (args[0]));
10000 1.1 mrg decl = builtin_decl_for_precision (BUILT_IN_COPYSIGN, argprec);
10001 1.1 mrg
10002 1.1 mrg se->expr = build_call_expr_loc_array (input_location, decl, 2, args);
10003 1.1 mrg }
10004 1.1 mrg
10005 1.1 mrg
10006 1.1 mrg /* Generate code for IEEE_CLASS. */
10007 1.1 mrg
10008 1.1 mrg static bool
10009 1.1 mrg conv_intrinsic_ieee_class (gfc_se *se, gfc_expr *expr)
10010 1.1 mrg {
10011 1.1 mrg tree arg, c, t1, t2, t3, t4;
10012 1.1 mrg
10013 1.1 mrg /* In GCC 12, handle inline only the powerpc64le-linux IEEE quad
10014 1.1 mrg real(kind=16) and nothing else. */
10015 1.1 mrg if (gfc_type_abi_kind (&expr->value.function.actual->expr->ts) != 17)
10016 1.1 mrg return false;
10017 1.1 mrg
10018 1.1 mrg /* Convert arg, evaluate it only once. */
10019 1.1 mrg conv_ieee_function_args (se, expr, &arg, 1);
10020 1.1 mrg arg = gfc_evaluate_now (arg, &se->pre);
10021 1.1 mrg
10022 1.1 mrg c = build_call_expr_loc (input_location,
10023 1.1 mrg builtin_decl_explicit (BUILT_IN_FPCLASSIFY), 6,
10024 1.1 mrg build_int_cst (integer_type_node, IEEE_QUIET_NAN),
10025 1.1 mrg build_int_cst (integer_type_node,
10026 1.1 mrg IEEE_POSITIVE_INF),
10027 1.1 mrg build_int_cst (integer_type_node,
10028 1.1 mrg IEEE_POSITIVE_NORMAL),
10029 1.1 mrg build_int_cst (integer_type_node,
10030 1.1 mrg IEEE_POSITIVE_DENORMAL),
10031 1.1 mrg build_int_cst (integer_type_node,
10032 1.1 mrg IEEE_POSITIVE_ZERO),
10033 1.1 mrg arg);
10034 1.1 mrg c = gfc_evaluate_now (c, &se->pre);
10035 1.1 mrg t1 = fold_build2_loc (input_location, EQ_EXPR, logical_type_node,
10036 1.1 mrg c, build_int_cst (integer_type_node,
10037 1.1 mrg IEEE_QUIET_NAN));
10038 1.1 mrg /* In GCC 12, we don't have __builtin_issignaling but above we made
10039 1.1 mrg sure arg is powerpc64le-linux IEEE quad real(kind=16).
10040 1.1 mrg When we check it is some kind of NaN by fpclassify, all we need
10041 1.1 mrg is check the ((__int128) 1) << 111 bit, if it is zero, it is a sNaN,
10042 1.1 mrg if it is set, it is a qNaN. */
10043 1.1 mrg t2 = fold_build1_loc (input_location, VIEW_CONVERT_EXPR,
10044 1.1 mrg build_nonstandard_integer_type (128, 1), arg);
10045 1.1 mrg t2 = fold_build2_loc (input_location, RSHIFT_EXPR, TREE_TYPE (t2), t2,
10046 1.1 mrg build_int_cst (integer_type_node, 111));
10047 1.1 mrg t2 = fold_convert (integer_type_node, t2);
10048 1.1 mrg t2 = fold_build2_loc (input_location, BIT_AND_EXPR, integer_type_node,
10049 1.1 mrg t2, integer_one_node);
10050 1.1 mrg t2 = fold_build2_loc (input_location, EQ_EXPR, logical_type_node,
10051 1.1 mrg t2, build_zero_cst (TREE_TYPE (t2)));
10052 1.1 mrg t1 = fold_build2_loc (input_location, TRUTH_AND_EXPR,
10053 1.1 mrg logical_type_node, t1, t2);
10054 1.1 mrg t3 = fold_build2_loc (input_location, GE_EXPR, logical_type_node,
10055 1.1 mrg c, build_int_cst (integer_type_node,
10056 1.1 mrg IEEE_POSITIVE_ZERO));
10057 1.1 mrg t4 = build_call_expr_loc (input_location,
10058 1.1 mrg builtin_decl_explicit (BUILT_IN_SIGNBIT), 1,
10059 1.1 mrg arg);
10060 1.1 mrg t4 = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
10061 1.1 mrg t4, build_zero_cst (TREE_TYPE (t4)));
10062 1.1 mrg t3 = fold_build2_loc (input_location, TRUTH_AND_EXPR,
10063 1.1 mrg logical_type_node, t3, t4);
10064 1.1 mrg int s = IEEE_NEGATIVE_ZERO + IEEE_POSITIVE_ZERO;
10065 1.1 mrg gcc_assert (IEEE_NEGATIVE_INF == s - IEEE_POSITIVE_INF);
10066 1.1 mrg gcc_assert (IEEE_NEGATIVE_NORMAL == s - IEEE_POSITIVE_NORMAL);
10067 1.1 mrg gcc_assert (IEEE_NEGATIVE_DENORMAL == s - IEEE_POSITIVE_DENORMAL);
10068 1.1 mrg gcc_assert (IEEE_NEGATIVE_SUBNORMAL == s - IEEE_POSITIVE_SUBNORMAL);
10069 1.1 mrg gcc_assert (IEEE_NEGATIVE_ZERO == s - IEEE_POSITIVE_ZERO);
10070 1.1 mrg t4 = fold_build2_loc (input_location, MINUS_EXPR, TREE_TYPE (c),
10071 1.1 mrg build_int_cst (TREE_TYPE (c), s), c);
10072 1.1 mrg t3 = fold_build3_loc (input_location, COND_EXPR, TREE_TYPE (c),
10073 1.1 mrg t3, t4, c);
10074 1.1 mrg t1 = fold_build3_loc (input_location, COND_EXPR, TREE_TYPE (c), t1,
10075 1.1 mrg build_int_cst (TREE_TYPE (c), IEEE_SIGNALING_NAN),
10076 1.1 mrg t3);
10077 1.1 mrg tree type = gfc_typenode_for_spec (&expr->ts);
10078 1.1 mrg /* Perform a quick sanity check that the return type is
10079 1.1 mrg IEEE_CLASS_TYPE derived type defined in
10080 1.1 mrg libgfortran/ieee/ieee_arithmetic.F90
10081 1.1 mrg Primarily check that it is a derived type with a single
10082 1.1 mrg member in it. */
10083 1.1 mrg gcc_assert (TREE_CODE (type) == RECORD_TYPE);
10084 1.1 mrg tree field = NULL_TREE;
10085 1.1 mrg for (tree f = TYPE_FIELDS (type); f != NULL_TREE; f = DECL_CHAIN (f))
10086 1.1 mrg if (TREE_CODE (f) == FIELD_DECL)
10087 1.1 mrg {
10088 1.1 mrg gcc_assert (field == NULL_TREE);
10089 1.1 mrg field = f;
10090 1.1 mrg }
10091 1.1 mrg gcc_assert (field);
10092 1.1 mrg t1 = fold_convert (TREE_TYPE (field), t1);
10093 1.1 mrg se->expr = build_constructor_single (type, field, t1);
10094 1.1 mrg return true;
10095 1.1 mrg }
10096 1.1 mrg
10097 1.1 mrg
10098 1.1 mrg /* Generate code for IEEE_VALUE. */
10099 1.1 mrg
10100 1.1 mrg static bool
10101 1.1 mrg conv_intrinsic_ieee_value (gfc_se *se, gfc_expr *expr)
10102 1.1 mrg {
10103 1.1 mrg tree args[2], arg, ret, tmp;
10104 1.1 mrg stmtblock_t body;
10105 1.1 mrg
10106 1.1 mrg /* In GCC 12, handle inline only the powerpc64le-linux IEEE quad
10107 1.1 mrg real(kind=16) and nothing else. */
10108 1.1 mrg if (gfc_type_abi_kind (&expr->ts) != 17)
10109 1.1 mrg return false;
10110 1.1 mrg
10111 1.1 mrg /* Convert args, evaluate the second one only once. */
10112 1.1 mrg conv_ieee_function_args (se, expr, args, 2);
10113 1.1 mrg arg = gfc_evaluate_now (args[1], &se->pre);
10114 1.1 mrg
10115 1.1 mrg tree type = TREE_TYPE (arg);
10116 1.1 mrg /* Perform a quick sanity check that the second argument's type is
10117 1.1 mrg IEEE_CLASS_TYPE derived type defined in
10118 1.1 mrg libgfortran/ieee/ieee_arithmetic.F90
10119 1.1 mrg Primarily check that it is a derived type with a single
10120 1.1 mrg member in it. */
10121 1.1 mrg gcc_assert (TREE_CODE (type) == RECORD_TYPE);
10122 1.1 mrg tree field = NULL_TREE;
10123 1.1 mrg for (tree f = TYPE_FIELDS (type); f != NULL_TREE; f = DECL_CHAIN (f))
10124 1.1 mrg if (TREE_CODE (f) == FIELD_DECL)
10125 1.1 mrg {
10126 1.1 mrg gcc_assert (field == NULL_TREE);
10127 1.1 mrg field = f;
10128 1.1 mrg }
10129 1.1 mrg gcc_assert (field);
10130 1.1 mrg arg = fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (field),
10131 1.1 mrg arg, field, NULL_TREE);
10132 1.1 mrg arg = gfc_evaluate_now (arg, &se->pre);
10133 1.1 mrg
10134 1.1 mrg type = gfc_typenode_for_spec (&expr->ts);
10135 1.1 mrg gcc_assert (TREE_CODE (type) == REAL_TYPE);
10136 1.1 mrg ret = gfc_create_var (type, NULL);
10137 1.1 mrg
10138 1.1 mrg gfc_init_block (&body);
10139 1.1 mrg
10140 1.1 mrg tree end_label = gfc_build_label_decl (NULL_TREE);
10141 1.1 mrg for (int c = IEEE_SIGNALING_NAN; c <= IEEE_POSITIVE_INF; ++c)
10142 1.1 mrg {
10143 1.1 mrg tree label = gfc_build_label_decl (NULL_TREE);
10144 1.1 mrg tree low = build_int_cst (TREE_TYPE (arg), c);
10145 1.1 mrg tmp = build_case_label (low, low, label);
10146 1.1 mrg gfc_add_expr_to_block (&body, tmp);
10147 1.1 mrg
10148 1.1 mrg REAL_VALUE_TYPE real;
10149 1.1 mrg int k;
10150 1.1 mrg switch (c)
10151 1.1 mrg {
10152 1.1 mrg case IEEE_SIGNALING_NAN:
10153 1.1 mrg real_nan (&real, "", 0, TYPE_MODE (type));
10154 1.1 mrg break;
10155 1.1 mrg case IEEE_QUIET_NAN:
10156 1.1 mrg real_nan (&real, "", 1, TYPE_MODE (type));
10157 1.1 mrg break;
10158 1.1 mrg case IEEE_NEGATIVE_INF:
10159 1.1 mrg real_inf (&real);
10160 1.1 mrg real = real_value_negate (&real);
10161 1.1 mrg break;
10162 1.1 mrg case IEEE_NEGATIVE_NORMAL:
10163 1.1 mrg real_from_integer (&real, TYPE_MODE (type), -42, SIGNED);
10164 1.1 mrg break;
10165 1.1 mrg case IEEE_NEGATIVE_DENORMAL:
10166 1.1 mrg k = gfc_validate_kind (BT_REAL, expr->ts.kind, false);
10167 1.1 mrg real_from_mpfr (&real, gfc_real_kinds[k].tiny,
10168 1.1 mrg type, GFC_RND_MODE);
10169 1.1 mrg real_arithmetic (&real, RDIV_EXPR, &real, &dconst2);
10170 1.1 mrg real = real_value_negate (&real);
10171 1.1 mrg break;
10172 1.1 mrg case IEEE_NEGATIVE_ZERO:
10173 1.1 mrg real_from_integer (&real, TYPE_MODE (type), 0, SIGNED);
10174 1.1 mrg real = real_value_negate (&real);
10175 1.1 mrg break;
10176 1.1 mrg case IEEE_POSITIVE_ZERO:
10177 1.1 mrg /* Make this also the default: label. The other possibility
10178 1.1 mrg would be to add a separate default: label followed by
10179 1.1 mrg __builtin_unreachable (). */
10180 1.1 mrg label = gfc_build_label_decl (NULL_TREE);
10181 1.1 mrg tmp = build_case_label (NULL_TREE, NULL_TREE, label);
10182 1.1 mrg gfc_add_expr_to_block (&body, tmp);
10183 1.1 mrg real_from_integer (&real, TYPE_MODE (type), 0, SIGNED);
10184 1.1 mrg break;
10185 1.1 mrg case IEEE_POSITIVE_DENORMAL:
10186 1.1 mrg k = gfc_validate_kind (BT_REAL, expr->ts.kind, false);
10187 1.1 mrg real_from_mpfr (&real, gfc_real_kinds[k].tiny,
10188 1.1 mrg type, GFC_RND_MODE);
10189 1.1 mrg real_arithmetic (&real, RDIV_EXPR, &real, &dconst2);
10190 1.1 mrg break;
10191 1.1 mrg case IEEE_POSITIVE_NORMAL:
10192 1.1 mrg real_from_integer (&real, TYPE_MODE (type), 42, SIGNED);
10193 1.1 mrg break;
10194 1.1 mrg case IEEE_POSITIVE_INF:
10195 1.1 mrg real_inf (&real);
10196 1.1 mrg break;
10197 1.1 mrg default:
10198 1.1 mrg gcc_unreachable ();
10199 1.1 mrg }
10200 1.1 mrg
10201 1.1 mrg tree val = build_real (type, real);
10202 1.1 mrg gfc_add_modify (&body, ret, val);
10203 1.1 mrg
10204 1.1 mrg tmp = build1_v (GOTO_EXPR, end_label);
10205 1.1 mrg gfc_add_expr_to_block (&body, tmp);
10206 1.1 mrg }
10207 1.1 mrg
10208 1.1 mrg tmp = gfc_finish_block (&body);
10209 1.1 mrg tmp = fold_build2_loc (input_location, SWITCH_EXPR, NULL_TREE, arg, tmp);
10210 1.1 mrg gfc_add_expr_to_block (&se->pre, tmp);
10211 1.1 mrg
10212 1.1 mrg tmp = build1_v (LABEL_EXPR, end_label);
10213 1.1 mrg gfc_add_expr_to_block (&se->pre, tmp);
10214 1.1 mrg
10215 1.1 mrg se->expr = ret;
10216 1.1 mrg return true;
10217 1.1 mrg }
10218 1.1 mrg
10219 1.1 mrg
10220 1.1 mrg /* Generate code for an intrinsic function from the IEEE_ARITHMETIC
10221 1.1 mrg module. */
10222 1.1 mrg
10223 1.1 mrg bool
10224 1.1 mrg gfc_conv_ieee_arithmetic_function (gfc_se * se, gfc_expr * expr)
10225 1.1 mrg {
10226 1.1 mrg const char *name = expr->value.function.name;
10227 1.1 mrg
10228 1.1 mrg if (startswith (name, "_gfortran_ieee_is_nan"))
10229 1.1 mrg conv_intrinsic_ieee_builtin (se, expr, BUILT_IN_ISNAN, 1);
10230 1.1 mrg else if (startswith (name, "_gfortran_ieee_is_finite"))
10231 1.1 mrg conv_intrinsic_ieee_builtin (se, expr, BUILT_IN_ISFINITE, 1);
10232 1.1 mrg else if (startswith (name, "_gfortran_ieee_unordered"))
10233 1.1 mrg conv_intrinsic_ieee_builtin (se, expr, BUILT_IN_ISUNORDERED, 2);
10234 1.1 mrg else if (startswith (name, "_gfortran_ieee_is_normal"))
10235 1.1 mrg conv_intrinsic_ieee_is_normal (se, expr);
10236 1.1 mrg else if (startswith (name, "_gfortran_ieee_is_negative"))
10237 1.1 mrg conv_intrinsic_ieee_is_negative (se, expr);
10238 1.1 mrg else if (startswith (name, "_gfortran_ieee_copy_sign"))
10239 1.1 mrg conv_intrinsic_ieee_copy_sign (se, expr);
10240 1.1 mrg else if (startswith (name, "_gfortran_ieee_scalb"))
10241 1.1 mrg conv_intrinsic_ieee_scalb (se, expr);
10242 1.1 mrg else if (startswith (name, "_gfortran_ieee_next_after"))
10243 1.1 mrg conv_intrinsic_ieee_next_after (se, expr);
10244 1.1 mrg else if (startswith (name, "_gfortran_ieee_rem"))
10245 1.1 mrg conv_intrinsic_ieee_rem (se, expr);
10246 1.1 mrg else if (startswith (name, "_gfortran_ieee_logb"))
10247 1.1 mrg conv_intrinsic_ieee_logb_rint (se, expr, BUILT_IN_LOGB);
10248 1.1 mrg else if (startswith (name, "_gfortran_ieee_rint"))
10249 1.1 mrg conv_intrinsic_ieee_logb_rint (se, expr, BUILT_IN_RINT);
10250 1.1 mrg else if (startswith (name, "ieee_class_") && ISDIGIT (name[11]))
10251 1.1 mrg return conv_intrinsic_ieee_class (se, expr);
10252 1.1 mrg else if (startswith (name, "ieee_value_") && ISDIGIT (name[11]))
10253 1.1 mrg return conv_intrinsic_ieee_value (se, expr);
10254 1.1 mrg else
10255 1.1 mrg /* It is not among the functions we translate directly. We return
10256 1.1 mrg false, so a library function call is emitted. */
10257 1.1 mrg return false;
10258 1.1 mrg
10259 1.1 mrg return true;
10260 1.1 mrg }
10261 1.1 mrg
10262 1.1 mrg
10263 1.1 mrg /* Generate a direct call to malloc() for the MALLOC intrinsic. */
10264 1.1 mrg
10265 1.1 mrg static void
10266 1.1 mrg gfc_conv_intrinsic_malloc (gfc_se * se, gfc_expr * expr)
10267 1.1 mrg {
10268 1.1 mrg tree arg, res, restype;
10269 1.1 mrg
10270 1.1 mrg gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
10271 1.1 mrg arg = fold_convert (size_type_node, arg);
10272 1.1 mrg res = build_call_expr_loc (input_location,
10273 1.1 mrg builtin_decl_explicit (BUILT_IN_MALLOC), 1, arg);
10274 1.1 mrg restype = gfc_typenode_for_spec (&expr->ts);
10275 1.1 mrg se->expr = fold_convert (restype, res);
10276 1.1 mrg }
10277 1.1 mrg
10278 1.1 mrg
10279 1.1 mrg /* Generate code for an intrinsic function. Some map directly to library
10280 1.1 mrg calls, others get special handling. In some cases the name of the function
10281 1.1 mrg used depends on the type specifiers. */
10282 1.1 mrg
10283 1.1 mrg void
10284 1.1 mrg gfc_conv_intrinsic_function (gfc_se * se, gfc_expr * expr)
10285 1.1 mrg {
10286 1.1 mrg const char *name;
10287 1.1 mrg int lib, kind;
10288 1.1 mrg tree fndecl;
10289 1.1 mrg
10290 1.1 mrg name = &expr->value.function.name[2];
10291 1.1 mrg
10292 1.1 mrg if (expr->rank > 0)
10293 1.1 mrg {
10294 1.1 mrg lib = gfc_is_intrinsic_libcall (expr);
10295 1.1 mrg if (lib != 0)
10296 1.1 mrg {
10297 1.1 mrg if (lib == 1)
10298 1.1 mrg se->ignore_optional = 1;
10299 1.1 mrg
10300 1.1 mrg switch (expr->value.function.isym->id)
10301 1.1 mrg {
10302 1.1 mrg case GFC_ISYM_EOSHIFT:
10303 1.1 mrg case GFC_ISYM_PACK:
10304 1.1 mrg case GFC_ISYM_RESHAPE:
10305 1.1 mrg /* For all of those the first argument specifies the type and the
10306 1.1 mrg third is optional. */
10307 1.1 mrg conv_generic_with_optional_char_arg (se, expr, 1, 3);
10308 1.1 mrg break;
10309 1.1 mrg
10310 1.1 mrg case GFC_ISYM_FINDLOC:
10311 1.1 mrg gfc_conv_intrinsic_findloc (se, expr);
10312 1.1 mrg break;
10313 1.1 mrg
10314 1.1 mrg case GFC_ISYM_MINLOC:
10315 1.1 mrg gfc_conv_intrinsic_minmaxloc (se, expr, LT_EXPR);
10316 1.1 mrg break;
10317 1.1 mrg
10318 1.1 mrg case GFC_ISYM_MAXLOC:
10319 1.1 mrg gfc_conv_intrinsic_minmaxloc (se, expr, GT_EXPR);
10320 1.1 mrg break;
10321 1.1 mrg
10322 1.1 mrg default:
10323 1.1 mrg gfc_conv_intrinsic_funcall (se, expr);
10324 1.1 mrg break;
10325 1.1 mrg }
10326 1.1 mrg
10327 1.1 mrg return;
10328 1.1 mrg }
10329 1.1 mrg }
10330 1.1 mrg
10331 1.1 mrg switch (expr->value.function.isym->id)
10332 1.1 mrg {
10333 1.1 mrg case GFC_ISYM_NONE:
10334 1.1 mrg gcc_unreachable ();
10335 1.1 mrg
10336 1.1 mrg case GFC_ISYM_REPEAT:
10337 1.1 mrg gfc_conv_intrinsic_repeat (se, expr);
10338 1.1 mrg break;
10339 1.1 mrg
10340 1.1 mrg case GFC_ISYM_TRIM:
10341 1.1 mrg gfc_conv_intrinsic_trim (se, expr);
10342 1.1 mrg break;
10343 1.1 mrg
10344 1.1 mrg case GFC_ISYM_SC_KIND:
10345 1.1 mrg gfc_conv_intrinsic_sc_kind (se, expr);
10346 1.1 mrg break;
10347 1.1 mrg
10348 1.1 mrg case GFC_ISYM_SI_KIND:
10349 1.1 mrg gfc_conv_intrinsic_si_kind (se, expr);
10350 1.1 mrg break;
10351 1.1 mrg
10352 1.1 mrg case GFC_ISYM_SR_KIND:
10353 1.1 mrg gfc_conv_intrinsic_sr_kind (se, expr);
10354 1.1 mrg break;
10355 1.1 mrg
10356 1.1 mrg case GFC_ISYM_EXPONENT:
10357 1.1 mrg gfc_conv_intrinsic_exponent (se, expr);
10358 1.1 mrg break;
10359 1.1 mrg
10360 1.1 mrg case GFC_ISYM_SCAN:
10361 1.1 mrg kind = expr->value.function.actual->expr->ts.kind;
10362 1.1 mrg if (kind == 1)
10363 1.1 mrg fndecl = gfor_fndecl_string_scan;
10364 1.1 mrg else if (kind == 4)
10365 1.1 mrg fndecl = gfor_fndecl_string_scan_char4;
10366 1.1 mrg else
10367 1.1 mrg gcc_unreachable ();
10368 1.1 mrg
10369 1.1 mrg gfc_conv_intrinsic_index_scan_verify (se, expr, fndecl);
10370 1.1 mrg break;
10371 1.1 mrg
10372 1.1 mrg case GFC_ISYM_VERIFY:
10373 1.1 mrg kind = expr->value.function.actual->expr->ts.kind;
10374 1.1 mrg if (kind == 1)
10375 1.1 mrg fndecl = gfor_fndecl_string_verify;
10376 1.1 mrg else if (kind == 4)
10377 1.1 mrg fndecl = gfor_fndecl_string_verify_char4;
10378 1.1 mrg else
10379 1.1 mrg gcc_unreachable ();
10380 1.1 mrg
10381 1.1 mrg gfc_conv_intrinsic_index_scan_verify (se, expr, fndecl);
10382 1.1 mrg break;
10383 1.1 mrg
10384 1.1 mrg case GFC_ISYM_ALLOCATED:
10385 1.1 mrg gfc_conv_allocated (se, expr);
10386 1.1 mrg break;
10387 1.1 mrg
10388 1.1 mrg case GFC_ISYM_ASSOCIATED:
10389 1.1 mrg gfc_conv_associated(se, expr);
10390 1.1 mrg break;
10391 1.1 mrg
10392 1.1 mrg case GFC_ISYM_SAME_TYPE_AS:
10393 1.1 mrg gfc_conv_same_type_as (se, expr);
10394 1.1 mrg break;
10395 1.1 mrg
10396 1.1 mrg case GFC_ISYM_ABS:
10397 1.1 mrg gfc_conv_intrinsic_abs (se, expr);
10398 1.1 mrg break;
10399 1.1 mrg
10400 1.1 mrg case GFC_ISYM_ADJUSTL:
10401 1.1 mrg if (expr->ts.kind == 1)
10402 1.1 mrg fndecl = gfor_fndecl_adjustl;
10403 1.1 mrg else if (expr->ts.kind == 4)
10404 1.1 mrg fndecl = gfor_fndecl_adjustl_char4;
10405 1.1 mrg else
10406 1.1 mrg gcc_unreachable ();
10407 1.1 mrg
10408 1.1 mrg gfc_conv_intrinsic_adjust (se, expr, fndecl);
10409 1.1 mrg break;
10410 1.1 mrg
10411 1.1 mrg case GFC_ISYM_ADJUSTR:
10412 1.1 mrg if (expr->ts.kind == 1)
10413 1.1 mrg fndecl = gfor_fndecl_adjustr;
10414 1.1 mrg else if (expr->ts.kind == 4)
10415 1.1 mrg fndecl = gfor_fndecl_adjustr_char4;
10416 1.1 mrg else
10417 1.1 mrg gcc_unreachable ();
10418 1.1 mrg
10419 1.1 mrg gfc_conv_intrinsic_adjust (se, expr, fndecl);
10420 1.1 mrg break;
10421 1.1 mrg
10422 1.1 mrg case GFC_ISYM_AIMAG:
10423 1.1 mrg gfc_conv_intrinsic_imagpart (se, expr);
10424 1.1 mrg break;
10425 1.1 mrg
10426 1.1 mrg case GFC_ISYM_AINT:
10427 1.1 mrg gfc_conv_intrinsic_aint (se, expr, RND_TRUNC);
10428 1.1 mrg break;
10429 1.1 mrg
10430 1.1 mrg case GFC_ISYM_ALL:
10431 1.1 mrg gfc_conv_intrinsic_anyall (se, expr, EQ_EXPR);
10432 1.1 mrg break;
10433 1.1 mrg
10434 1.1 mrg case GFC_ISYM_ANINT:
10435 1.1 mrg gfc_conv_intrinsic_aint (se, expr, RND_ROUND);
10436 1.1 mrg break;
10437 1.1 mrg
10438 1.1 mrg case GFC_ISYM_AND:
10439 1.1 mrg gfc_conv_intrinsic_bitop (se, expr, BIT_AND_EXPR);
10440 1.1 mrg break;
10441 1.1 mrg
10442 1.1 mrg case GFC_ISYM_ANY:
10443 1.1 mrg gfc_conv_intrinsic_anyall (se, expr, NE_EXPR);
10444 1.1 mrg break;
10445 1.1 mrg
10446 1.1 mrg case GFC_ISYM_ACOSD:
10447 1.1 mrg case GFC_ISYM_ASIND:
10448 1.1 mrg case GFC_ISYM_ATAND:
10449 1.1 mrg gfc_conv_intrinsic_atrigd (se, expr, expr->value.function.isym->id);
10450 1.1 mrg break;
10451 1.1 mrg
10452 1.1 mrg case GFC_ISYM_COTAN:
10453 1.1 mrg gfc_conv_intrinsic_cotan (se, expr);
10454 1.1 mrg break;
10455 1.1 mrg
10456 1.1 mrg case GFC_ISYM_COTAND:
10457 1.1 mrg gfc_conv_intrinsic_cotand (se, expr);
10458 1.1 mrg break;
10459 1.1 mrg
10460 1.1 mrg case GFC_ISYM_ATAN2D:
10461 1.1 mrg gfc_conv_intrinsic_atan2d (se, expr);
10462 1.1 mrg break;
10463 1.1 mrg
10464 1.1 mrg case GFC_ISYM_BTEST:
10465 1.1 mrg gfc_conv_intrinsic_btest (se, expr);
10466 1.1 mrg break;
10467 1.1 mrg
10468 1.1 mrg case GFC_ISYM_BGE:
10469 1.1 mrg gfc_conv_intrinsic_bitcomp (se, expr, GE_EXPR);
10470 1.1 mrg break;
10471 1.1 mrg
10472 1.1 mrg case GFC_ISYM_BGT:
10473 1.1 mrg gfc_conv_intrinsic_bitcomp (se, expr, GT_EXPR);
10474 1.1 mrg break;
10475 1.1 mrg
10476 1.1 mrg case GFC_ISYM_BLE:
10477 1.1 mrg gfc_conv_intrinsic_bitcomp (se, expr, LE_EXPR);
10478 1.1 mrg break;
10479 1.1 mrg
10480 1.1 mrg case GFC_ISYM_BLT:
10481 1.1 mrg gfc_conv_intrinsic_bitcomp (se, expr, LT_EXPR);
10482 1.1 mrg break;
10483 1.1 mrg
10484 1.1 mrg case GFC_ISYM_C_ASSOCIATED:
10485 1.1 mrg case GFC_ISYM_C_FUNLOC:
10486 1.1 mrg case GFC_ISYM_C_LOC:
10487 1.1 mrg conv_isocbinding_function (se, expr);
10488 1.1 mrg break;
10489 1.1 mrg
10490 1.1 mrg case GFC_ISYM_ACHAR:
10491 1.1 mrg case GFC_ISYM_CHAR:
10492 1.1 mrg gfc_conv_intrinsic_char (se, expr);
10493 1.1 mrg break;
10494 1.1 mrg
10495 1.1 mrg case GFC_ISYM_CONVERSION:
10496 1.1 mrg case GFC_ISYM_DBLE:
10497 1.1 mrg case GFC_ISYM_DFLOAT:
10498 1.1 mrg case GFC_ISYM_FLOAT:
10499 1.1 mrg case GFC_ISYM_LOGICAL:
10500 1.1 mrg case GFC_ISYM_REAL:
10501 1.1 mrg case GFC_ISYM_REALPART:
10502 1.1 mrg case GFC_ISYM_SNGL:
10503 1.1 mrg gfc_conv_intrinsic_conversion (se, expr);
10504 1.1 mrg break;
10505 1.1 mrg
10506 1.1 mrg /* Integer conversions are handled separately to make sure we get the
10507 1.1 mrg correct rounding mode. */
10508 1.1 mrg case GFC_ISYM_INT:
10509 1.1 mrg case GFC_ISYM_INT2:
10510 1.1 mrg case GFC_ISYM_INT8:
10511 1.1 mrg case GFC_ISYM_LONG:
10512 1.1 mrg gfc_conv_intrinsic_int (se, expr, RND_TRUNC);
10513 1.1 mrg break;
10514 1.1 mrg
10515 1.1 mrg case GFC_ISYM_NINT:
10516 1.1 mrg gfc_conv_intrinsic_int (se, expr, RND_ROUND);
10517 1.1 mrg break;
10518 1.1 mrg
10519 1.1 mrg case GFC_ISYM_CEILING:
10520 1.1 mrg gfc_conv_intrinsic_int (se, expr, RND_CEIL);
10521 1.1 mrg break;
10522 1.1 mrg
10523 1.1 mrg case GFC_ISYM_FLOOR:
10524 1.1 mrg gfc_conv_intrinsic_int (se, expr, RND_FLOOR);
10525 1.1 mrg break;
10526 1.1 mrg
10527 1.1 mrg case GFC_ISYM_MOD:
10528 1.1 mrg gfc_conv_intrinsic_mod (se, expr, 0);
10529 1.1 mrg break;
10530 1.1 mrg
10531 1.1 mrg case GFC_ISYM_MODULO:
10532 1.1 mrg gfc_conv_intrinsic_mod (se, expr, 1);
10533 1.1 mrg break;
10534 1.1 mrg
10535 1.1 mrg case GFC_ISYM_CAF_GET:
10536 1.1 mrg gfc_conv_intrinsic_caf_get (se, expr, NULL_TREE, NULL_TREE, NULL_TREE,
10537 1.1 mrg false, NULL);
10538 1.1 mrg break;
10539 1.1 mrg
10540 1.1 mrg case GFC_ISYM_CMPLX:
10541 1.1 mrg gfc_conv_intrinsic_cmplx (se, expr, name[5] == '1');
10542 1.1 mrg break;
10543 1.1 mrg
10544 1.1 mrg case GFC_ISYM_COMMAND_ARGUMENT_COUNT:
10545 1.1 mrg gfc_conv_intrinsic_iargc (se, expr);
10546 1.1 mrg break;
10547 1.1 mrg
10548 1.1 mrg case GFC_ISYM_COMPLEX:
10549 1.1 mrg gfc_conv_intrinsic_cmplx (se, expr, 1);
10550 1.1 mrg break;
10551 1.1 mrg
10552 1.1 mrg case GFC_ISYM_CONJG:
10553 1.1 mrg gfc_conv_intrinsic_conjg (se, expr);
10554 1.1 mrg break;
10555 1.1 mrg
10556 1.1 mrg case GFC_ISYM_COUNT:
10557 1.1 mrg gfc_conv_intrinsic_count (se, expr);
10558 1.1 mrg break;
10559 1.1 mrg
10560 1.1 mrg case GFC_ISYM_CTIME:
10561 1.1 mrg gfc_conv_intrinsic_ctime (se, expr);
10562 1.1 mrg break;
10563 1.1 mrg
10564 1.1 mrg case GFC_ISYM_DIM:
10565 1.1 mrg gfc_conv_intrinsic_dim (se, expr);
10566 1.1 mrg break;
10567 1.1 mrg
10568 1.1 mrg case GFC_ISYM_DOT_PRODUCT:
10569 1.1 mrg gfc_conv_intrinsic_dot_product (se, expr);
10570 1.1 mrg break;
10571 1.1 mrg
10572 1.1 mrg case GFC_ISYM_DPROD:
10573 1.1 mrg gfc_conv_intrinsic_dprod (se, expr);
10574 1.1 mrg break;
10575 1.1 mrg
10576 1.1 mrg case GFC_ISYM_DSHIFTL:
10577 1.1 mrg gfc_conv_intrinsic_dshift (se, expr, true);
10578 1.1 mrg break;
10579 1.1 mrg
10580 1.1 mrg case GFC_ISYM_DSHIFTR:
10581 1.1 mrg gfc_conv_intrinsic_dshift (se, expr, false);
10582 1.1 mrg break;
10583 1.1 mrg
10584 1.1 mrg case GFC_ISYM_FDATE:
10585 1.1 mrg gfc_conv_intrinsic_fdate (se, expr);
10586 1.1 mrg break;
10587 1.1 mrg
10588 1.1 mrg case GFC_ISYM_FRACTION:
10589 1.1 mrg gfc_conv_intrinsic_fraction (se, expr);
10590 1.1 mrg break;
10591 1.1 mrg
10592 1.1 mrg case GFC_ISYM_IALL:
10593 1.1 mrg gfc_conv_intrinsic_arith (se, expr, BIT_AND_EXPR, false);
10594 1.1 mrg break;
10595 1.1 mrg
10596 1.1 mrg case GFC_ISYM_IAND:
10597 1.1 mrg gfc_conv_intrinsic_bitop (se, expr, BIT_AND_EXPR);
10598 1.1 mrg break;
10599 1.1 mrg
10600 1.1 mrg case GFC_ISYM_IANY:
10601 1.1 mrg gfc_conv_intrinsic_arith (se, expr, BIT_IOR_EXPR, false);
10602 1.1 mrg break;
10603 1.1 mrg
10604 1.1 mrg case GFC_ISYM_IBCLR:
10605 1.1 mrg gfc_conv_intrinsic_singlebitop (se, expr, 0);
10606 1.1 mrg break;
10607 1.1 mrg
10608 1.1 mrg case GFC_ISYM_IBITS:
10609 1.1 mrg gfc_conv_intrinsic_ibits (se, expr);
10610 1.1 mrg break;
10611 1.1 mrg
10612 1.1 mrg case GFC_ISYM_IBSET:
10613 1.1 mrg gfc_conv_intrinsic_singlebitop (se, expr, 1);
10614 1.1 mrg break;
10615 1.1 mrg
10616 1.1 mrg case GFC_ISYM_IACHAR:
10617 1.1 mrg case GFC_ISYM_ICHAR:
10618 1.1 mrg /* We assume ASCII character sequence. */
10619 1.1 mrg gfc_conv_intrinsic_ichar (se, expr);
10620 1.1 mrg break;
10621 1.1 mrg
10622 1.1 mrg case GFC_ISYM_IARGC:
10623 1.1 mrg gfc_conv_intrinsic_iargc (se, expr);
10624 1.1 mrg break;
10625 1.1 mrg
10626 1.1 mrg case GFC_ISYM_IEOR:
10627 1.1 mrg gfc_conv_intrinsic_bitop (se, expr, BIT_XOR_EXPR);
10628 1.1 mrg break;
10629 1.1 mrg
10630 1.1 mrg case GFC_ISYM_INDEX:
10631 1.1 mrg kind = expr->value.function.actual->expr->ts.kind;
10632 1.1 mrg if (kind == 1)
10633 1.1 mrg fndecl = gfor_fndecl_string_index;
10634 1.1 mrg else if (kind == 4)
10635 1.1 mrg fndecl = gfor_fndecl_string_index_char4;
10636 1.1 mrg else
10637 1.1 mrg gcc_unreachable ();
10638 1.1 mrg
10639 1.1 mrg gfc_conv_intrinsic_index_scan_verify (se, expr, fndecl);
10640 1.1 mrg break;
10641 1.1 mrg
10642 1.1 mrg case GFC_ISYM_IOR:
10643 1.1 mrg gfc_conv_intrinsic_bitop (se, expr, BIT_IOR_EXPR);
10644 1.1 mrg break;
10645 1.1 mrg
10646 1.1 mrg case GFC_ISYM_IPARITY:
10647 1.1 mrg gfc_conv_intrinsic_arith (se, expr, BIT_XOR_EXPR, false);
10648 1.1 mrg break;
10649 1.1 mrg
10650 1.1 mrg case GFC_ISYM_IS_IOSTAT_END:
10651 1.1 mrg gfc_conv_has_intvalue (se, expr, LIBERROR_END);
10652 1.1 mrg break;
10653 1.1 mrg
10654 1.1 mrg case GFC_ISYM_IS_IOSTAT_EOR:
10655 1.1 mrg gfc_conv_has_intvalue (se, expr, LIBERROR_EOR);
10656 1.1 mrg break;
10657 1.1 mrg
10658 1.1 mrg case GFC_ISYM_IS_CONTIGUOUS:
10659 1.1 mrg gfc_conv_intrinsic_is_contiguous (se, expr);
10660 1.1 mrg break;
10661 1.1 mrg
10662 1.1 mrg case GFC_ISYM_ISNAN:
10663 1.1 mrg gfc_conv_intrinsic_isnan (se, expr);
10664 1.1 mrg break;
10665 1.1 mrg
10666 1.1 mrg case GFC_ISYM_KILL:
10667 1.1 mrg conv_intrinsic_kill (se, expr);
10668 1.1 mrg break;
10669 1.1 mrg
10670 1.1 mrg case GFC_ISYM_LSHIFT:
10671 1.1 mrg gfc_conv_intrinsic_shift (se, expr, false, false);
10672 1.1 mrg break;
10673 1.1 mrg
10674 1.1 mrg case GFC_ISYM_RSHIFT:
10675 1.1 mrg gfc_conv_intrinsic_shift (se, expr, true, true);
10676 1.1 mrg break;
10677 1.1 mrg
10678 1.1 mrg case GFC_ISYM_SHIFTA:
10679 1.1 mrg gfc_conv_intrinsic_shift (se, expr, true, true);
10680 1.1 mrg break;
10681 1.1 mrg
10682 1.1 mrg case GFC_ISYM_SHIFTL:
10683 1.1 mrg gfc_conv_intrinsic_shift (se, expr, false, false);
10684 1.1 mrg break;
10685 1.1 mrg
10686 1.1 mrg case GFC_ISYM_SHIFTR:
10687 1.1 mrg gfc_conv_intrinsic_shift (se, expr, true, false);
10688 1.1 mrg break;
10689 1.1 mrg
10690 1.1 mrg case GFC_ISYM_ISHFT:
10691 1.1 mrg gfc_conv_intrinsic_ishft (se, expr);
10692 1.1 mrg break;
10693 1.1 mrg
10694 1.1 mrg case GFC_ISYM_ISHFTC:
10695 1.1 mrg gfc_conv_intrinsic_ishftc (se, expr);
10696 1.1 mrg break;
10697 1.1 mrg
10698 1.1 mrg case GFC_ISYM_LEADZ:
10699 1.1 mrg gfc_conv_intrinsic_leadz (se, expr);
10700 1.1 mrg break;
10701 1.1 mrg
10702 1.1 mrg case GFC_ISYM_TRAILZ:
10703 1.1 mrg gfc_conv_intrinsic_trailz (se, expr);
10704 1.1 mrg break;
10705 1.1 mrg
10706 1.1 mrg case GFC_ISYM_POPCNT:
10707 1.1 mrg gfc_conv_intrinsic_popcnt_poppar (se, expr, 0);
10708 1.1 mrg break;
10709 1.1 mrg
10710 1.1 mrg case GFC_ISYM_POPPAR:
10711 1.1 mrg gfc_conv_intrinsic_popcnt_poppar (se, expr, 1);
10712 1.1 mrg break;
10713 1.1 mrg
10714 1.1 mrg case GFC_ISYM_LBOUND:
10715 1.1 mrg gfc_conv_intrinsic_bound (se, expr, GFC_ISYM_LBOUND);
10716 1.1 mrg break;
10717 1.1 mrg
10718 1.1 mrg case GFC_ISYM_LCOBOUND:
10719 1.1 mrg conv_intrinsic_cobound (se, expr);
10720 1.1 mrg break;
10721 1.1 mrg
10722 1.1 mrg case GFC_ISYM_TRANSPOSE:
10723 1.1 mrg /* The scalarizer has already been set up for reversed dimension access
10724 1.1 mrg order ; now we just get the argument value normally. */
10725 1.1 mrg gfc_conv_expr (se, expr->value.function.actual->expr);
10726 1.1 mrg break;
10727 1.1 mrg
10728 1.1 mrg case GFC_ISYM_LEN:
10729 1.1 mrg gfc_conv_intrinsic_len (se, expr);
10730 1.1 mrg break;
10731 1.1 mrg
10732 1.1 mrg case GFC_ISYM_LEN_TRIM:
10733 1.1 mrg gfc_conv_intrinsic_len_trim (se, expr);
10734 1.1 mrg break;
10735 1.1 mrg
10736 1.1 mrg case GFC_ISYM_LGE:
10737 1.1 mrg gfc_conv_intrinsic_strcmp (se, expr, GE_EXPR);
10738 1.1 mrg break;
10739 1.1 mrg
10740 1.1 mrg case GFC_ISYM_LGT:
10741 1.1 mrg gfc_conv_intrinsic_strcmp (se, expr, GT_EXPR);
10742 1.1 mrg break;
10743 1.1 mrg
10744 1.1 mrg case GFC_ISYM_LLE:
10745 1.1 mrg gfc_conv_intrinsic_strcmp (se, expr, LE_EXPR);
10746 1.1 mrg break;
10747 1.1 mrg
10748 1.1 mrg case GFC_ISYM_LLT:
10749 1.1 mrg gfc_conv_intrinsic_strcmp (se, expr, LT_EXPR);
10750 1.1 mrg break;
10751 1.1 mrg
10752 1.1 mrg case GFC_ISYM_MALLOC:
10753 1.1 mrg gfc_conv_intrinsic_malloc (se, expr);
10754 1.1 mrg break;
10755 1.1 mrg
10756 1.1 mrg case GFC_ISYM_MASKL:
10757 1.1 mrg gfc_conv_intrinsic_mask (se, expr, 1);
10758 1.1 mrg break;
10759 1.1 mrg
10760 1.1 mrg case GFC_ISYM_MASKR:
10761 1.1 mrg gfc_conv_intrinsic_mask (se, expr, 0);
10762 1.1 mrg break;
10763 1.1 mrg
10764 1.1 mrg case GFC_ISYM_MAX:
10765 1.1 mrg if (expr->ts.type == BT_CHARACTER)
10766 1.1 mrg gfc_conv_intrinsic_minmax_char (se, expr, 1);
10767 1.1 mrg else
10768 1.1 mrg gfc_conv_intrinsic_minmax (se, expr, GT_EXPR);
10769 1.1 mrg break;
10770 1.1 mrg
10771 1.1 mrg case GFC_ISYM_MAXLOC:
10772 1.1 mrg gfc_conv_intrinsic_minmaxloc (se, expr, GT_EXPR);
10773 1.1 mrg break;
10774 1.1 mrg
10775 1.1 mrg case GFC_ISYM_FINDLOC:
10776 1.1 mrg gfc_conv_intrinsic_findloc (se, expr);
10777 1.1 mrg break;
10778 1.1 mrg
10779 1.1 mrg case GFC_ISYM_MAXVAL:
10780 1.1 mrg gfc_conv_intrinsic_minmaxval (se, expr, GT_EXPR);
10781 1.1 mrg break;
10782 1.1 mrg
10783 1.1 mrg case GFC_ISYM_MERGE:
10784 1.1 mrg gfc_conv_intrinsic_merge (se, expr);
10785 1.1 mrg break;
10786 1.1 mrg
10787 1.1 mrg case GFC_ISYM_MERGE_BITS:
10788 1.1 mrg gfc_conv_intrinsic_merge_bits (se, expr);
10789 1.1 mrg break;
10790 1.1 mrg
10791 1.1 mrg case GFC_ISYM_MIN:
10792 1.1 mrg if (expr->ts.type == BT_CHARACTER)
10793 1.1 mrg gfc_conv_intrinsic_minmax_char (se, expr, -1);
10794 1.1 mrg else
10795 1.1 mrg gfc_conv_intrinsic_minmax (se, expr, LT_EXPR);
10796 1.1 mrg break;
10797 1.1 mrg
10798 1.1 mrg case GFC_ISYM_MINLOC:
10799 1.1 mrg gfc_conv_intrinsic_minmaxloc (se, expr, LT_EXPR);
10800 1.1 mrg break;
10801 1.1 mrg
10802 1.1 mrg case GFC_ISYM_MINVAL:
10803 1.1 mrg gfc_conv_intrinsic_minmaxval (se, expr, LT_EXPR);
10804 1.1 mrg break;
10805 1.1 mrg
10806 1.1 mrg case GFC_ISYM_NEAREST:
10807 1.1 mrg gfc_conv_intrinsic_nearest (se, expr);
10808 1.1 mrg break;
10809 1.1 mrg
10810 1.1 mrg case GFC_ISYM_NORM2:
10811 1.1 mrg gfc_conv_intrinsic_arith (se, expr, PLUS_EXPR, true);
10812 1.1 mrg break;
10813 1.1 mrg
10814 1.1 mrg case GFC_ISYM_NOT:
10815 1.1 mrg gfc_conv_intrinsic_not (se, expr);
10816 1.1 mrg break;
10817 1.1 mrg
10818 1.1 mrg case GFC_ISYM_OR:
10819 1.1 mrg gfc_conv_intrinsic_bitop (se, expr, BIT_IOR_EXPR);
10820 1.1 mrg break;
10821 1.1 mrg
10822 1.1 mrg case GFC_ISYM_PARITY:
10823 1.1 mrg gfc_conv_intrinsic_arith (se, expr, NE_EXPR, false);
10824 1.1 mrg break;
10825 1.1 mrg
10826 1.1 mrg case GFC_ISYM_PRESENT:
10827 1.1 mrg gfc_conv_intrinsic_present (se, expr);
10828 1.1 mrg break;
10829 1.1 mrg
10830 1.1 mrg case GFC_ISYM_PRODUCT:
10831 1.1 mrg gfc_conv_intrinsic_arith (se, expr, MULT_EXPR, false);
10832 1.1 mrg break;
10833 1.1 mrg
10834 1.1 mrg case GFC_ISYM_RANK:
10835 1.1 mrg gfc_conv_intrinsic_rank (se, expr);
10836 1.1 mrg break;
10837 1.1 mrg
10838 1.1 mrg case GFC_ISYM_RRSPACING:
10839 1.1 mrg gfc_conv_intrinsic_rrspacing (se, expr);
10840 1.1 mrg break;
10841 1.1 mrg
10842 1.1 mrg case GFC_ISYM_SET_EXPONENT:
10843 1.1 mrg gfc_conv_intrinsic_set_exponent (se, expr);
10844 1.1 mrg break;
10845 1.1 mrg
10846 1.1 mrg case GFC_ISYM_SCALE:
10847 1.1 mrg gfc_conv_intrinsic_scale (se, expr);
10848 1.1 mrg break;
10849 1.1 mrg
10850 1.1 mrg case GFC_ISYM_SHAPE:
10851 1.1 mrg gfc_conv_intrinsic_bound (se, expr, GFC_ISYM_SHAPE);
10852 1.1 mrg break;
10853 1.1 mrg
10854 1.1 mrg case GFC_ISYM_SIGN:
10855 1.1 mrg gfc_conv_intrinsic_sign (se, expr);
10856 1.1 mrg break;
10857 1.1 mrg
10858 1.1 mrg case GFC_ISYM_SIZE:
10859 1.1 mrg gfc_conv_intrinsic_size (se, expr);
10860 1.1 mrg break;
10861 1.1 mrg
10862 1.1 mrg case GFC_ISYM_SIZEOF:
10863 1.1 mrg case GFC_ISYM_C_SIZEOF:
10864 1.1 mrg gfc_conv_intrinsic_sizeof (se, expr);
10865 1.1 mrg break;
10866 1.1 mrg
10867 1.1 mrg case GFC_ISYM_STORAGE_SIZE:
10868 1.1 mrg gfc_conv_intrinsic_storage_size (se, expr);
10869 1.1 mrg break;
10870 1.1 mrg
10871 1.1 mrg case GFC_ISYM_SPACING:
10872 1.1 mrg gfc_conv_intrinsic_spacing (se, expr);
10873 1.1 mrg break;
10874 1.1 mrg
10875 1.1 mrg case GFC_ISYM_STRIDE:
10876 1.1 mrg conv_intrinsic_stride (se, expr);
10877 1.1 mrg break;
10878 1.1 mrg
10879 1.1 mrg case GFC_ISYM_SUM:
10880 1.1 mrg gfc_conv_intrinsic_arith (se, expr, PLUS_EXPR, false);
10881 1.1 mrg break;
10882 1.1 mrg
10883 1.1 mrg case GFC_ISYM_TEAM_NUMBER:
10884 1.1 mrg conv_intrinsic_team_number (se, expr);
10885 1.1 mrg break;
10886 1.1 mrg
10887 1.1 mrg case GFC_ISYM_TRANSFER:
10888 1.1 mrg if (se->ss && se->ss->info->useflags)
10889 1.1 mrg /* Access the previously obtained result. */
10890 1.1 mrg gfc_conv_tmp_array_ref (se);
10891 1.1 mrg else
10892 1.1 mrg gfc_conv_intrinsic_transfer (se, expr);
10893 1.1 mrg break;
10894 1.1 mrg
10895 1.1 mrg case GFC_ISYM_TTYNAM:
10896 1.1 mrg gfc_conv_intrinsic_ttynam (se, expr);
10897 1.1 mrg break;
10898 1.1 mrg
10899 1.1 mrg case GFC_ISYM_UBOUND:
10900 1.1 mrg gfc_conv_intrinsic_bound (se, expr, GFC_ISYM_UBOUND);
10901 1.1 mrg break;
10902 1.1 mrg
10903 1.1 mrg case GFC_ISYM_UCOBOUND:
10904 1.1 mrg conv_intrinsic_cobound (se, expr);
10905 1.1 mrg break;
10906 1.1 mrg
10907 1.1 mrg case GFC_ISYM_XOR:
10908 1.1 mrg gfc_conv_intrinsic_bitop (se, expr, BIT_XOR_EXPR);
10909 1.1 mrg break;
10910 1.1 mrg
10911 1.1 mrg case GFC_ISYM_LOC:
10912 1.1 mrg gfc_conv_intrinsic_loc (se, expr);
10913 1.1 mrg break;
10914 1.1 mrg
10915 1.1 mrg case GFC_ISYM_THIS_IMAGE:
10916 1.1 mrg /* For num_images() == 1, handle as LCOBOUND. */
10917 1.1 mrg if (expr->value.function.actual->expr
10918 1.1 mrg && flag_coarray == GFC_FCOARRAY_SINGLE)
10919 1.1 mrg conv_intrinsic_cobound (se, expr);
10920 1.1 mrg else
10921 1.1 mrg trans_this_image (se, expr);
10922 1.1 mrg break;
10923 1.1 mrg
10924 1.1 mrg case GFC_ISYM_IMAGE_INDEX:
10925 1.1 mrg trans_image_index (se, expr);
10926 1.1 mrg break;
10927 1.1 mrg
10928 1.1 mrg case GFC_ISYM_IMAGE_STATUS:
10929 1.1 mrg conv_intrinsic_image_status (se, expr);
10930 1.1 mrg break;
10931 1.1 mrg
10932 1.1 mrg case GFC_ISYM_NUM_IMAGES:
10933 1.1 mrg trans_num_images (se, expr);
10934 1.1 mrg break;
10935 1.1 mrg
10936 1.1 mrg case GFC_ISYM_ACCESS:
10937 1.1 mrg case GFC_ISYM_CHDIR:
10938 1.1 mrg case GFC_ISYM_CHMOD:
10939 1.1 mrg case GFC_ISYM_DTIME:
10940 1.1 mrg case GFC_ISYM_ETIME:
10941 1.1 mrg case GFC_ISYM_EXTENDS_TYPE_OF:
10942 1.1 mrg case GFC_ISYM_FGET:
10943 1.1 mrg case GFC_ISYM_FGETC:
10944 1.1 mrg case GFC_ISYM_FNUM:
10945 1.1 mrg case GFC_ISYM_FPUT:
10946 1.1 mrg case GFC_ISYM_FPUTC:
10947 1.1 mrg case GFC_ISYM_FSTAT:
10948 1.1 mrg case GFC_ISYM_FTELL:
10949 1.1 mrg case GFC_ISYM_GETCWD:
10950 1.1 mrg case GFC_ISYM_GETGID:
10951 1.1 mrg case GFC_ISYM_GETPID:
10952 1.1 mrg case GFC_ISYM_GETUID:
10953 1.1 mrg case GFC_ISYM_HOSTNM:
10954 1.1 mrg case GFC_ISYM_IERRNO:
10955 1.1 mrg case GFC_ISYM_IRAND:
10956 1.1 mrg case GFC_ISYM_ISATTY:
10957 1.1 mrg case GFC_ISYM_JN2:
10958 1.1 mrg case GFC_ISYM_LINK:
10959 1.1 mrg case GFC_ISYM_LSTAT:
10960 1.1 mrg case GFC_ISYM_MATMUL:
10961 1.1 mrg case GFC_ISYM_MCLOCK:
10962 1.1 mrg case GFC_ISYM_MCLOCK8:
10963 1.1 mrg case GFC_ISYM_RAND:
10964 1.1 mrg case GFC_ISYM_RENAME:
10965 1.1 mrg case GFC_ISYM_SECOND:
10966 1.1 mrg case GFC_ISYM_SECNDS:
10967 1.1 mrg case GFC_ISYM_SIGNAL:
10968 1.1 mrg case GFC_ISYM_STAT:
10969 1.1 mrg case GFC_ISYM_SYMLNK:
10970 1.1 mrg case GFC_ISYM_SYSTEM:
10971 1.1 mrg case GFC_ISYM_TIME:
10972 1.1 mrg case GFC_ISYM_TIME8:
10973 1.1 mrg case GFC_ISYM_UMASK:
10974 1.1 mrg case GFC_ISYM_UNLINK:
10975 1.1 mrg case GFC_ISYM_YN2:
10976 1.1 mrg gfc_conv_intrinsic_funcall (se, expr);
10977 1.1 mrg break;
10978 1.1 mrg
10979 1.1 mrg case GFC_ISYM_EOSHIFT:
10980 1.1 mrg case GFC_ISYM_PACK:
10981 1.1 mrg case GFC_ISYM_RESHAPE:
10982 1.1 mrg /* For those, expr->rank should always be >0 and thus the if above the
10983 1.1 mrg switch should have matched. */
10984 1.1 mrg gcc_unreachable ();
10985 1.1 mrg break;
10986 1.1 mrg
10987 1.1 mrg default:
10988 1.1 mrg gfc_conv_intrinsic_lib_function (se, expr);
10989 1.1 mrg break;
10990 1.1 mrg }
10991 1.1 mrg }
10992 1.1 mrg
10993 1.1 mrg
10994 1.1 mrg static gfc_ss *
10995 1.1 mrg walk_inline_intrinsic_transpose (gfc_ss *ss, gfc_expr *expr)
10996 1.1 mrg {
10997 1.1 mrg gfc_ss *arg_ss, *tmp_ss;
10998 1.1 mrg gfc_actual_arglist *arg;
10999 1.1 mrg
11000 1.1 mrg arg = expr->value.function.actual;
11001 1.1 mrg
11002 1.1 mrg gcc_assert (arg->expr);
11003 1.1 mrg
11004 1.1 mrg arg_ss = gfc_walk_subexpr (gfc_ss_terminator, arg->expr);
11005 1.1 mrg gcc_assert (arg_ss != gfc_ss_terminator);
11006 1.1 mrg
11007 1.1 mrg for (tmp_ss = arg_ss; ; tmp_ss = tmp_ss->next)
11008 1.1 mrg {
11009 1.1 mrg if (tmp_ss->info->type != GFC_SS_SCALAR
11010 1.1 mrg && tmp_ss->info->type != GFC_SS_REFERENCE)
11011 1.1 mrg {
11012 1.1 mrg gcc_assert (tmp_ss->dimen == 2);
11013 1.1 mrg
11014 1.1 mrg /* We just invert dimensions. */
11015 1.1 mrg std::swap (tmp_ss->dim[0], tmp_ss->dim[1]);
11016 1.1 mrg }
11017 1.1 mrg
11018 1.1 mrg /* Stop when tmp_ss points to the last valid element of the chain... */
11019 1.1 mrg if (tmp_ss->next == gfc_ss_terminator)
11020 1.1 mrg break;
11021 1.1 mrg }
11022 1.1 mrg
11023 1.1 mrg /* ... so that we can attach the rest of the chain to it. */
11024 1.1 mrg tmp_ss->next = ss;
11025 1.1 mrg
11026 1.1 mrg return arg_ss;
11027 1.1 mrg }
11028 1.1 mrg
11029 1.1 mrg
11030 1.1 mrg /* Move the given dimension of the given gfc_ss list to a nested gfc_ss list.
11031 1.1 mrg This has the side effect of reversing the nested list, so there is no
11032 1.1 mrg need to call gfc_reverse_ss on it (the given list is assumed not to be
11033 1.1 mrg reversed yet). */
11034 1.1 mrg
11035 1.1 mrg static gfc_ss *
11036 1.1 mrg nest_loop_dimension (gfc_ss *ss, int dim)
11037 1.1 mrg {
11038 1.1 mrg int ss_dim, i;
11039 1.1 mrg gfc_ss *new_ss, *prev_ss = gfc_ss_terminator;
11040 1.1 mrg gfc_loopinfo *new_loop;
11041 1.1 mrg
11042 1.1 mrg gcc_assert (ss != gfc_ss_terminator);
11043 1.1 mrg
11044 1.1 mrg for (; ss != gfc_ss_terminator; ss = ss->next)
11045 1.1 mrg {
11046 1.1 mrg new_ss = gfc_get_ss ();
11047 1.1 mrg new_ss->next = prev_ss;
11048 1.1 mrg new_ss->parent = ss;
11049 1.1 mrg new_ss->info = ss->info;
11050 1.1 mrg new_ss->info->refcount++;
11051 1.1 mrg if (ss->dimen != 0)
11052 1.1 mrg {
11053 1.1 mrg gcc_assert (ss->info->type != GFC_SS_SCALAR
11054 1.1 mrg && ss->info->type != GFC_SS_REFERENCE);
11055 1.1 mrg
11056 1.1 mrg new_ss->dimen = 1;
11057 1.1 mrg new_ss->dim[0] = ss->dim[dim];
11058 1.1 mrg
11059 1.1 mrg gcc_assert (dim < ss->dimen);
11060 1.1 mrg
11061 1.1 mrg ss_dim = --ss->dimen;
11062 1.1 mrg for (i = dim; i < ss_dim; i++)
11063 1.1 mrg ss->dim[i] = ss->dim[i + 1];
11064 1.1 mrg
11065 1.1 mrg ss->dim[ss_dim] = 0;
11066 1.1 mrg }
11067 1.1 mrg prev_ss = new_ss;
11068 1.1 mrg
11069 1.1 mrg if (ss->nested_ss)
11070 1.1 mrg {
11071 1.1 mrg ss->nested_ss->parent = new_ss;
11072 1.1 mrg new_ss->nested_ss = ss->nested_ss;
11073 1.1 mrg }
11074 1.1 mrg ss->nested_ss = new_ss;
11075 1.1 mrg }
11076 1.1 mrg
11077 1.1 mrg new_loop = gfc_get_loopinfo ();
11078 1.1 mrg gfc_init_loopinfo (new_loop);
11079 1.1 mrg
11080 1.1 mrg gcc_assert (prev_ss != NULL);
11081 1.1 mrg gcc_assert (prev_ss != gfc_ss_terminator);
11082 1.1 mrg gfc_add_ss_to_loop (new_loop, prev_ss);
11083 1.1 mrg return new_ss->parent;
11084 1.1 mrg }
11085 1.1 mrg
11086 1.1 mrg
11087 1.1 mrg /* Create the gfc_ss list for the SUM/PRODUCT arguments when the function
11088 1.1 mrg is to be inlined. */
11089 1.1 mrg
11090 1.1 mrg static gfc_ss *
11091 1.1 mrg walk_inline_intrinsic_arith (gfc_ss *ss, gfc_expr *expr)
11092 1.1 mrg {
11093 1.1 mrg gfc_ss *tmp_ss, *tail, *array_ss;
11094 1.1 mrg gfc_actual_arglist *arg1, *arg2, *arg3;
11095 1.1 mrg int sum_dim;
11096 1.1 mrg bool scalar_mask = false;
11097 1.1 mrg
11098 1.1 mrg /* The rank of the result will be determined later. */
11099 1.1 mrg arg1 = expr->value.function.actual;
11100 1.1 mrg arg2 = arg1->next;
11101 1.1 mrg arg3 = arg2->next;
11102 1.1 mrg gcc_assert (arg3 != NULL);
11103 1.1 mrg
11104 1.1 mrg if (expr->rank == 0)
11105 1.1 mrg return ss;
11106 1.1 mrg
11107 1.1 mrg tmp_ss = gfc_ss_terminator;
11108 1.1 mrg
11109 1.1 mrg if (arg3->expr)
11110 1.1 mrg {
11111 1.1 mrg gfc_ss *mask_ss;
11112 1.1 mrg
11113 1.1 mrg mask_ss = gfc_walk_subexpr (tmp_ss, arg3->expr);
11114 1.1 mrg if (mask_ss == tmp_ss)
11115 1.1 mrg scalar_mask = 1;
11116 1.1 mrg
11117 1.1 mrg tmp_ss = mask_ss;
11118 1.1 mrg }
11119 1.1 mrg
11120 1.1 mrg array_ss = gfc_walk_subexpr (tmp_ss, arg1->expr);
11121 1.1 mrg gcc_assert (array_ss != tmp_ss);
11122 1.1 mrg
11123 1.1 mrg /* Odd thing: If the mask is scalar, it is used by the frontend after
11124 1.1 mrg the array (to make an if around the nested loop). Thus it shall
11125 1.1 mrg be after array_ss once the gfc_ss list is reversed. */
11126 1.1 mrg if (scalar_mask)
11127 1.1 mrg tmp_ss = gfc_get_scalar_ss (array_ss, arg3->expr);
11128 1.1 mrg else
11129 1.1 mrg tmp_ss = array_ss;
11130 1.1 mrg
11131 1.1 mrg /* "Hide" the dimension on which we will sum in the first arg's scalarization
11132 1.1 mrg chain. */
11133 1.1 mrg sum_dim = mpz_get_si (arg2->expr->value.integer) - 1;
11134 1.1 mrg tail = nest_loop_dimension (tmp_ss, sum_dim);
11135 1.1 mrg tail->next = ss;
11136 1.1 mrg
11137 1.1 mrg return tmp_ss;
11138 1.1 mrg }
11139 1.1 mrg
11140 1.1 mrg
11141 1.1 mrg static gfc_ss *
11142 1.1 mrg walk_inline_intrinsic_function (gfc_ss * ss, gfc_expr * expr)
11143 1.1 mrg {
11144 1.1 mrg
11145 1.1 mrg switch (expr->value.function.isym->id)
11146 1.1 mrg {
11147 1.1 mrg case GFC_ISYM_PRODUCT:
11148 1.1 mrg case GFC_ISYM_SUM:
11149 1.1 mrg return walk_inline_intrinsic_arith (ss, expr);
11150 1.1 mrg
11151 1.1 mrg case GFC_ISYM_TRANSPOSE:
11152 1.1 mrg return walk_inline_intrinsic_transpose (ss, expr);
11153 1.1 mrg
11154 1.1 mrg default:
11155 1.1 mrg gcc_unreachable ();
11156 1.1 mrg }
11157 1.1 mrg gcc_unreachable ();
11158 1.1 mrg }
11159 1.1 mrg
11160 1.1 mrg
11161 1.1 mrg /* This generates code to execute before entering the scalarization loop.
11162 1.1 mrg Currently does nothing. */
11163 1.1 mrg
11164 1.1 mrg void
11165 1.1 mrg gfc_add_intrinsic_ss_code (gfc_loopinfo * loop ATTRIBUTE_UNUSED, gfc_ss * ss)
11166 1.1 mrg {
11167 1.1 mrg switch (ss->info->expr->value.function.isym->id)
11168 1.1 mrg {
11169 1.1 mrg case GFC_ISYM_UBOUND:
11170 1.1 mrg case GFC_ISYM_LBOUND:
11171 1.1 mrg case GFC_ISYM_UCOBOUND:
11172 1.1 mrg case GFC_ISYM_LCOBOUND:
11173 1.1 mrg case GFC_ISYM_THIS_IMAGE:
11174 1.1 mrg case GFC_ISYM_SHAPE:
11175 1.1 mrg break;
11176 1.1 mrg
11177 1.1 mrg default:
11178 1.1 mrg gcc_unreachable ();
11179 1.1 mrg }
11180 1.1 mrg }
11181 1.1 mrg
11182 1.1 mrg
11183 1.1 mrg /* The LBOUND, LCOBOUND, UBOUND, UCOBOUND, and SHAPE intrinsics with
11184 1.1 mrg one parameter are expanded into code inside the scalarization loop. */
11185 1.1 mrg
11186 1.1 mrg static gfc_ss *
11187 1.1 mrg gfc_walk_intrinsic_bound (gfc_ss * ss, gfc_expr * expr)
11188 1.1 mrg {
11189 1.1 mrg if (expr->value.function.actual->expr->ts.type == BT_CLASS)
11190 1.1 mrg gfc_add_class_array_ref (expr->value.function.actual->expr);
11191 1.1 mrg
11192 1.1 mrg /* The two argument version returns a scalar. */
11193 1.1 mrg if (expr->value.function.isym->id != GFC_ISYM_SHAPE
11194 1.1 mrg && expr->value.function.actual->next->expr)
11195 1.1 mrg return ss;
11196 1.1 mrg
11197 1.1 mrg return gfc_get_array_ss (ss, expr, 1, GFC_SS_INTRINSIC);
11198 1.1 mrg }
11199 1.1 mrg
11200 1.1 mrg
11201 1.1 mrg /* Walk an intrinsic array libcall. */
11202 1.1 mrg
11203 1.1 mrg static gfc_ss *
11204 1.1 mrg gfc_walk_intrinsic_libfunc (gfc_ss * ss, gfc_expr * expr)
11205 1.1 mrg {
11206 1.1 mrg gcc_assert (expr->rank > 0);
11207 1.1 mrg return gfc_get_array_ss (ss, expr, expr->rank, GFC_SS_FUNCTION);
11208 1.1 mrg }
11209 1.1 mrg
11210 1.1 mrg
11211 1.1 mrg /* Return whether the function call expression EXPR will be expanded
11212 1.1 mrg inline by gfc_conv_intrinsic_function. */
11213 1.1 mrg
11214 1.1 mrg bool
11215 1.1 mrg gfc_inline_intrinsic_function_p (gfc_expr *expr)
11216 1.1 mrg {
11217 1.1 mrg gfc_actual_arglist *args, *dim_arg, *mask_arg;
11218 1.1 mrg gfc_expr *maskexpr;
11219 1.1 mrg
11220 1.1 mrg if (!expr->value.function.isym)
11221 1.1 mrg return false;
11222 1.1 mrg
11223 1.1 mrg switch (expr->value.function.isym->id)
11224 1.1 mrg {
11225 1.1 mrg case GFC_ISYM_PRODUCT:
11226 1.1 mrg case GFC_ISYM_SUM:
11227 1.1 mrg /* Disable inline expansion if code size matters. */
11228 1.1 mrg if (optimize_size)
11229 1.1 mrg return false;
11230 1.1 mrg
11231 1.1 mrg args = expr->value.function.actual;
11232 1.1 mrg dim_arg = args->next;
11233 1.1 mrg
11234 1.1 mrg /* We need to be able to subset the SUM argument at compile-time. */
11235 1.1 mrg if (dim_arg->expr && dim_arg->expr->expr_type != EXPR_CONSTANT)
11236 1.1 mrg return false;
11237 1.1 mrg
11238 1.1 mrg /* FIXME: If MASK is optional for a more than two-dimensional
11239 1.1 mrg argument, the scalarizer gets confused if the mask is
11240 1.1 mrg absent. See PR 82995. For now, fall back to the library
11241 1.1 mrg function. */
11242 1.1 mrg
11243 1.1 mrg mask_arg = dim_arg->next;
11244 1.1 mrg maskexpr = mask_arg->expr;
11245 1.1 mrg
11246 1.1 mrg if (expr->rank > 0 && maskexpr && maskexpr->expr_type == EXPR_VARIABLE
11247 1.1 mrg && maskexpr->symtree->n.sym->attr.dummy
11248 1.1 mrg && maskexpr->symtree->n.sym->attr.optional)
11249 1.1 mrg return false;
11250 1.1 mrg
11251 1.1 mrg return true;
11252 1.1 mrg
11253 1.1 mrg case GFC_ISYM_TRANSPOSE:
11254 1.1 mrg return true;
11255 1.1 mrg
11256 1.1 mrg default:
11257 1.1 mrg return false;
11258 1.1 mrg }
11259 1.1 mrg }
11260 1.1 mrg
11261 1.1 mrg
11262 1.1 mrg /* Returns nonzero if the specified intrinsic function call maps directly to
11263 1.1 mrg an external library call. Should only be used for functions that return
11264 1.1 mrg arrays. */
11265 1.1 mrg
11266 1.1 mrg int
11267 1.1 mrg gfc_is_intrinsic_libcall (gfc_expr * expr)
11268 1.1 mrg {
11269 1.1 mrg gcc_assert (expr->expr_type == EXPR_FUNCTION && expr->value.function.isym);
11270 1.1 mrg gcc_assert (expr->rank > 0);
11271 1.1 mrg
11272 1.1 mrg if (gfc_inline_intrinsic_function_p (expr))
11273 1.1 mrg return 0;
11274 1.1 mrg
11275 1.1 mrg switch (expr->value.function.isym->id)
11276 1.1 mrg {
11277 1.1 mrg case GFC_ISYM_ALL:
11278 1.1 mrg case GFC_ISYM_ANY:
11279 1.1 mrg case GFC_ISYM_COUNT:
11280 1.1 mrg case GFC_ISYM_FINDLOC:
11281 1.1 mrg case GFC_ISYM_JN2:
11282 1.1 mrg case GFC_ISYM_IANY:
11283 1.1 mrg case GFC_ISYM_IALL:
11284 1.1 mrg case GFC_ISYM_IPARITY:
11285 1.1 mrg case GFC_ISYM_MATMUL:
11286 1.1 mrg case GFC_ISYM_MAXLOC:
11287 1.1 mrg case GFC_ISYM_MAXVAL:
11288 1.1 mrg case GFC_ISYM_MINLOC:
11289 1.1 mrg case GFC_ISYM_MINVAL:
11290 1.1 mrg case GFC_ISYM_NORM2:
11291 1.1 mrg case GFC_ISYM_PARITY:
11292 1.1 mrg case GFC_ISYM_PRODUCT:
11293 1.1 mrg case GFC_ISYM_SUM:
11294 1.1 mrg case GFC_ISYM_SPREAD:
11295 1.1 mrg case GFC_ISYM_YN2:
11296 1.1 mrg /* Ignore absent optional parameters. */
11297 1.1 mrg return 1;
11298 1.1 mrg
11299 1.1 mrg case GFC_ISYM_CSHIFT:
11300 1.1 mrg case GFC_ISYM_EOSHIFT:
11301 1.1 mrg case GFC_ISYM_GET_TEAM:
11302 1.1 mrg case GFC_ISYM_FAILED_IMAGES:
11303 1.1 mrg case GFC_ISYM_STOPPED_IMAGES:
11304 1.1 mrg case GFC_ISYM_PACK:
11305 1.1 mrg case GFC_ISYM_RESHAPE:
11306 1.1 mrg case GFC_ISYM_UNPACK:
11307 1.1 mrg /* Pass absent optional parameters. */
11308 1.1 mrg return 2;
11309 1.1 mrg
11310 1.1 mrg default:
11311 1.1 mrg return 0;
11312 1.1 mrg }
11313 1.1 mrg }
11314 1.1 mrg
11315 1.1 mrg /* Walk an intrinsic function. */
11316 1.1 mrg gfc_ss *
11317 1.1 mrg gfc_walk_intrinsic_function (gfc_ss * ss, gfc_expr * expr,
11318 1.1 mrg gfc_intrinsic_sym * isym)
11319 1.1 mrg {
11320 1.1 mrg gcc_assert (isym);
11321 1.1 mrg
11322 1.1 mrg if (isym->elemental)
11323 1.1 mrg return gfc_walk_elemental_function_args (ss, expr->value.function.actual,
11324 1.1 mrg expr->value.function.isym,
11325 1.1 mrg GFC_SS_SCALAR);
11326 1.1 mrg
11327 1.1 mrg if (expr->rank == 0)
11328 1.1 mrg return ss;
11329 1.1 mrg
11330 1.1 mrg if (gfc_inline_intrinsic_function_p (expr))
11331 1.1 mrg return walk_inline_intrinsic_function (ss, expr);
11332 1.1 mrg
11333 1.1 mrg if (gfc_is_intrinsic_libcall (expr))
11334 1.1 mrg return gfc_walk_intrinsic_libfunc (ss, expr);
11335 1.1 mrg
11336 1.1 mrg /* Special cases. */
11337 1.1 mrg switch (isym->id)
11338 1.1 mrg {
11339 1.1 mrg case GFC_ISYM_LBOUND:
11340 1.1 mrg case GFC_ISYM_LCOBOUND:
11341 1.1 mrg case GFC_ISYM_UBOUND:
11342 1.1 mrg case GFC_ISYM_UCOBOUND:
11343 1.1 mrg case GFC_ISYM_THIS_IMAGE:
11344 1.1 mrg case GFC_ISYM_SHAPE:
11345 1.1 mrg return gfc_walk_intrinsic_bound (ss, expr);
11346 1.1 mrg
11347 1.1 mrg case GFC_ISYM_TRANSFER:
11348 1.1 mrg case GFC_ISYM_CAF_GET:
11349 1.1 mrg return gfc_walk_intrinsic_libfunc (ss, expr);
11350 1.1 mrg
11351 1.1 mrg default:
11352 1.1 mrg /* This probably meant someone forgot to add an intrinsic to the above
11353 1.1 mrg list(s) when they implemented it, or something's gone horribly
11354 1.1 mrg wrong. */
11355 1.1 mrg gcc_unreachable ();
11356 1.1 mrg }
11357 1.1 mrg }
11358 1.1 mrg
11359 1.1 mrg static tree
11360 1.1 mrg conv_co_collective (gfc_code *code)
11361 1.1 mrg {
11362 1.1 mrg gfc_se argse;
11363 1.1 mrg stmtblock_t block, post_block;
11364 1.1 mrg tree fndecl, array = NULL_TREE, strlen, image_index, stat, errmsg, errmsg_len;
11365 1.1 mrg gfc_expr *image_idx_expr, *stat_expr, *errmsg_expr, *opr_expr;
11366 1.1 mrg
11367 1.1 mrg gfc_start_block (&block);
11368 1.1 mrg gfc_init_block (&post_block);
11369 1.1 mrg
11370 1.1 mrg if (code->resolved_isym->id == GFC_ISYM_CO_REDUCE)
11371 1.1 mrg {
11372 1.1 mrg opr_expr = code->ext.actual->next->expr;
11373 1.1 mrg image_idx_expr = code->ext.actual->next->next->expr;
11374 1.1 mrg stat_expr = code->ext.actual->next->next->next->expr;
11375 1.1 mrg errmsg_expr = code->ext.actual->next->next->next->next->expr;
11376 1.1 mrg }
11377 1.1 mrg else
11378 1.1 mrg {
11379 1.1 mrg opr_expr = NULL;
11380 1.1 mrg image_idx_expr = code->ext.actual->next->expr;
11381 1.1 mrg stat_expr = code->ext.actual->next->next->expr;
11382 1.1 mrg errmsg_expr = code->ext.actual->next->next->next->expr;
11383 1.1 mrg }
11384 1.1 mrg
11385 1.1 mrg /* stat. */
11386 1.1 mrg if (stat_expr)
11387 1.1 mrg {
11388 1.1 mrg gfc_init_se (&argse, NULL);
11389 1.1 mrg gfc_conv_expr (&argse, stat_expr);
11390 1.1 mrg gfc_add_block_to_block (&block, &argse.pre);
11391 1.1 mrg gfc_add_block_to_block (&post_block, &argse.post);
11392 1.1 mrg stat = argse.expr;
11393 1.1 mrg if (flag_coarray != GFC_FCOARRAY_SINGLE)
11394 1.1 mrg stat = gfc_build_addr_expr (NULL_TREE, stat);
11395 1.1 mrg }
11396 1.1 mrg else if (flag_coarray == GFC_FCOARRAY_SINGLE)
11397 1.1 mrg stat = NULL_TREE;
11398 1.1 mrg else
11399 1.1 mrg stat = null_pointer_node;
11400 1.1 mrg
11401 1.1 mrg /* Early exit for GFC_FCOARRAY_SINGLE. */
11402 1.1 mrg if (flag_coarray == GFC_FCOARRAY_SINGLE)
11403 1.1 mrg {
11404 1.1 mrg if (stat != NULL_TREE)
11405 1.1 mrg {
11406 1.1 mrg /* For optional stats, check the pointer is valid before zero'ing. */
11407 1.1 mrg if (gfc_expr_attr (stat_expr).optional)
11408 1.1 mrg {
11409 1.1 mrg tree tmp;
11410 1.1 mrg stmtblock_t ass_block;
11411 1.1 mrg gfc_start_block (&ass_block);
11412 1.1 mrg gfc_add_modify (&ass_block, stat,
11413 1.1 mrg fold_convert (TREE_TYPE (stat),
11414 1.1 mrg integer_zero_node));
11415 1.1 mrg tmp = fold_build2 (NE_EXPR, logical_type_node,
11416 1.1 mrg gfc_build_addr_expr (NULL_TREE, stat),
11417 1.1 mrg null_pointer_node);
11418 1.1 mrg tmp = fold_build3 (COND_EXPR, void_type_node, tmp,
11419 1.1 mrg gfc_finish_block (&ass_block),
11420 1.1 mrg build_empty_stmt (input_location));
11421 1.1 mrg gfc_add_expr_to_block (&block, tmp);
11422 1.1 mrg }
11423 1.1 mrg else
11424 1.1 mrg gfc_add_modify (&block, stat,
11425 1.1 mrg fold_convert (TREE_TYPE (stat), integer_zero_node));
11426 1.1 mrg }
11427 1.1 mrg return gfc_finish_block (&block);
11428 1.1 mrg }
11429 1.1 mrg
11430 1.1 mrg gfc_symbol *derived = code->ext.actual->expr->ts.type == BT_DERIVED
11431 1.1 mrg ? code->ext.actual->expr->ts.u.derived : NULL;
11432 1.1 mrg
11433 1.1 mrg /* Handle the array. */
11434 1.1 mrg gfc_init_se (&argse, NULL);
11435 1.1 mrg if (!derived || !derived->attr.alloc_comp
11436 1.1 mrg || code->resolved_isym->id != GFC_ISYM_CO_BROADCAST)
11437 1.1 mrg {
11438 1.1 mrg if (code->ext.actual->expr->rank == 0)
11439 1.1 mrg {
11440 1.1 mrg symbol_attribute attr;
11441 1.1 mrg gfc_clear_attr (&attr);
11442 1.1 mrg gfc_init_se (&argse, NULL);
11443 1.1 mrg gfc_conv_expr (&argse, code->ext.actual->expr);
11444 1.1 mrg gfc_add_block_to_block (&block, &argse.pre);
11445 1.1 mrg gfc_add_block_to_block (&post_block, &argse.post);
11446 1.1 mrg array = gfc_conv_scalar_to_descriptor (&argse, argse.expr, attr);
11447 1.1 mrg array = gfc_build_addr_expr (NULL_TREE, array);
11448 1.1 mrg }
11449 1.1 mrg else
11450 1.1 mrg {
11451 1.1 mrg argse.want_pointer = 1;
11452 1.1 mrg gfc_conv_expr_descriptor (&argse, code->ext.actual->expr);
11453 1.1 mrg array = argse.expr;
11454 1.1 mrg }
11455 1.1 mrg }
11456 1.1 mrg
11457 1.1 mrg gfc_add_block_to_block (&block, &argse.pre);
11458 1.1 mrg gfc_add_block_to_block (&post_block, &argse.post);
11459 1.1 mrg
11460 1.1 mrg if (code->ext.actual->expr->ts.type == BT_CHARACTER)
11461 1.1 mrg strlen = argse.string_length;
11462 1.1 mrg else
11463 1.1 mrg strlen = integer_zero_node;
11464 1.1 mrg
11465 1.1 mrg /* image_index. */
11466 1.1 mrg if (image_idx_expr)
11467 1.1 mrg {
11468 1.1 mrg gfc_init_se (&argse, NULL);
11469 1.1 mrg gfc_conv_expr (&argse, image_idx_expr);
11470 1.1 mrg gfc_add_block_to_block (&block, &argse.pre);
11471 1.1 mrg gfc_add_block_to_block (&post_block, &argse.post);
11472 1.1 mrg image_index = fold_convert (integer_type_node, argse.expr);
11473 1.1 mrg }
11474 1.1 mrg else
11475 1.1 mrg image_index = integer_zero_node;
11476 1.1 mrg
11477 1.1 mrg /* errmsg. */
11478 1.1 mrg if (errmsg_expr)
11479 1.1 mrg {
11480 1.1 mrg gfc_init_se (&argse, NULL);
11481 1.1 mrg gfc_conv_expr (&argse, errmsg_expr);
11482 1.1 mrg gfc_add_block_to_block (&block, &argse.pre);
11483 1.1 mrg gfc_add_block_to_block (&post_block, &argse.post);
11484 1.1 mrg errmsg = argse.expr;
11485 1.1 mrg errmsg_len = fold_convert (size_type_node, argse.string_length);
11486 1.1 mrg }
11487 1.1 mrg else
11488 1.1 mrg {
11489 1.1 mrg errmsg = null_pointer_node;
11490 1.1 mrg errmsg_len = build_zero_cst (size_type_node);
11491 1.1 mrg }
11492 1.1 mrg
11493 1.1 mrg /* Generate the function call. */
11494 1.1 mrg switch (code->resolved_isym->id)
11495 1.1 mrg {
11496 1.1 mrg case GFC_ISYM_CO_BROADCAST:
11497 1.1 mrg fndecl = gfor_fndecl_co_broadcast;
11498 1.1 mrg break;
11499 1.1 mrg case GFC_ISYM_CO_MAX:
11500 1.1 mrg fndecl = gfor_fndecl_co_max;
11501 1.1 mrg break;
11502 1.1 mrg case GFC_ISYM_CO_MIN:
11503 1.1 mrg fndecl = gfor_fndecl_co_min;
11504 1.1 mrg break;
11505 1.1 mrg case GFC_ISYM_CO_REDUCE:
11506 1.1 mrg fndecl = gfor_fndecl_co_reduce;
11507 1.1 mrg break;
11508 1.1 mrg case GFC_ISYM_CO_SUM:
11509 1.1 mrg fndecl = gfor_fndecl_co_sum;
11510 1.1 mrg break;
11511 1.1 mrg default:
11512 1.1 mrg gcc_unreachable ();
11513 1.1 mrg }
11514 1.1 mrg
11515 1.1 mrg if (derived && derived->attr.alloc_comp
11516 1.1 mrg && code->resolved_isym->id == GFC_ISYM_CO_BROADCAST)
11517 1.1 mrg /* The derived type has the attribute 'alloc_comp'. */
11518 1.1 mrg {
11519 1.1 mrg tree tmp = gfc_bcast_alloc_comp (derived, code->ext.actual->expr,
11520 1.1 mrg code->ext.actual->expr->rank,
11521 1.1 mrg image_index, stat, errmsg, errmsg_len);
11522 1.1 mrg gfc_add_expr_to_block (&block, tmp);
11523 1.1 mrg }
11524 1.1 mrg else
11525 1.1 mrg {
11526 1.1 mrg if (code->resolved_isym->id == GFC_ISYM_CO_SUM
11527 1.1 mrg || code->resolved_isym->id == GFC_ISYM_CO_BROADCAST)
11528 1.1 mrg fndecl = build_call_expr_loc (input_location, fndecl, 5, array,
11529 1.1 mrg image_index, stat, errmsg, errmsg_len);
11530 1.1 mrg else if (code->resolved_isym->id != GFC_ISYM_CO_REDUCE)
11531 1.1 mrg fndecl = build_call_expr_loc (input_location, fndecl, 6, array,
11532 1.1 mrg image_index, stat, errmsg,
11533 1.1 mrg strlen, errmsg_len);
11534 1.1 mrg else
11535 1.1 mrg {
11536 1.1 mrg tree opr, opr_flags;
11537 1.1 mrg
11538 1.1 mrg // FIXME: Handle TS29113's bind(C) strings with descriptor.
11539 1.1 mrg int opr_flag_int;
11540 1.1 mrg if (gfc_is_proc_ptr_comp (opr_expr))
11541 1.1 mrg {
11542 1.1 mrg gfc_symbol *sym = gfc_get_proc_ptr_comp (opr_expr)->ts.interface;
11543 1.1 mrg opr_flag_int = sym->attr.dimension
11544 1.1 mrg || (sym->ts.type == BT_CHARACTER
11545 1.1 mrg && !sym->attr.is_bind_c)
11546 1.1 mrg ? GFC_CAF_BYREF : 0;
11547 1.1 mrg opr_flag_int |= opr_expr->ts.type == BT_CHARACTER
11548 1.1 mrg && !sym->attr.is_bind_c
11549 1.1 mrg ? GFC_CAF_HIDDENLEN : 0;
11550 1.1 mrg opr_flag_int |= sym->formal->sym->attr.value
11551 1.1 mrg ? GFC_CAF_ARG_VALUE : 0;
11552 1.1 mrg }
11553 1.1 mrg else
11554 1.1 mrg {
11555 1.1 mrg opr_flag_int = gfc_return_by_reference (opr_expr->symtree->n.sym)
11556 1.1 mrg ? GFC_CAF_BYREF : 0;
11557 1.1 mrg opr_flag_int |= opr_expr->ts.type == BT_CHARACTER
11558 1.1 mrg && !opr_expr->symtree->n.sym->attr.is_bind_c
11559 1.1 mrg ? GFC_CAF_HIDDENLEN : 0;
11560 1.1 mrg opr_flag_int |= opr_expr->symtree->n.sym->formal->sym->attr.value
11561 1.1 mrg ? GFC_CAF_ARG_VALUE : 0;
11562 1.1 mrg }
11563 1.1 mrg opr_flags = build_int_cst (integer_type_node, opr_flag_int);
11564 1.1 mrg gfc_conv_expr (&argse, opr_expr);
11565 1.1 mrg opr = argse.expr;
11566 1.1 mrg fndecl = build_call_expr_loc (input_location, fndecl, 8, array, opr,
11567 1.1 mrg opr_flags, image_index, stat, errmsg,
11568 1.1 mrg strlen, errmsg_len);
11569 1.1 mrg }
11570 1.1 mrg }
11571 1.1 mrg
11572 1.1 mrg gfc_add_expr_to_block (&block, fndecl);
11573 1.1 mrg gfc_add_block_to_block (&block, &post_block);
11574 1.1 mrg
11575 1.1 mrg return gfc_finish_block (&block);
11576 1.1 mrg }
11577 1.1 mrg
11578 1.1 mrg
11579 1.1 mrg static tree
11580 1.1 mrg conv_intrinsic_atomic_op (gfc_code *code)
11581 1.1 mrg {
11582 1.1 mrg gfc_se argse;
11583 1.1 mrg tree tmp, atom, value, old = NULL_TREE, stat = NULL_TREE;
11584 1.1 mrg stmtblock_t block, post_block;
11585 1.1 mrg gfc_expr *atom_expr = code->ext.actual->expr;
11586 1.1 mrg gfc_expr *stat_expr;
11587 1.1 mrg built_in_function fn;
11588 1.1 mrg
11589 1.1 mrg if (atom_expr->expr_type == EXPR_FUNCTION
11590 1.1 mrg && atom_expr->value.function.isym
11591 1.1 mrg && atom_expr->value.function.isym->id == GFC_ISYM_CAF_GET)
11592 1.1 mrg atom_expr = atom_expr->value.function.actual->expr;
11593 1.1 mrg
11594 1.1 mrg gfc_start_block (&block);
11595 1.1 mrg gfc_init_block (&post_block);
11596 1.1 mrg
11597 1.1 mrg gfc_init_se (&argse, NULL);
11598 1.1 mrg argse.want_pointer = 1;
11599 1.1 mrg gfc_conv_expr (&argse, atom_expr);
11600 1.1 mrg gfc_add_block_to_block (&block, &argse.pre);
11601 1.1 mrg gfc_add_block_to_block (&post_block, &argse.post);
11602 1.1 mrg atom = argse.expr;
11603 1.1 mrg
11604 1.1 mrg gfc_init_se (&argse, NULL);
11605 1.1 mrg if (flag_coarray == GFC_FCOARRAY_LIB
11606 1.1 mrg && code->ext.actual->next->expr->ts.kind == atom_expr->ts.kind)
11607 1.1 mrg argse.want_pointer = 1;
11608 1.1 mrg gfc_conv_expr (&argse, code->ext.actual->next->expr);
11609 1.1 mrg gfc_add_block_to_block (&block, &argse.pre);
11610 1.1 mrg gfc_add_block_to_block (&post_block, &argse.post);
11611 1.1 mrg value = argse.expr;
11612 1.1 mrg
11613 1.1 mrg switch (code->resolved_isym->id)
11614 1.1 mrg {
11615 1.1 mrg case GFC_ISYM_ATOMIC_ADD:
11616 1.1 mrg case GFC_ISYM_ATOMIC_AND:
11617 1.1 mrg case GFC_ISYM_ATOMIC_DEF:
11618 1.1 mrg case GFC_ISYM_ATOMIC_OR:
11619 1.1 mrg case GFC_ISYM_ATOMIC_XOR:
11620 1.1 mrg stat_expr = code->ext.actual->next->next->expr;
11621 1.1 mrg if (flag_coarray == GFC_FCOARRAY_LIB)
11622 1.1 mrg old = null_pointer_node;
11623 1.1 mrg break;
11624 1.1 mrg default:
11625 1.1 mrg gfc_init_se (&argse, NULL);
11626 1.1 mrg if (flag_coarray == GFC_FCOARRAY_LIB)
11627 1.1 mrg argse.want_pointer = 1;
11628 1.1 mrg gfc_conv_expr (&argse, code->ext.actual->next->next->expr);
11629 1.1 mrg gfc_add_block_to_block (&block, &argse.pre);
11630 1.1 mrg gfc_add_block_to_block (&post_block, &argse.post);
11631 1.1 mrg old = argse.expr;
11632 1.1 mrg stat_expr = code->ext.actual->next->next->next->expr;
11633 1.1 mrg }
11634 1.1 mrg
11635 1.1 mrg /* STAT= */
11636 1.1 mrg if (stat_expr != NULL)
11637 1.1 mrg {
11638 1.1 mrg gcc_assert (stat_expr->expr_type == EXPR_VARIABLE);
11639 1.1 mrg gfc_init_se (&argse, NULL);
11640 1.1 mrg if (flag_coarray == GFC_FCOARRAY_LIB)
11641 1.1 mrg argse.want_pointer = 1;
11642 1.1 mrg gfc_conv_expr_val (&argse, stat_expr);
11643 1.1 mrg gfc_add_block_to_block (&block, &argse.pre);
11644 1.1 mrg gfc_add_block_to_block (&post_block, &argse.post);
11645 1.1 mrg stat = argse.expr;
11646 1.1 mrg }
11647 1.1 mrg else if (flag_coarray == GFC_FCOARRAY_LIB)
11648 1.1 mrg stat = null_pointer_node;
11649 1.1 mrg
11650 1.1 mrg if (flag_coarray == GFC_FCOARRAY_LIB)
11651 1.1 mrg {
11652 1.1 mrg tree image_index, caf_decl, offset, token;
11653 1.1 mrg int op;
11654 1.1 mrg
11655 1.1 mrg switch (code->resolved_isym->id)
11656 1.1 mrg {
11657 1.1 mrg case GFC_ISYM_ATOMIC_ADD:
11658 1.1 mrg case GFC_ISYM_ATOMIC_FETCH_ADD:
11659 1.1 mrg op = (int) GFC_CAF_ATOMIC_ADD;
11660 1.1 mrg break;
11661 1.1 mrg case GFC_ISYM_ATOMIC_AND:
11662 1.1 mrg case GFC_ISYM_ATOMIC_FETCH_AND:
11663 1.1 mrg op = (int) GFC_CAF_ATOMIC_AND;
11664 1.1 mrg break;
11665 1.1 mrg case GFC_ISYM_ATOMIC_OR:
11666 1.1 mrg case GFC_ISYM_ATOMIC_FETCH_OR:
11667 1.1 mrg op = (int) GFC_CAF_ATOMIC_OR;
11668 1.1 mrg break;
11669 1.1 mrg case GFC_ISYM_ATOMIC_XOR:
11670 1.1 mrg case GFC_ISYM_ATOMIC_FETCH_XOR:
11671 1.1 mrg op = (int) GFC_CAF_ATOMIC_XOR;
11672 1.1 mrg break;
11673 1.1 mrg case GFC_ISYM_ATOMIC_DEF:
11674 1.1 mrg op = 0; /* Unused. */
11675 1.1 mrg break;
11676 1.1 mrg default:
11677 1.1 mrg gcc_unreachable ();
11678 1.1 mrg }
11679 1.1 mrg
11680 1.1 mrg caf_decl = gfc_get_tree_for_caf_expr (atom_expr);
11681 1.1 mrg if (TREE_CODE (TREE_TYPE (caf_decl)) == REFERENCE_TYPE)
11682 1.1 mrg caf_decl = build_fold_indirect_ref_loc (input_location, caf_decl);
11683 1.1 mrg
11684 1.1 mrg if (gfc_is_coindexed (atom_expr))
11685 1.1 mrg image_index = gfc_caf_get_image_index (&block, atom_expr, caf_decl);
11686 1.1 mrg else
11687 1.1 mrg image_index = integer_zero_node;
11688 1.1 mrg
11689 1.1 mrg if (!POINTER_TYPE_P (TREE_TYPE (value)))
11690 1.1 mrg {
11691 1.1 mrg tmp = gfc_create_var (TREE_TYPE (TREE_TYPE (atom)), "value");
11692 1.1 mrg gfc_add_modify (&block, tmp, fold_convert (TREE_TYPE (tmp), value));
11693 1.1 mrg value = gfc_build_addr_expr (NULL_TREE, tmp);
11694 1.1 mrg }
11695 1.1 mrg
11696 1.1 mrg gfc_init_se (&argse, NULL);
11697 1.1 mrg gfc_get_caf_token_offset (&argse, &token, &offset, caf_decl, atom,
11698 1.1 mrg atom_expr);
11699 1.1 mrg
11700 1.1 mrg gfc_add_block_to_block (&block, &argse.pre);
11701 1.1 mrg if (code->resolved_isym->id == GFC_ISYM_ATOMIC_DEF)
11702 1.1 mrg tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_atomic_def, 7,
11703 1.1 mrg token, offset, image_index, value, stat,
11704 1.1 mrg build_int_cst (integer_type_node,
11705 1.1 mrg (int) atom_expr->ts.type),
11706 1.1 mrg build_int_cst (integer_type_node,
11707 1.1 mrg (int) atom_expr->ts.kind));
11708 1.1 mrg else
11709 1.1 mrg tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_atomic_op, 9,
11710 1.1 mrg build_int_cst (integer_type_node, op),
11711 1.1 mrg token, offset, image_index, value, old, stat,
11712 1.1 mrg build_int_cst (integer_type_node,
11713 1.1 mrg (int) atom_expr->ts.type),
11714 1.1 mrg build_int_cst (integer_type_node,
11715 1.1 mrg (int) atom_expr->ts.kind));
11716 1.1 mrg
11717 1.1 mrg gfc_add_expr_to_block (&block, tmp);
11718 1.1 mrg gfc_add_block_to_block (&block, &argse.post);
11719 1.1 mrg gfc_add_block_to_block (&block, &post_block);
11720 1.1 mrg return gfc_finish_block (&block);
11721 1.1 mrg }
11722 1.1 mrg
11723 1.1 mrg
11724 1.1 mrg switch (code->resolved_isym->id)
11725 1.1 mrg {
11726 1.1 mrg case GFC_ISYM_ATOMIC_ADD:
11727 1.1 mrg case GFC_ISYM_ATOMIC_FETCH_ADD:
11728 1.1 mrg fn = BUILT_IN_ATOMIC_FETCH_ADD_N;
11729 1.1 mrg break;
11730 1.1 mrg case GFC_ISYM_ATOMIC_AND:
11731 1.1 mrg case GFC_ISYM_ATOMIC_FETCH_AND:
11732 1.1 mrg fn = BUILT_IN_ATOMIC_FETCH_AND_N;
11733 1.1 mrg break;
11734 1.1 mrg case GFC_ISYM_ATOMIC_DEF:
11735 1.1 mrg fn = BUILT_IN_ATOMIC_STORE_N;
11736 1.1 mrg break;
11737 1.1 mrg case GFC_ISYM_ATOMIC_OR:
11738 1.1 mrg case GFC_ISYM_ATOMIC_FETCH_OR:
11739 1.1 mrg fn = BUILT_IN_ATOMIC_FETCH_OR_N;
11740 1.1 mrg break;
11741 1.1 mrg case GFC_ISYM_ATOMIC_XOR:
11742 1.1 mrg case GFC_ISYM_ATOMIC_FETCH_XOR:
11743 1.1 mrg fn = BUILT_IN_ATOMIC_FETCH_XOR_N;
11744 1.1 mrg break;
11745 1.1 mrg default:
11746 1.1 mrg gcc_unreachable ();
11747 1.1 mrg }
11748 1.1 mrg
11749 1.1 mrg tmp = TREE_TYPE (TREE_TYPE (atom));
11750 1.1 mrg fn = (built_in_function) ((int) fn
11751 1.1 mrg + exact_log2 (tree_to_uhwi (TYPE_SIZE_UNIT (tmp)))
11752 1.1 mrg + 1);
11753 1.1 mrg tree itype = TREE_TYPE (TREE_TYPE (atom));
11754 1.1 mrg tmp = builtin_decl_explicit (fn);
11755 1.1 mrg
11756 1.1 mrg switch (code->resolved_isym->id)
11757 1.1 mrg {
11758 1.1 mrg case GFC_ISYM_ATOMIC_ADD:
11759 1.1 mrg case GFC_ISYM_ATOMIC_AND:
11760 1.1 mrg case GFC_ISYM_ATOMIC_DEF:
11761 1.1 mrg case GFC_ISYM_ATOMIC_OR:
11762 1.1 mrg case GFC_ISYM_ATOMIC_XOR:
11763 1.1 mrg tmp = build_call_expr_loc (input_location, tmp, 3, atom,
11764 1.1 mrg fold_convert (itype, value),
11765 1.1 mrg build_int_cst (NULL, MEMMODEL_RELAXED));
11766 1.1 mrg gfc_add_expr_to_block (&block, tmp);
11767 1.1 mrg break;
11768 1.1 mrg default:
11769 1.1 mrg tmp = build_call_expr_loc (input_location, tmp, 3, atom,
11770 1.1 mrg fold_convert (itype, value),
11771 1.1 mrg build_int_cst (NULL, MEMMODEL_RELAXED));
11772 1.1 mrg gfc_add_modify (&block, old, fold_convert (TREE_TYPE (old), tmp));
11773 1.1 mrg break;
11774 1.1 mrg }
11775 1.1 mrg
11776 1.1 mrg if (stat != NULL_TREE)
11777 1.1 mrg gfc_add_modify (&block, stat, build_int_cst (TREE_TYPE (stat), 0));
11778 1.1 mrg gfc_add_block_to_block (&block, &post_block);
11779 1.1 mrg return gfc_finish_block (&block);
11780 1.1 mrg }
11781 1.1 mrg
11782 1.1 mrg
11783 1.1 mrg static tree
11784 1.1 mrg conv_intrinsic_atomic_ref (gfc_code *code)
11785 1.1 mrg {
11786 1.1 mrg gfc_se argse;
11787 1.1 mrg tree tmp, atom, value, stat = NULL_TREE;
11788 1.1 mrg stmtblock_t block, post_block;
11789 1.1 mrg built_in_function fn;
11790 1.1 mrg gfc_expr *atom_expr = code->ext.actual->next->expr;
11791 1.1 mrg
11792 1.1 mrg if (atom_expr->expr_type == EXPR_FUNCTION
11793 1.1 mrg && atom_expr->value.function.isym
11794 1.1 mrg && atom_expr->value.function.isym->id == GFC_ISYM_CAF_GET)
11795 1.1 mrg atom_expr = atom_expr->value.function.actual->expr;
11796 1.1 mrg
11797 1.1 mrg gfc_start_block (&block);
11798 1.1 mrg gfc_init_block (&post_block);
11799 1.1 mrg gfc_init_se (&argse, NULL);
11800 1.1 mrg argse.want_pointer = 1;
11801 1.1 mrg gfc_conv_expr (&argse, atom_expr);
11802 1.1 mrg gfc_add_block_to_block (&block, &argse.pre);
11803 1.1 mrg gfc_add_block_to_block (&post_block, &argse.post);
11804 1.1 mrg atom = argse.expr;
11805 1.1 mrg
11806 1.1 mrg gfc_init_se (&argse, NULL);
11807 1.1 mrg if (flag_coarray == GFC_FCOARRAY_LIB
11808 1.1 mrg && code->ext.actual->expr->ts.kind == atom_expr->ts.kind)
11809 1.1 mrg argse.want_pointer = 1;
11810 1.1 mrg gfc_conv_expr (&argse, code->ext.actual->expr);
11811 1.1 mrg gfc_add_block_to_block (&block, &argse.pre);
11812 1.1 mrg gfc_add_block_to_block (&post_block, &argse.post);
11813 1.1 mrg value = argse.expr;
11814 1.1 mrg
11815 1.1 mrg /* STAT= */
11816 1.1 mrg if (code->ext.actual->next->next->expr != NULL)
11817 1.1 mrg {
11818 1.1 mrg gcc_assert (code->ext.actual->next->next->expr->expr_type
11819 1.1 mrg == EXPR_VARIABLE);
11820 1.1 mrg gfc_init_se (&argse, NULL);
11821 1.1 mrg if (flag_coarray == GFC_FCOARRAY_LIB)
11822 1.1 mrg argse.want_pointer = 1;
11823 1.1 mrg gfc_conv_expr_val (&argse, code->ext.actual->next->next->expr);
11824 1.1 mrg gfc_add_block_to_block (&block, &argse.pre);
11825 1.1 mrg gfc_add_block_to_block (&post_block, &argse.post);
11826 1.1 mrg stat = argse.expr;
11827 1.1 mrg }
11828 1.1 mrg else if (flag_coarray == GFC_FCOARRAY_LIB)
11829 1.1 mrg stat = null_pointer_node;
11830 1.1 mrg
11831 1.1 mrg if (flag_coarray == GFC_FCOARRAY_LIB)
11832 1.1 mrg {
11833 1.1 mrg tree image_index, caf_decl, offset, token;
11834 1.1 mrg tree orig_value = NULL_TREE, vardecl = NULL_TREE;
11835 1.1 mrg
11836 1.1 mrg caf_decl = gfc_get_tree_for_caf_expr (atom_expr);
11837 1.1 mrg if (TREE_CODE (TREE_TYPE (caf_decl)) == REFERENCE_TYPE)
11838 1.1 mrg caf_decl = build_fold_indirect_ref_loc (input_location, caf_decl);
11839 1.1 mrg
11840 1.1 mrg if (gfc_is_coindexed (atom_expr))
11841 1.1 mrg image_index = gfc_caf_get_image_index (&block, atom_expr, caf_decl);
11842 1.1 mrg else
11843 1.1 mrg image_index = integer_zero_node;
11844 1.1 mrg
11845 1.1 mrg gfc_init_se (&argse, NULL);
11846 1.1 mrg gfc_get_caf_token_offset (&argse, &token, &offset, caf_decl, atom,
11847 1.1 mrg atom_expr);
11848 1.1 mrg gfc_add_block_to_block (&block, &argse.pre);
11849 1.1 mrg
11850 1.1 mrg /* Different type, need type conversion. */
11851 1.1 mrg if (!POINTER_TYPE_P (TREE_TYPE (value)))
11852 1.1 mrg {
11853 1.1 mrg vardecl = gfc_create_var (TREE_TYPE (TREE_TYPE (atom)), "value");
11854 1.1 mrg orig_value = value;
11855 1.1 mrg value = gfc_build_addr_expr (NULL_TREE, vardecl);
11856 1.1 mrg }
11857 1.1 mrg
11858 1.1 mrg tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_atomic_ref, 7,
11859 1.1 mrg token, offset, image_index, value, stat,
11860 1.1 mrg build_int_cst (integer_type_node,
11861 1.1 mrg (int) atom_expr->ts.type),
11862 1.1 mrg build_int_cst (integer_type_node,
11863 1.1 mrg (int) atom_expr->ts.kind));
11864 1.1 mrg gfc_add_expr_to_block (&block, tmp);
11865 1.1 mrg if (vardecl != NULL_TREE)
11866 1.1 mrg gfc_add_modify (&block, orig_value,
11867 1.1 mrg fold_convert (TREE_TYPE (orig_value), vardecl));
11868 1.1 mrg gfc_add_block_to_block (&block, &argse.post);
11869 1.1 mrg gfc_add_block_to_block (&block, &post_block);
11870 1.1 mrg return gfc_finish_block (&block);
11871 1.1 mrg }
11872 1.1 mrg
11873 1.1 mrg tmp = TREE_TYPE (TREE_TYPE (atom));
11874 1.1 mrg fn = (built_in_function) ((int) BUILT_IN_ATOMIC_LOAD_N
11875 1.1 mrg + exact_log2 (tree_to_uhwi (TYPE_SIZE_UNIT (tmp)))
11876 1.1 mrg + 1);
11877 1.1 mrg tmp = builtin_decl_explicit (fn);
11878 1.1 mrg tmp = build_call_expr_loc (input_location, tmp, 2, atom,
11879 1.1 mrg build_int_cst (integer_type_node,
11880 1.1 mrg MEMMODEL_RELAXED));
11881 1.1 mrg gfc_add_modify (&block, value, fold_convert (TREE_TYPE (value), tmp));
11882 1.1 mrg
11883 1.1 mrg if (stat != NULL_TREE)
11884 1.1 mrg gfc_add_modify (&block, stat, build_int_cst (TREE_TYPE (stat), 0));
11885 1.1 mrg gfc_add_block_to_block (&block, &post_block);
11886 1.1 mrg return gfc_finish_block (&block);
11887 1.1 mrg }
11888 1.1 mrg
11889 1.1 mrg
11890 1.1 mrg static tree
11891 1.1 mrg conv_intrinsic_atomic_cas (gfc_code *code)
11892 1.1 mrg {
11893 1.1 mrg gfc_se argse;
11894 1.1 mrg tree tmp, atom, old, new_val, comp, stat = NULL_TREE;
11895 1.1 mrg stmtblock_t block, post_block;
11896 1.1 mrg built_in_function fn;
11897 1.1 mrg gfc_expr *atom_expr = code->ext.actual->expr;
11898 1.1 mrg
11899 1.1 mrg if (atom_expr->expr_type == EXPR_FUNCTION
11900 1.1 mrg && atom_expr->value.function.isym
11901 1.1 mrg && atom_expr->value.function.isym->id == GFC_ISYM_CAF_GET)
11902 1.1 mrg atom_expr = atom_expr->value.function.actual->expr;
11903 1.1 mrg
11904 1.1 mrg gfc_init_block (&block);
11905 1.1 mrg gfc_init_block (&post_block);
11906 1.1 mrg gfc_init_se (&argse, NULL);
11907 1.1 mrg argse.want_pointer = 1;
11908 1.1 mrg gfc_conv_expr (&argse, atom_expr);
11909 1.1 mrg atom = argse.expr;
11910 1.1 mrg
11911 1.1 mrg gfc_init_se (&argse, NULL);
11912 1.1 mrg if (flag_coarray == GFC_FCOARRAY_LIB)
11913 1.1 mrg argse.want_pointer = 1;
11914 1.1 mrg gfc_conv_expr (&argse, code->ext.actual->next->expr);
11915 1.1 mrg gfc_add_block_to_block (&block, &argse.pre);
11916 1.1 mrg gfc_add_block_to_block (&post_block, &argse.post);
11917 1.1 mrg old = argse.expr;
11918 1.1 mrg
11919 1.1 mrg gfc_init_se (&argse, NULL);
11920 1.1 mrg if (flag_coarray == GFC_FCOARRAY_LIB)
11921 1.1 mrg argse.want_pointer = 1;
11922 1.1 mrg gfc_conv_expr (&argse, code->ext.actual->next->next->expr);
11923 1.1 mrg gfc_add_block_to_block (&block, &argse.pre);
11924 1.1 mrg gfc_add_block_to_block (&post_block, &argse.post);
11925 1.1 mrg comp = argse.expr;
11926 1.1 mrg
11927 1.1 mrg gfc_init_se (&argse, NULL);
11928 1.1 mrg if (flag_coarray == GFC_FCOARRAY_LIB
11929 1.1 mrg && code->ext.actual->next->next->next->expr->ts.kind
11930 1.1 mrg == atom_expr->ts.kind)
11931 1.1 mrg argse.want_pointer = 1;
11932 1.1 mrg gfc_conv_expr (&argse, code->ext.actual->next->next->next->expr);
11933 1.1 mrg gfc_add_block_to_block (&block, &argse.pre);
11934 1.1 mrg gfc_add_block_to_block (&post_block, &argse.post);
11935 1.1 mrg new_val = argse.expr;
11936 1.1 mrg
11937 1.1 mrg /* STAT= */
11938 1.1 mrg if (code->ext.actual->next->next->next->next->expr != NULL)
11939 1.1 mrg {
11940 1.1 mrg gcc_assert (code->ext.actual->next->next->next->next->expr->expr_type
11941 1.1 mrg == EXPR_VARIABLE);
11942 1.1 mrg gfc_init_se (&argse, NULL);
11943 1.1 mrg if (flag_coarray == GFC_FCOARRAY_LIB)
11944 1.1 mrg argse.want_pointer = 1;
11945 1.1 mrg gfc_conv_expr_val (&argse,
11946 1.1 mrg code->ext.actual->next->next->next->next->expr);
11947 1.1 mrg gfc_add_block_to_block (&block, &argse.pre);
11948 1.1 mrg gfc_add_block_to_block (&post_block, &argse.post);
11949 1.1 mrg stat = argse.expr;
11950 1.1 mrg }
11951 1.1 mrg else if (flag_coarray == GFC_FCOARRAY_LIB)
11952 1.1 mrg stat = null_pointer_node;
11953 1.1 mrg
11954 1.1 mrg if (flag_coarray == GFC_FCOARRAY_LIB)
11955 1.1 mrg {
11956 1.1 mrg tree image_index, caf_decl, offset, token;
11957 1.1 mrg
11958 1.1 mrg caf_decl = gfc_get_tree_for_caf_expr (atom_expr);
11959 1.1 mrg if (TREE_CODE (TREE_TYPE (caf_decl)) == REFERENCE_TYPE)
11960 1.1 mrg caf_decl = build_fold_indirect_ref_loc (input_location, caf_decl);
11961 1.1 mrg
11962 1.1 mrg if (gfc_is_coindexed (atom_expr))
11963 1.1 mrg image_index = gfc_caf_get_image_index (&block, atom_expr, caf_decl);
11964 1.1 mrg else
11965 1.1 mrg image_index = integer_zero_node;
11966 1.1 mrg
11967 1.1 mrg if (TREE_TYPE (TREE_TYPE (new_val)) != TREE_TYPE (TREE_TYPE (old)))
11968 1.1 mrg {
11969 1.1 mrg tmp = gfc_create_var (TREE_TYPE (TREE_TYPE (old)), "new");
11970 1.1 mrg gfc_add_modify (&block, tmp, fold_convert (TREE_TYPE (tmp), new_val));
11971 1.1 mrg new_val = gfc_build_addr_expr (NULL_TREE, tmp);
11972 1.1 mrg }
11973 1.1 mrg
11974 1.1 mrg /* Convert a constant to a pointer. */
11975 1.1 mrg if (!POINTER_TYPE_P (TREE_TYPE (comp)))
11976 1.1 mrg {
11977 1.1 mrg tmp = gfc_create_var (TREE_TYPE (TREE_TYPE (old)), "comp");
11978 1.1 mrg gfc_add_modify (&block, tmp, fold_convert (TREE_TYPE (tmp), comp));
11979 1.1 mrg comp = gfc_build_addr_expr (NULL_TREE, tmp);
11980 1.1 mrg }
11981 1.1 mrg
11982 1.1 mrg gfc_init_se (&argse, NULL);
11983 1.1 mrg gfc_get_caf_token_offset (&argse, &token, &offset, caf_decl, atom,
11984 1.1 mrg atom_expr);
11985 1.1 mrg gfc_add_block_to_block (&block, &argse.pre);
11986 1.1 mrg
11987 1.1 mrg tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_atomic_cas, 9,
11988 1.1 mrg token, offset, image_index, old, comp, new_val,
11989 1.1 mrg stat, build_int_cst (integer_type_node,
11990 1.1 mrg (int) atom_expr->ts.type),
11991 1.1 mrg build_int_cst (integer_type_node,
11992 1.1 mrg (int) atom_expr->ts.kind));
11993 1.1 mrg gfc_add_expr_to_block (&block, tmp);
11994 1.1 mrg gfc_add_block_to_block (&block, &argse.post);
11995 1.1 mrg gfc_add_block_to_block (&block, &post_block);
11996 1.1 mrg return gfc_finish_block (&block);
11997 1.1 mrg }
11998 1.1 mrg
11999 1.1 mrg tmp = TREE_TYPE (TREE_TYPE (atom));
12000 1.1 mrg fn = (built_in_function) ((int) BUILT_IN_ATOMIC_COMPARE_EXCHANGE_N
12001 1.1 mrg + exact_log2 (tree_to_uhwi (TYPE_SIZE_UNIT (tmp)))
12002 1.1 mrg + 1);
12003 1.1 mrg tmp = builtin_decl_explicit (fn);
12004 1.1 mrg
12005 1.1 mrg gfc_add_modify (&block, old, comp);
12006 1.1 mrg tmp = build_call_expr_loc (input_location, tmp, 6, atom,
12007 1.1 mrg gfc_build_addr_expr (NULL, old),
12008 1.1 mrg fold_convert (TREE_TYPE (old), new_val),
12009 1.1 mrg boolean_false_node,
12010 1.1 mrg build_int_cst (NULL, MEMMODEL_RELAXED),
12011 1.1 mrg build_int_cst (NULL, MEMMODEL_RELAXED));
12012 1.1 mrg gfc_add_expr_to_block (&block, tmp);
12013 1.1 mrg
12014 1.1 mrg if (stat != NULL_TREE)
12015 1.1 mrg gfc_add_modify (&block, stat, build_int_cst (TREE_TYPE (stat), 0));
12016 1.1 mrg gfc_add_block_to_block (&block, &post_block);
12017 1.1 mrg return gfc_finish_block (&block);
12018 1.1 mrg }
12019 1.1 mrg
12020 1.1 mrg static tree
12021 1.1 mrg conv_intrinsic_event_query (gfc_code *code)
12022 1.1 mrg {
12023 1.1 mrg gfc_se se, argse;
12024 1.1 mrg tree stat = NULL_TREE, stat2 = NULL_TREE;
12025 1.1 mrg tree count = NULL_TREE, count2 = NULL_TREE;
12026 1.1 mrg
12027 1.1 mrg gfc_expr *event_expr = code->ext.actual->expr;
12028 1.1 mrg
12029 1.1 mrg if (code->ext.actual->next->next->expr)
12030 1.1 mrg {
12031 1.1 mrg gcc_assert (code->ext.actual->next->next->expr->expr_type
12032 1.1 mrg == EXPR_VARIABLE);
12033 1.1 mrg gfc_init_se (&argse, NULL);
12034 1.1 mrg gfc_conv_expr_val (&argse, code->ext.actual->next->next->expr);
12035 1.1 mrg stat = argse.expr;
12036 1.1 mrg }
12037 1.1 mrg else if (flag_coarray == GFC_FCOARRAY_LIB)
12038 1.1 mrg stat = null_pointer_node;
12039 1.1 mrg
12040 1.1 mrg if (code->ext.actual->next->expr)
12041 1.1 mrg {
12042 1.1 mrg gcc_assert (code->ext.actual->next->expr->expr_type == EXPR_VARIABLE);
12043 1.1 mrg gfc_init_se (&argse, NULL);
12044 1.1 mrg gfc_conv_expr_val (&argse, code->ext.actual->next->expr);
12045 1.1 mrg count = argse.expr;
12046 1.1 mrg }
12047 1.1 mrg
12048 1.1 mrg gfc_start_block (&se.pre);
12049 1.1 mrg if (flag_coarray == GFC_FCOARRAY_LIB)
12050 1.1 mrg {
12051 1.1 mrg tree tmp, token, image_index;
12052 1.1 mrg tree index = build_zero_cst (gfc_array_index_type);
12053 1.1 mrg
12054 1.1 mrg if (event_expr->expr_type == EXPR_FUNCTION
12055 1.1 mrg && event_expr->value.function.isym
12056 1.1 mrg && event_expr->value.function.isym->id == GFC_ISYM_CAF_GET)
12057 1.1 mrg event_expr = event_expr->value.function.actual->expr;
12058 1.1 mrg
12059 1.1 mrg tree caf_decl = gfc_get_tree_for_caf_expr (event_expr);
12060 1.1 mrg
12061 1.1 mrg if (event_expr->symtree->n.sym->ts.type != BT_DERIVED
12062 1.1 mrg || event_expr->symtree->n.sym->ts.u.derived->from_intmod
12063 1.1 mrg != INTMOD_ISO_FORTRAN_ENV
12064 1.1 mrg || event_expr->symtree->n.sym->ts.u.derived->intmod_sym_id
12065 1.1 mrg != ISOFORTRAN_EVENT_TYPE)
12066 1.1 mrg {
12067 1.1 mrg gfc_error ("Sorry, the event component of derived type at %L is not "
12068 1.1 mrg "yet supported", &event_expr->where);
12069 1.1 mrg return NULL_TREE;
12070 1.1 mrg }
12071 1.1 mrg
12072 1.1 mrg if (gfc_is_coindexed (event_expr))
12073 1.1 mrg {
12074 1.1 mrg gfc_error ("The event variable at %L shall not be coindexed",
12075 1.1 mrg &event_expr->where);
12076 1.1 mrg return NULL_TREE;
12077 1.1 mrg }
12078 1.1 mrg
12079 1.1 mrg image_index = integer_zero_node;
12080 1.1 mrg
12081 1.1 mrg gfc_get_caf_token_offset (&se, &token, NULL, caf_decl, NULL_TREE,
12082 1.1 mrg event_expr);
12083 1.1 mrg
12084 1.1 mrg /* For arrays, obtain the array index. */
12085 1.1 mrg if (gfc_expr_attr (event_expr).dimension)
12086 1.1 mrg {
12087 1.1 mrg tree desc, tmp, extent, lbound, ubound;
12088 1.1 mrg gfc_array_ref *ar, ar2;
12089 1.1 mrg int i;
12090 1.1 mrg
12091 1.1 mrg /* TODO: Extend this, once DT components are supported. */
12092 1.1 mrg ar = &event_expr->ref->u.ar;
12093 1.1 mrg ar2 = *ar;
12094 1.1 mrg memset (ar, '\0', sizeof (*ar));
12095 1.1 mrg ar->as = ar2.as;
12096 1.1 mrg ar->type = AR_FULL;
12097 1.1 mrg
12098 1.1 mrg gfc_init_se (&argse, NULL);
12099 1.1 mrg argse.descriptor_only = 1;
12100 1.1 mrg gfc_conv_expr_descriptor (&argse, event_expr);
12101 1.1 mrg gfc_add_block_to_block (&se.pre, &argse.pre);
12102 1.1 mrg desc = argse.expr;
12103 1.1 mrg *ar = ar2;
12104 1.1 mrg
12105 1.1 mrg extent = build_one_cst (gfc_array_index_type);
12106 1.1 mrg for (i = 0; i < ar->dimen; i++)
12107 1.1 mrg {
12108 1.1 mrg gfc_init_se (&argse, NULL);
12109 1.1 mrg gfc_conv_expr_type (&argse, ar->start[i], gfc_array_index_type);
12110 1.1 mrg gfc_add_block_to_block (&argse.pre, &argse.pre);
12111 1.1 mrg lbound = gfc_conv_descriptor_lbound_get (desc, gfc_rank_cst[i]);
12112 1.1 mrg tmp = fold_build2_loc (input_location, MINUS_EXPR,
12113 1.1 mrg TREE_TYPE (lbound), argse.expr, lbound);
12114 1.1 mrg tmp = fold_build2_loc (input_location, MULT_EXPR,
12115 1.1 mrg TREE_TYPE (tmp), extent, tmp);
12116 1.1 mrg index = fold_build2_loc (input_location, PLUS_EXPR,
12117 1.1 mrg TREE_TYPE (tmp), index, tmp);
12118 1.1 mrg if (i < ar->dimen - 1)
12119 1.1 mrg {
12120 1.1 mrg ubound = gfc_conv_descriptor_ubound_get (desc, gfc_rank_cst[i]);
12121 1.1 mrg tmp = gfc_conv_array_extent_dim (lbound, ubound, NULL);
12122 1.1 mrg extent = fold_build2_loc (input_location, MULT_EXPR,
12123 1.1 mrg TREE_TYPE (tmp), extent, tmp);
12124 1.1 mrg }
12125 1.1 mrg }
12126 1.1 mrg }
12127 1.1 mrg
12128 1.1 mrg if (count != null_pointer_node && TREE_TYPE (count) != integer_type_node)
12129 1.1 mrg {
12130 1.1 mrg count2 = count;
12131 1.1 mrg count = gfc_create_var (integer_type_node, "count");
12132 1.1 mrg }
12133 1.1 mrg
12134 1.1 mrg if (stat != null_pointer_node && TREE_TYPE (stat) != integer_type_node)
12135 1.1 mrg {
12136 1.1 mrg stat2 = stat;
12137 1.1 mrg stat = gfc_create_var (integer_type_node, "stat");
12138 1.1 mrg }
12139 1.1 mrg
12140 1.1 mrg index = fold_convert (size_type_node, index);
12141 1.1 mrg tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_event_query, 5,
12142 1.1 mrg token, index, image_index, count
12143 1.1 mrg ? gfc_build_addr_expr (NULL, count) : count,
12144 1.1 mrg stat != null_pointer_node
12145 1.1 mrg ? gfc_build_addr_expr (NULL, stat) : stat);
12146 1.1 mrg gfc_add_expr_to_block (&se.pre, tmp);
12147 1.1 mrg
12148 1.1 mrg if (count2 != NULL_TREE)
12149 1.1 mrg gfc_add_modify (&se.pre, count2,
12150 1.1 mrg fold_convert (TREE_TYPE (count2), count));
12151 1.1 mrg
12152 1.1 mrg if (stat2 != NULL_TREE)
12153 1.1 mrg gfc_add_modify (&se.pre, stat2,
12154 1.1 mrg fold_convert (TREE_TYPE (stat2), stat));
12155 1.1 mrg
12156 1.1 mrg return gfc_finish_block (&se.pre);
12157 1.1 mrg }
12158 1.1 mrg
12159 1.1 mrg gfc_init_se (&argse, NULL);
12160 1.1 mrg gfc_conv_expr_val (&argse, code->ext.actual->expr);
12161 1.1 mrg gfc_add_modify (&se.pre, count, fold_convert (TREE_TYPE (count), argse.expr));
12162 1.1 mrg
12163 1.1 mrg if (stat != NULL_TREE)
12164 1.1 mrg gfc_add_modify (&se.pre, stat, build_int_cst (TREE_TYPE (stat), 0));
12165 1.1 mrg
12166 1.1 mrg return gfc_finish_block (&se.pre);
12167 1.1 mrg }
12168 1.1 mrg
12169 1.1 mrg
12170 1.1 mrg /* This is a peculiar case because of the need to do dependency checking.
12171 1.1 mrg It is called via trans-stmt.cc(gfc_trans_call), where it is picked out as
12172 1.1 mrg a special case and this function called instead of
12173 1.1 mrg gfc_conv_procedure_call. */
12174 1.1 mrg void
12175 1.1 mrg gfc_conv_intrinsic_mvbits (gfc_se *se, gfc_actual_arglist *actual_args,
12176 1.1 mrg gfc_loopinfo *loop)
12177 1.1 mrg {
12178 1.1 mrg gfc_actual_arglist *actual;
12179 1.1 mrg gfc_se argse[5];
12180 1.1 mrg gfc_expr *arg[5];
12181 1.1 mrg gfc_ss *lss;
12182 1.1 mrg int n;
12183 1.1 mrg
12184 1.1 mrg tree from, frompos, len, to, topos;
12185 1.1 mrg tree lenmask, oldbits, newbits, bitsize;
12186 1.1 mrg tree type, utype, above, mask1, mask2;
12187 1.1 mrg
12188 1.1 mrg if (loop)
12189 1.1 mrg lss = loop->ss;
12190 1.1 mrg else
12191 1.1 mrg lss = gfc_ss_terminator;
12192 1.1 mrg
12193 1.1 mrg actual = actual_args;
12194 1.1 mrg for (n = 0; n < 5; n++, actual = actual->next)
12195 1.1 mrg {
12196 1.1 mrg arg[n] = actual->expr;
12197 1.1 mrg gfc_init_se (&argse[n], NULL);
12198 1.1 mrg
12199 1.1 mrg if (lss != gfc_ss_terminator)
12200 1.1 mrg {
12201 1.1 mrg gfc_copy_loopinfo_to_se (&argse[n], loop);
12202 1.1 mrg /* Find the ss for the expression if it is there. */
12203 1.1 mrg argse[n].ss = lss;
12204 1.1 mrg gfc_mark_ss_chain_used (lss, 1);
12205 1.1 mrg }
12206 1.1 mrg
12207 1.1 mrg gfc_conv_expr (&argse[n], arg[n]);
12208 1.1 mrg
12209 1.1 mrg if (loop)
12210 1.1 mrg lss = argse[n].ss;
12211 1.1 mrg }
12212 1.1 mrg
12213 1.1 mrg from = argse[0].expr;
12214 1.1 mrg frompos = argse[1].expr;
12215 1.1 mrg len = argse[2].expr;
12216 1.1 mrg to = argse[3].expr;
12217 1.1 mrg topos = argse[4].expr;
12218 1.1 mrg
12219 1.1 mrg /* The type of the result (TO). */
12220 1.1 mrg type = TREE_TYPE (to);
12221 1.1 mrg bitsize = build_int_cst (integer_type_node, TYPE_PRECISION (type));
12222 1.1 mrg
12223 1.1 mrg /* Optionally generate code for runtime argument check. */
12224 1.1 mrg if (gfc_option.rtcheck & GFC_RTCHECK_BITS)
12225 1.1 mrg {
12226 1.1 mrg tree nbits, below, ccond;
12227 1.1 mrg tree fp = fold_convert (long_integer_type_node, frompos);
12228 1.1 mrg tree ln = fold_convert (long_integer_type_node, len);
12229 1.1 mrg tree tp = fold_convert (long_integer_type_node, topos);
12230 1.1 mrg below = fold_build2_loc (input_location, LT_EXPR,
12231 1.1 mrg logical_type_node, frompos,
12232 1.1 mrg build_int_cst (TREE_TYPE (frompos), 0));
12233 1.1 mrg above = fold_build2_loc (input_location, GT_EXPR,
12234 1.1 mrg logical_type_node, frompos,
12235 1.1 mrg fold_convert (TREE_TYPE (frompos), bitsize));
12236 1.1 mrg ccond = fold_build2_loc (input_location, TRUTH_ORIF_EXPR,
12237 1.1 mrg logical_type_node, below, above);
12238 1.1 mrg gfc_trans_runtime_check (true, false, ccond, &argse[1].pre,
12239 1.1 mrg &arg[1]->where,
12240 1.1 mrg "FROMPOS argument (%ld) out of range 0:%d "
12241 1.1 mrg "in intrinsic MVBITS", fp, bitsize);
12242 1.1 mrg below = fold_build2_loc (input_location, LT_EXPR,
12243 1.1 mrg logical_type_node, len,
12244 1.1 mrg build_int_cst (TREE_TYPE (len), 0));
12245 1.1 mrg above = fold_build2_loc (input_location, GT_EXPR,
12246 1.1 mrg logical_type_node, len,
12247 1.1 mrg fold_convert (TREE_TYPE (len), bitsize));
12248 1.1 mrg ccond = fold_build2_loc (input_location, TRUTH_ORIF_EXPR,
12249 1.1 mrg logical_type_node, below, above);
12250 1.1 mrg gfc_trans_runtime_check (true, false, ccond, &argse[2].pre,
12251 1.1 mrg &arg[2]->where,
12252 1.1 mrg "LEN argument (%ld) out of range 0:%d "
12253 1.1 mrg "in intrinsic MVBITS", ln, bitsize);
12254 1.1 mrg below = fold_build2_loc (input_location, LT_EXPR,
12255 1.1 mrg logical_type_node, topos,
12256 1.1 mrg build_int_cst (TREE_TYPE (topos), 0));
12257 1.1 mrg above = fold_build2_loc (input_location, GT_EXPR,
12258 1.1 mrg logical_type_node, topos,
12259 1.1 mrg fold_convert (TREE_TYPE (topos), bitsize));
12260 1.1 mrg ccond = fold_build2_loc (input_location, TRUTH_ORIF_EXPR,
12261 1.1 mrg logical_type_node, below, above);
12262 1.1 mrg gfc_trans_runtime_check (true, false, ccond, &argse[4].pre,
12263 1.1 mrg &arg[4]->where,
12264 1.1 mrg "TOPOS argument (%ld) out of range 0:%d "
12265 1.1 mrg "in intrinsic MVBITS", tp, bitsize);
12266 1.1 mrg
12267 1.1 mrg /* The tests above ensure that FROMPOS, LEN and TOPOS fit into short
12268 1.1 mrg integers. Additions below cannot overflow. */
12269 1.1 mrg nbits = fold_convert (long_integer_type_node, bitsize);
12270 1.1 mrg above = fold_build2_loc (input_location, PLUS_EXPR,
12271 1.1 mrg long_integer_type_node, fp, ln);
12272 1.1 mrg ccond = fold_build2_loc (input_location, GT_EXPR,
12273 1.1 mrg logical_type_node, above, nbits);
12274 1.1 mrg gfc_trans_runtime_check (true, false, ccond, &argse[1].pre,
12275 1.1 mrg &arg[1]->where,
12276 1.1 mrg "FROMPOS(%ld)+LEN(%ld)>BIT_SIZE(%d) "
12277 1.1 mrg "in intrinsic MVBITS", fp, ln, bitsize);
12278 1.1 mrg above = fold_build2_loc (input_location, PLUS_EXPR,
12279 1.1 mrg long_integer_type_node, tp, ln);
12280 1.1 mrg ccond = fold_build2_loc (input_location, GT_EXPR,
12281 1.1 mrg logical_type_node, above, nbits);
12282 1.1 mrg gfc_trans_runtime_check (true, false, ccond, &argse[4].pre,
12283 1.1 mrg &arg[4]->where,
12284 1.1 mrg "TOPOS(%ld)+LEN(%ld)>BIT_SIZE(%d) "
12285 1.1 mrg "in intrinsic MVBITS", tp, ln, bitsize);
12286 1.1 mrg }
12287 1.1 mrg
12288 1.1 mrg for (n = 0; n < 5; n++)
12289 1.1 mrg {
12290 1.1 mrg gfc_add_block_to_block (&se->pre, &argse[n].pre);
12291 1.1 mrg gfc_add_block_to_block (&se->post, &argse[n].post);
12292 1.1 mrg }
12293 1.1 mrg
12294 1.1 mrg /* lenmask = (LEN >= bit_size (TYPE)) ? ~(TYPE)0 : ((TYPE)1 << LEN) - 1 */
12295 1.1 mrg above = fold_build2_loc (input_location, GE_EXPR, logical_type_node,
12296 1.1 mrg len, fold_convert (TREE_TYPE (len), bitsize));
12297 1.1 mrg mask1 = build_int_cst (type, -1);
12298 1.1 mrg mask2 = fold_build2_loc (input_location, LSHIFT_EXPR, type,
12299 1.1 mrg build_int_cst (type, 1), len);
12300 1.1 mrg mask2 = fold_build2_loc (input_location, MINUS_EXPR, type,
12301 1.1 mrg mask2, build_int_cst (type, 1));
12302 1.1 mrg lenmask = fold_build3_loc (input_location, COND_EXPR, type,
12303 1.1 mrg above, mask1, mask2);
12304 1.1 mrg
12305 1.1 mrg /* newbits = (((UTYPE)(FROM) >> FROMPOS) & lenmask) << TOPOS.
12306 1.1 mrg * For valid frompos+len <= bit_size(FROM) the conversion to unsigned is
12307 1.1 mrg * not strictly necessary; artificial bits from rshift will be masked. */
12308 1.1 mrg utype = unsigned_type_for (type);
12309 1.1 mrg newbits = fold_build2_loc (input_location, RSHIFT_EXPR, utype,
12310 1.1 mrg fold_convert (utype, from), frompos);
12311 1.1 mrg newbits = fold_build2_loc (input_location, BIT_AND_EXPR, type,
12312 1.1 mrg fold_convert (type, newbits), lenmask);
12313 1.1 mrg newbits = fold_build2_loc (input_location, LSHIFT_EXPR, type,
12314 1.1 mrg newbits, topos);
12315 1.1 mrg
12316 1.1 mrg /* oldbits = TO & (~(lenmask << TOPOS)). */
12317 1.1 mrg oldbits = fold_build2_loc (input_location, LSHIFT_EXPR, type,
12318 1.1 mrg lenmask, topos);
12319 1.1 mrg oldbits = fold_build1_loc (input_location, BIT_NOT_EXPR, type, oldbits);
12320 1.1 mrg oldbits = fold_build2_loc (input_location, BIT_AND_EXPR, type, oldbits, to);
12321 1.1 mrg
12322 1.1 mrg /* TO = newbits | oldbits. */
12323 1.1 mrg se->expr = fold_build2_loc (input_location, BIT_IOR_EXPR, type,
12324 1.1 mrg oldbits, newbits);
12325 1.1 mrg
12326 1.1 mrg /* Return the assignment. */
12327 1.1 mrg se->expr = fold_build2_loc (input_location, MODIFY_EXPR,
12328 1.1 mrg void_type_node, to, se->expr);
12329 1.1 mrg }
12330 1.1 mrg
12331 1.1 mrg
12332 1.1 mrg static tree
12333 1.1 mrg conv_intrinsic_move_alloc (gfc_code *code)
12334 1.1 mrg {
12335 1.1 mrg stmtblock_t block;
12336 1.1 mrg gfc_expr *from_expr, *to_expr;
12337 1.1 mrg gfc_expr *to_expr2, *from_expr2 = NULL;
12338 1.1 mrg gfc_se from_se, to_se;
12339 1.1 mrg tree tmp;
12340 1.1 mrg bool coarray;
12341 1.1 mrg
12342 1.1 mrg gfc_start_block (&block);
12343 1.1 mrg
12344 1.1 mrg from_expr = code->ext.actual->expr;
12345 1.1 mrg to_expr = code->ext.actual->next->expr;
12346 1.1 mrg
12347 1.1 mrg gfc_init_se (&from_se, NULL);
12348 1.1 mrg gfc_init_se (&to_se, NULL);
12349 1.1 mrg
12350 1.1 mrg gcc_assert (from_expr->ts.type != BT_CLASS
12351 1.1 mrg || to_expr->ts.type == BT_CLASS);
12352 1.1 mrg coarray = gfc_get_corank (from_expr) != 0;
12353 1.1 mrg
12354 1.1 mrg if (from_expr->rank == 0 && !coarray)
12355 1.1 mrg {
12356 1.1 mrg if (from_expr->ts.type != BT_CLASS)
12357 1.1 mrg from_expr2 = from_expr;
12358 1.1 mrg else
12359 1.1 mrg {
12360 1.1 mrg from_expr2 = gfc_copy_expr (from_expr);
12361 1.1 mrg gfc_add_data_component (from_expr2);
12362 1.1 mrg }
12363 1.1 mrg
12364 1.1 mrg if (to_expr->ts.type != BT_CLASS)
12365 1.1 mrg to_expr2 = to_expr;
12366 1.1 mrg else
12367 1.1 mrg {
12368 1.1 mrg to_expr2 = gfc_copy_expr (to_expr);
12369 1.1 mrg gfc_add_data_component (to_expr2);
12370 1.1 mrg }
12371 1.1 mrg
12372 1.1 mrg from_se.want_pointer = 1;
12373 1.1 mrg to_se.want_pointer = 1;
12374 1.1 mrg gfc_conv_expr (&from_se, from_expr2);
12375 1.1 mrg gfc_conv_expr (&to_se, to_expr2);
12376 1.1 mrg gfc_add_block_to_block (&block, &from_se.pre);
12377 1.1 mrg gfc_add_block_to_block (&block, &to_se.pre);
12378 1.1 mrg
12379 1.1 mrg /* Deallocate "to". */
12380 1.1 mrg tmp = gfc_deallocate_scalar_with_status (to_se.expr, NULL_TREE, NULL_TREE,
12381 1.1 mrg true, to_expr, to_expr->ts);
12382 1.1 mrg gfc_add_expr_to_block (&block, tmp);
12383 1.1 mrg
12384 1.1 mrg /* Assign (_data) pointers. */
12385 1.1 mrg gfc_add_modify_loc (input_location, &block, to_se.expr,
12386 1.1 mrg fold_convert (TREE_TYPE (to_se.expr), from_se.expr));
12387 1.1 mrg
12388 1.1 mrg /* Set "from" to NULL. */
12389 1.1 mrg gfc_add_modify_loc (input_location, &block, from_se.expr,
12390 1.1 mrg fold_convert (TREE_TYPE (from_se.expr), null_pointer_node));
12391 1.1 mrg
12392 1.1 mrg gfc_add_block_to_block (&block, &from_se.post);
12393 1.1 mrg gfc_add_block_to_block (&block, &to_se.post);
12394 1.1 mrg
12395 1.1 mrg /* Set _vptr. */
12396 1.1 mrg if (to_expr->ts.type == BT_CLASS)
12397 1.1 mrg {
12398 1.1 mrg gfc_symbol *vtab;
12399 1.1 mrg
12400 1.1 mrg gfc_free_expr (to_expr2);
12401 1.1 mrg gfc_init_se (&to_se, NULL);
12402 1.1 mrg to_se.want_pointer = 1;
12403 1.1 mrg gfc_add_vptr_component (to_expr);
12404 1.1 mrg gfc_conv_expr (&to_se, to_expr);
12405 1.1 mrg
12406 1.1 mrg if (from_expr->ts.type == BT_CLASS)
12407 1.1 mrg {
12408 1.1 mrg if (UNLIMITED_POLY (from_expr))
12409 1.1 mrg vtab = NULL;
12410 1.1 mrg else
12411 1.1 mrg {
12412 1.1 mrg vtab = gfc_find_derived_vtab (from_expr->ts.u.derived);
12413 1.1 mrg gcc_assert (vtab);
12414 1.1 mrg }
12415 1.1 mrg
12416 1.1 mrg gfc_free_expr (from_expr2);
12417 1.1 mrg gfc_init_se (&from_se, NULL);
12418 1.1 mrg from_se.want_pointer = 1;
12419 1.1 mrg gfc_add_vptr_component (from_expr);
12420 1.1 mrg gfc_conv_expr (&from_se, from_expr);
12421 1.1 mrg gfc_add_modify_loc (input_location, &block, to_se.expr,
12422 1.1 mrg fold_convert (TREE_TYPE (to_se.expr),
12423 1.1 mrg from_se.expr));
12424 1.1 mrg
12425 1.1 mrg /* Reset _vptr component to declared type. */
12426 1.1 mrg if (vtab == NULL)
12427 1.1 mrg /* Unlimited polymorphic. */
12428 1.1 mrg gfc_add_modify_loc (input_location, &block, from_se.expr,
12429 1.1 mrg fold_convert (TREE_TYPE (from_se.expr),
12430 1.1 mrg null_pointer_node));
12431 1.1 mrg else
12432 1.1 mrg {
12433 1.1 mrg tmp = gfc_build_addr_expr (NULL_TREE, gfc_get_symbol_decl (vtab));
12434 1.1 mrg gfc_add_modify_loc (input_location, &block, from_se.expr,
12435 1.1 mrg fold_convert (TREE_TYPE (from_se.expr), tmp));
12436 1.1 mrg }
12437 1.1 mrg }
12438 1.1 mrg else
12439 1.1 mrg {
12440 1.1 mrg vtab = gfc_find_vtab (&from_expr->ts);
12441 1.1 mrg gcc_assert (vtab);
12442 1.1 mrg tmp = gfc_build_addr_expr (NULL_TREE, gfc_get_symbol_decl (vtab));
12443 1.1 mrg gfc_add_modify_loc (input_location, &block, to_se.expr,
12444 1.1 mrg fold_convert (TREE_TYPE (to_se.expr), tmp));
12445 1.1 mrg }
12446 1.1 mrg }
12447 1.1 mrg
12448 1.1 mrg if (to_expr->ts.type == BT_CHARACTER && to_expr->ts.deferred)
12449 1.1 mrg {
12450 1.1 mrg gfc_add_modify_loc (input_location, &block, to_se.string_length,
12451 1.1 mrg fold_convert (TREE_TYPE (to_se.string_length),
12452 1.1 mrg from_se.string_length));
12453 1.1 mrg if (from_expr->ts.deferred)
12454 1.1 mrg gfc_add_modify_loc (input_location, &block, from_se.string_length,
12455 1.1 mrg build_int_cst (TREE_TYPE (from_se.string_length), 0));
12456 1.1 mrg }
12457 1.1 mrg
12458 1.1 mrg return gfc_finish_block (&block);
12459 1.1 mrg }
12460 1.1 mrg
12461 1.1 mrg /* Update _vptr component. */
12462 1.1 mrg if (to_expr->ts.type == BT_CLASS)
12463 1.1 mrg {
12464 1.1 mrg gfc_symbol *vtab;
12465 1.1 mrg
12466 1.1 mrg to_se.want_pointer = 1;
12467 1.1 mrg to_expr2 = gfc_copy_expr (to_expr);
12468 1.1 mrg gfc_add_vptr_component (to_expr2);
12469 1.1 mrg gfc_conv_expr (&to_se, to_expr2);
12470 1.1 mrg
12471 1.1 mrg if (from_expr->ts.type == BT_CLASS)
12472 1.1 mrg {
12473 1.1 mrg if (UNLIMITED_POLY (from_expr))
12474 1.1 mrg vtab = NULL;
12475 1.1 mrg else
12476 1.1 mrg {
12477 1.1 mrg vtab = gfc_find_derived_vtab (from_expr->ts.u.derived);
12478 1.1 mrg gcc_assert (vtab);
12479 1.1 mrg }
12480 1.1 mrg
12481 1.1 mrg from_se.want_pointer = 1;
12482 1.1 mrg from_expr2 = gfc_copy_expr (from_expr);
12483 1.1 mrg gfc_add_vptr_component (from_expr2);
12484 1.1 mrg gfc_conv_expr (&from_se, from_expr2);
12485 1.1 mrg gfc_add_modify_loc (input_location, &block, to_se.expr,
12486 1.1 mrg fold_convert (TREE_TYPE (to_se.expr),
12487 1.1 mrg from_se.expr));
12488 1.1 mrg
12489 1.1 mrg /* Reset _vptr component to declared type. */
12490 1.1 mrg if (vtab == NULL)
12491 1.1 mrg /* Unlimited polymorphic. */
12492 1.1 mrg gfc_add_modify_loc (input_location, &block, from_se.expr,
12493 1.1 mrg fold_convert (TREE_TYPE (from_se.expr),
12494 1.1 mrg null_pointer_node));
12495 1.1 mrg else
12496 1.1 mrg {
12497 1.1 mrg tmp = gfc_build_addr_expr (NULL_TREE, gfc_get_symbol_decl (vtab));
12498 1.1 mrg gfc_add_modify_loc (input_location, &block, from_se.expr,
12499 1.1 mrg fold_convert (TREE_TYPE (from_se.expr), tmp));
12500 1.1 mrg }
12501 1.1 mrg }
12502 1.1 mrg else
12503 1.1 mrg {
12504 1.1 mrg vtab = gfc_find_vtab (&from_expr->ts);
12505 1.1 mrg gcc_assert (vtab);
12506 1.1 mrg tmp = gfc_build_addr_expr (NULL_TREE, gfc_get_symbol_decl (vtab));
12507 1.1 mrg gfc_add_modify_loc (input_location, &block, to_se.expr,
12508 1.1 mrg fold_convert (TREE_TYPE (to_se.expr), tmp));
12509 1.1 mrg }
12510 1.1 mrg
12511 1.1 mrg gfc_free_expr (to_expr2);
12512 1.1 mrg gfc_init_se (&to_se, NULL);
12513 1.1 mrg
12514 1.1 mrg if (from_expr->ts.type == BT_CLASS)
12515 1.1 mrg {
12516 1.1 mrg gfc_free_expr (from_expr2);
12517 1.1 mrg gfc_init_se (&from_se, NULL);
12518 1.1 mrg }
12519 1.1 mrg }
12520 1.1 mrg
12521 1.1 mrg
12522 1.1 mrg /* Deallocate "to". */
12523 1.1 mrg if (from_expr->rank == 0)
12524 1.1 mrg {
12525 1.1 mrg to_se.want_coarray = 1;
12526 1.1 mrg from_se.want_coarray = 1;
12527 1.1 mrg }
12528 1.1 mrg gfc_conv_expr_descriptor (&to_se, to_expr);
12529 1.1 mrg gfc_conv_expr_descriptor (&from_se, from_expr);
12530 1.1 mrg
12531 1.1 mrg /* For coarrays, call SYNC ALL if TO is already deallocated as MOVE_ALLOC
12532 1.1 mrg is an image control "statement", cf. IR F08/0040 in 12-006A. */
12533 1.1 mrg if (coarray && flag_coarray == GFC_FCOARRAY_LIB)
12534 1.1 mrg {
12535 1.1 mrg tree cond;
12536 1.1 mrg
12537 1.1 mrg tmp = gfc_deallocate_with_status (to_se.expr, NULL_TREE, NULL_TREE,
12538 1.1 mrg NULL_TREE, NULL_TREE, true, to_expr,
12539 1.1 mrg GFC_CAF_COARRAY_DEALLOCATE_ONLY);
12540 1.1 mrg gfc_add_expr_to_block (&block, tmp);
12541 1.1 mrg
12542 1.1 mrg tmp = gfc_conv_descriptor_data_get (to_se.expr);
12543 1.1 mrg cond = fold_build2_loc (input_location, EQ_EXPR,
12544 1.1 mrg logical_type_node, tmp,
12545 1.1 mrg fold_convert (TREE_TYPE (tmp),
12546 1.1 mrg null_pointer_node));
12547 1.1 mrg tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_sync_all,
12548 1.1 mrg 3, null_pointer_node, null_pointer_node,
12549 1.1 mrg build_int_cst (integer_type_node, 0));
12550 1.1 mrg
12551 1.1 mrg tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node, cond,
12552 1.1 mrg tmp, build_empty_stmt (input_location));
12553 1.1 mrg gfc_add_expr_to_block (&block, tmp);
12554 1.1 mrg }
12555 1.1 mrg else
12556 1.1 mrg {
12557 1.1 mrg if (to_expr->ts.type == BT_DERIVED
12558 1.1 mrg && to_expr->ts.u.derived->attr.alloc_comp)
12559 1.1 mrg {
12560 1.1 mrg tmp = gfc_deallocate_alloc_comp (to_expr->ts.u.derived,
12561 1.1 mrg to_se.expr, to_expr->rank);
12562 1.1 mrg gfc_add_expr_to_block (&block, tmp);
12563 1.1 mrg }
12564 1.1 mrg
12565 1.1 mrg tmp = gfc_conv_descriptor_data_get (to_se.expr);
12566 1.1 mrg tmp = gfc_deallocate_with_status (tmp, NULL_TREE, NULL_TREE, NULL_TREE,
12567 1.1 mrg NULL_TREE, true, to_expr,
12568 1.1 mrg GFC_CAF_COARRAY_NOCOARRAY);
12569 1.1 mrg gfc_add_expr_to_block (&block, tmp);
12570 1.1 mrg }
12571 1.1 mrg
12572 1.1 mrg /* Move the pointer and update the array descriptor data. */
12573 1.1 mrg gfc_add_modify_loc (input_location, &block, to_se.expr, from_se.expr);
12574 1.1 mrg
12575 1.1 mrg /* Set "from" to NULL. */
12576 1.1 mrg tmp = gfc_conv_descriptor_data_get (from_se.expr);
12577 1.1 mrg gfc_add_modify_loc (input_location, &block, tmp,
12578 1.1 mrg fold_convert (TREE_TYPE (tmp), null_pointer_node));
12579 1.1 mrg
12580 1.1 mrg
12581 1.1 mrg if (to_expr->ts.type == BT_CHARACTER && to_expr->ts.deferred)
12582 1.1 mrg {
12583 1.1 mrg gfc_add_modify_loc (input_location, &block, to_se.string_length,
12584 1.1 mrg fold_convert (TREE_TYPE (to_se.string_length),
12585 1.1 mrg from_se.string_length));
12586 1.1 mrg if (from_expr->ts.deferred)
12587 1.1 mrg gfc_add_modify_loc (input_location, &block, from_se.string_length,
12588 1.1 mrg build_int_cst (TREE_TYPE (from_se.string_length), 0));
12589 1.1 mrg }
12590 1.1 mrg
12591 1.1 mrg return gfc_finish_block (&block);
12592 1.1 mrg }
12593 1.1 mrg
12594 1.1 mrg
12595 1.1 mrg tree
12596 1.1 mrg gfc_conv_intrinsic_subroutine (gfc_code *code)
12597 1.1 mrg {
12598 1.1 mrg tree res;
12599 1.1 mrg
12600 1.1 mrg gcc_assert (code->resolved_isym);
12601 1.1 mrg
12602 1.1 mrg switch (code->resolved_isym->id)
12603 1.1 mrg {
12604 1.1 mrg case GFC_ISYM_MOVE_ALLOC:
12605 1.1 mrg res = conv_intrinsic_move_alloc (code);
12606 1.1 mrg break;
12607 1.1 mrg
12608 1.1 mrg case GFC_ISYM_ATOMIC_CAS:
12609 1.1 mrg res = conv_intrinsic_atomic_cas (code);
12610 1.1 mrg break;
12611 1.1 mrg
12612 1.1 mrg case GFC_ISYM_ATOMIC_ADD:
12613 1.1 mrg case GFC_ISYM_ATOMIC_AND:
12614 1.1 mrg case GFC_ISYM_ATOMIC_DEF:
12615 1.1 mrg case GFC_ISYM_ATOMIC_OR:
12616 1.1 mrg case GFC_ISYM_ATOMIC_XOR:
12617 1.1 mrg case GFC_ISYM_ATOMIC_FETCH_ADD:
12618 1.1 mrg case GFC_ISYM_ATOMIC_FETCH_AND:
12619 1.1 mrg case GFC_ISYM_ATOMIC_FETCH_OR:
12620 1.1 mrg case GFC_ISYM_ATOMIC_FETCH_XOR:
12621 1.1 mrg res = conv_intrinsic_atomic_op (code);
12622 1.1 mrg break;
12623 1.1 mrg
12624 1.1 mrg case GFC_ISYM_ATOMIC_REF:
12625 1.1 mrg res = conv_intrinsic_atomic_ref (code);
12626 1.1 mrg break;
12627 1.1 mrg
12628 1.1 mrg case GFC_ISYM_EVENT_QUERY:
12629 1.1 mrg res = conv_intrinsic_event_query (code);
12630 1.1 mrg break;
12631 1.1 mrg
12632 1.1 mrg case GFC_ISYM_C_F_POINTER:
12633 1.1 mrg case GFC_ISYM_C_F_PROCPOINTER:
12634 1.1 mrg res = conv_isocbinding_subroutine (code);
12635 1.1 mrg break;
12636 1.1 mrg
12637 1.1 mrg case GFC_ISYM_CAF_SEND:
12638 1.1 mrg res = conv_caf_send (code);
12639 1.1 mrg break;
12640 1.1 mrg
12641 1.1 mrg case GFC_ISYM_CO_BROADCAST:
12642 1.1 mrg case GFC_ISYM_CO_MIN:
12643 1.1 mrg case GFC_ISYM_CO_MAX:
12644 1.1 mrg case GFC_ISYM_CO_REDUCE:
12645 1.1 mrg case GFC_ISYM_CO_SUM:
12646 1.1 mrg res = conv_co_collective (code);
12647 1.1 mrg break;
12648 1.1 mrg
12649 1.1 mrg case GFC_ISYM_FREE:
12650 1.1 mrg res = conv_intrinsic_free (code);
12651 1.1 mrg break;
12652 1.1 mrg
12653 1.1 mrg case GFC_ISYM_RANDOM_INIT:
12654 1.1 mrg res = conv_intrinsic_random_init (code);
12655 1.1 mrg break;
12656 1.1 mrg
12657 1.1 mrg case GFC_ISYM_KILL:
12658 1.1 mrg res = conv_intrinsic_kill_sub (code);
12659 1.1 mrg break;
12660 1.1 mrg
12661 1.1 mrg case GFC_ISYM_MVBITS:
12662 1.1 mrg res = NULL_TREE;
12663 1.1 mrg break;
12664 1.1 mrg
12665 1.1 mrg case GFC_ISYM_SYSTEM_CLOCK:
12666 1.1 mrg res = conv_intrinsic_system_clock (code);
12667 1.1 mrg break;
12668 1.1 mrg
12669 1.1 mrg default:
12670 1.1 mrg res = NULL_TREE;
12671 1.1 mrg break;
12672 1.1 mrg }
12673 1.1 mrg
12674 1.1 mrg return res;
12675 1.1 mrg }
12676 1.1 mrg
12677 1.1 mrg #include "gt-fortran-trans-intrinsic.h"
12678