OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-dev/] [or1k-gcc/] [gcc/] [fortran/] [trans-intrinsic.c] - Blame information for rev 801

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 712 jeremybenn
/* Intrinsic translation
2
   Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
3
   2011, 2012
4
   Free Software Foundation, Inc.
5
   Contributed by Paul Brook <paul@nowt.org>
6
   and Steven Bosscher <s.bosscher@student.tudelft.nl>
7
 
8
This file is part of GCC.
9
 
10
GCC is free software; you can redistribute it and/or modify it under
11
the terms of the GNU General Public License as published by the Free
12
Software Foundation; either version 3, or (at your option) any later
13
version.
14
 
15
GCC is distributed in the hope that it will be useful, but WITHOUT ANY
16
WARRANTY; without even the implied warranty of MERCHANTABILITY or
17
FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
18
for more details.
19
 
20
You should have received a copy of the GNU General Public License
21
along with GCC; see the file COPYING3.  If not see
22
<http://www.gnu.org/licenses/>.  */
23
 
24
/* trans-intrinsic.c-- generate GENERIC trees for calls to intrinsics.  */
25
 
26
#include "config.h"
27
#include "system.h"
28
#include "coretypes.h"
29
#include "tm.h"         /* For UNITS_PER_WORD.  */
30
#include "tree.h"
31
#include "ggc.h"
32
#include "diagnostic-core.h"    /* For internal_error.  */
33
#include "toplev.h"     /* For rest_of_decl_compilation.  */
34
#include "flags.h"
35
#include "gfortran.h"
36
#include "arith.h"
37
#include "intrinsic.h"
38
#include "trans.h"
39
#include "trans-const.h"
40
#include "trans-types.h"
41
#include "trans-array.h"
42
#include "defaults.h"
43
/* Only for gfc_trans_assign and gfc_trans_pointer_assign.  */
44
#include "trans-stmt.h"
45
 
46
/* This maps fortran intrinsic math functions to external library or GCC
47
   builtin functions.  */
48
typedef struct GTY(()) gfc_intrinsic_map_t {
49
  /* The explicit enum is required to work around inadequacies in the
50
     garbage collection/gengtype parsing mechanism.  */
51
  enum gfc_isym_id id;
52
 
53
  /* Enum value from the "language-independent", aka C-centric, part
54
     of gcc, or END_BUILTINS of no such value set.  */
55
  enum built_in_function float_built_in;
56
  enum built_in_function double_built_in;
57
  enum built_in_function long_double_built_in;
58
  enum built_in_function complex_float_built_in;
59
  enum built_in_function complex_double_built_in;
60
  enum built_in_function complex_long_double_built_in;
61
 
62
  /* True if the naming pattern is to prepend "c" for complex and
63
     append "f" for kind=4.  False if the naming pattern is to
64
     prepend "_gfortran_" and append "[rc](4|8|10|16)".  */
65
  bool libm_name;
66
 
67
  /* True if a complex version of the function exists.  */
68
  bool complex_available;
69
 
70
  /* True if the function should be marked const.  */
71
  bool is_constant;
72
 
73
  /* The base library name of this function.  */
74
  const char *name;
75
 
76
  /* Cache decls created for the various operand types.  */
77
  tree real4_decl;
78
  tree real8_decl;
79
  tree real10_decl;
80
  tree real16_decl;
81
  tree complex4_decl;
82
  tree complex8_decl;
83
  tree complex10_decl;
84
  tree complex16_decl;
85
}
86
gfc_intrinsic_map_t;
87
 
88
/* ??? The NARGS==1 hack here is based on the fact that (c99 at least)
89
   defines complex variants of all of the entries in mathbuiltins.def
90
   except for atan2.  */
91
#define DEFINE_MATH_BUILTIN(ID, NAME, ARGTYPE) \
92
  { GFC_ISYM_ ## ID, BUILT_IN_ ## ID ## F, BUILT_IN_ ## ID, \
93
    BUILT_IN_ ## ID ## L, END_BUILTINS, END_BUILTINS, END_BUILTINS, \
94
    true, false, true, NAME, NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE, \
95
    NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE},
96
 
97
#define DEFINE_MATH_BUILTIN_C(ID, NAME, ARGTYPE) \
98
  { GFC_ISYM_ ## ID, BUILT_IN_ ## ID ## F, BUILT_IN_ ## ID, \
99
    BUILT_IN_ ## ID ## L, BUILT_IN_C ## ID ## F, BUILT_IN_C ## ID, \
100
    BUILT_IN_C ## ID ## L, true, true, true, NAME, NULL_TREE, NULL_TREE, \
101
    NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE},
102
 
103
#define LIB_FUNCTION(ID, NAME, HAVE_COMPLEX) \
104
  { GFC_ISYM_ ## ID, END_BUILTINS, END_BUILTINS, END_BUILTINS, \
105
    END_BUILTINS, END_BUILTINS, END_BUILTINS, \
106
    false, HAVE_COMPLEX, true, NAME, NULL_TREE, NULL_TREE, NULL_TREE, \
107
    NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE }
108
 
109
#define OTHER_BUILTIN(ID, NAME, TYPE, CONST) \
110
  { GFC_ISYM_NONE, BUILT_IN_ ## ID ## F, BUILT_IN_ ## ID, \
111
    BUILT_IN_ ## ID ## L, END_BUILTINS, END_BUILTINS, END_BUILTINS, \
112
    true, false, CONST, NAME, NULL_TREE, NULL_TREE, \
113
    NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE},
114
 
115
static GTY(()) gfc_intrinsic_map_t gfc_intrinsic_map[] =
116
{
117
  /* Functions built into gcc itself (DEFINE_MATH_BUILTIN and
118
     DEFINE_MATH_BUILTIN_C), then the built-ins that don't correspond
119
     to any GFC_ISYM id directly, which use the OTHER_BUILTIN macro.  */
120
#include "mathbuiltins.def"
121
 
122
  /* Functions in libgfortran.  */
123
  LIB_FUNCTION (ERFC_SCALED, "erfc_scaled", false),
124
 
125
  /* End the list.  */
126
  LIB_FUNCTION (NONE, NULL, false)
127
 
128
};
129
#undef OTHER_BUILTIN
130
#undef LIB_FUNCTION
131
#undef DEFINE_MATH_BUILTIN
132
#undef DEFINE_MATH_BUILTIN_C
133
 
134
 
135
enum rounding_mode { RND_ROUND, RND_TRUNC, RND_CEIL, RND_FLOOR };
136
 
137
 
138
/* Find the correct variant of a given builtin from its argument.  */
139
static tree
140
builtin_decl_for_precision (enum built_in_function base_built_in,
141
                            int precision)
142
{
143
  enum built_in_function i = END_BUILTINS;
144
 
145
  gfc_intrinsic_map_t *m;
146
  for (m = gfc_intrinsic_map; m->double_built_in != base_built_in ; m++)
147
    ;
148
 
149
  if (precision == TYPE_PRECISION (float_type_node))
150
    i = m->float_built_in;
151
  else if (precision == TYPE_PRECISION (double_type_node))
152
    i = m->double_built_in;
153
  else if (precision == TYPE_PRECISION (long_double_type_node))
154
    i = m->long_double_built_in;
155
  else if (precision == TYPE_PRECISION (float128_type_node))
156
    {
157
      /* Special treatment, because it is not exactly a built-in, but
158
         a library function.  */
159
      return m->real16_decl;
160
    }
161
 
162
  return (i == END_BUILTINS ? NULL_TREE : builtin_decl_explicit (i));
163
}
164
 
165
 
166
tree
167
gfc_builtin_decl_for_float_kind (enum built_in_function double_built_in,
168
                                 int kind)
169
{
170
  int i = gfc_validate_kind (BT_REAL, kind, false);
171
 
172
  if (gfc_real_kinds[i].c_float128)
173
    {
174
      /* For __float128, the story is a bit different, because we return
175
         a decl to a library function rather than a built-in.  */
176
      gfc_intrinsic_map_t *m;
177
      for (m = gfc_intrinsic_map; m->double_built_in != double_built_in ; m++)
178
        ;
179
 
180
      return m->real16_decl;
181
    }
182
 
183
  return builtin_decl_for_precision (double_built_in,
184
                                     gfc_real_kinds[i].mode_precision);
185
}
186
 
187
 
188
/* Evaluate the arguments to an intrinsic function.  The value
189
   of NARGS may be less than the actual number of arguments in EXPR
190
   to allow optional "KIND" arguments that are not included in the
191
   generated code to be ignored.  */
192
 
193
static void
194
gfc_conv_intrinsic_function_args (gfc_se *se, gfc_expr *expr,
195
                                  tree *argarray, int nargs)
196
{
197
  gfc_actual_arglist *actual;
198
  gfc_expr *e;
199
  gfc_intrinsic_arg  *formal;
200
  gfc_se argse;
201
  int curr_arg;
202
 
203
  formal = expr->value.function.isym->formal;
204
  actual = expr->value.function.actual;
205
 
206
   for (curr_arg = 0; curr_arg < nargs; curr_arg++,
207
        actual = actual->next,
208
        formal = formal ? formal->next : NULL)
209
    {
210
      gcc_assert (actual);
211
      e = actual->expr;
212
      /* Skip omitted optional arguments.  */
213
      if (!e)
214
        {
215
          --curr_arg;
216
          continue;
217
        }
218
 
219
      /* Evaluate the parameter.  This will substitute scalarized
220
         references automatically.  */
221
      gfc_init_se (&argse, se);
222
 
223
      if (e->ts.type == BT_CHARACTER)
224
        {
225
          gfc_conv_expr (&argse, e);
226
          gfc_conv_string_parameter (&argse);
227
          argarray[curr_arg++] = argse.string_length;
228
          gcc_assert (curr_arg < nargs);
229
        }
230
      else
231
        gfc_conv_expr_val (&argse, e);
232
 
233
      /* If an optional argument is itself an optional dummy argument,
234
         check its presence and substitute a null if absent.  */
235
      if (e->expr_type == EXPR_VARIABLE
236
            && e->symtree->n.sym->attr.optional
237
            && formal
238
            && formal->optional)
239
        gfc_conv_missing_dummy (&argse, e, formal->ts, 0);
240
 
241
      gfc_add_block_to_block (&se->pre, &argse.pre);
242
      gfc_add_block_to_block (&se->post, &argse.post);
243
      argarray[curr_arg] = argse.expr;
244
    }
245
}
246
 
247
/* Count the number of actual arguments to the intrinsic function EXPR
248
   including any "hidden" string length arguments.  */
249
 
250
static unsigned int
251
gfc_intrinsic_argument_list_length (gfc_expr *expr)
252
{
253
  int n = 0;
254
  gfc_actual_arglist *actual;
255
 
256
  for (actual = expr->value.function.actual; actual; actual = actual->next)
257
    {
258
      if (!actual->expr)
259
        continue;
260
 
261
      if (actual->expr->ts.type == BT_CHARACTER)
262
        n += 2;
263
      else
264
        n++;
265
    }
266
 
267
  return n;
268
}
269
 
270
 
271
/* Conversions between different types are output by the frontend as
272
   intrinsic functions.  We implement these directly with inline code.  */
273
 
274
static void
275
gfc_conv_intrinsic_conversion (gfc_se * se, gfc_expr * expr)
276
{
277
  tree type;
278
  tree *args;
279
  int nargs;
280
 
281
  nargs = gfc_intrinsic_argument_list_length (expr);
282
  args = XALLOCAVEC (tree, nargs);
283
 
284
  /* Evaluate all the arguments passed. Whilst we're only interested in the
285
     first one here, there are other parts of the front-end that assume this
286
     and will trigger an ICE if it's not the case.  */
287
  type = gfc_typenode_for_spec (&expr->ts);
288
  gcc_assert (expr->value.function.actual->expr);
289
  gfc_conv_intrinsic_function_args (se, expr, args, nargs);
290
 
291
  /* Conversion between character kinds involves a call to a library
292
     function.  */
293
  if (expr->ts.type == BT_CHARACTER)
294
    {
295
      tree fndecl, var, addr, tmp;
296
 
297
      if (expr->ts.kind == 1
298
          && expr->value.function.actual->expr->ts.kind == 4)
299
        fndecl = gfor_fndecl_convert_char4_to_char1;
300
      else if (expr->ts.kind == 4
301
               && expr->value.function.actual->expr->ts.kind == 1)
302
        fndecl = gfor_fndecl_convert_char1_to_char4;
303
      else
304
        gcc_unreachable ();
305
 
306
      /* Create the variable storing the converted value.  */
307
      type = gfc_get_pchar_type (expr->ts.kind);
308
      var = gfc_create_var (type, "str");
309
      addr = gfc_build_addr_expr (build_pointer_type (type), var);
310
 
311
      /* Call the library function that will perform the conversion.  */
312
      gcc_assert (nargs >= 2);
313
      tmp = build_call_expr_loc (input_location,
314
                             fndecl, 3, addr, args[0], args[1]);
315
      gfc_add_expr_to_block (&se->pre, tmp);
316
 
317
      /* Free the temporary afterwards.  */
318
      tmp = gfc_call_free (var);
319
      gfc_add_expr_to_block (&se->post, tmp);
320
 
321
      se->expr = var;
322
      se->string_length = args[0];
323
 
324
      return;
325
    }
326
 
327
  /* Conversion from complex to non-complex involves taking the real
328
     component of the value.  */
329
  if (TREE_CODE (TREE_TYPE (args[0])) == COMPLEX_TYPE
330
      && expr->ts.type != BT_COMPLEX)
331
    {
332
      tree artype;
333
 
334
      artype = TREE_TYPE (TREE_TYPE (args[0]));
335
      args[0] = fold_build1_loc (input_location, REALPART_EXPR, artype,
336
                                 args[0]);
337
    }
338
 
339
  se->expr = convert (type, args[0]);
340
}
341
 
342
/* This is needed because the gcc backend only implements
343
   FIX_TRUNC_EXPR, which is the same as INT() in Fortran.
344
   FLOOR(x) = INT(x) <= x ? INT(x) : INT(x) - 1
345
   Similarly for CEILING.  */
346
 
347
static tree
348
build_fixbound_expr (stmtblock_t * pblock, tree arg, tree type, int up)
349
{
350
  tree tmp;
351
  tree cond;
352
  tree argtype;
353
  tree intval;
354
 
355
  argtype = TREE_TYPE (arg);
356
  arg = gfc_evaluate_now (arg, pblock);
357
 
358
  intval = convert (type, arg);
359
  intval = gfc_evaluate_now (intval, pblock);
360
 
361
  tmp = convert (argtype, intval);
362
  cond = fold_build2_loc (input_location, up ? GE_EXPR : LE_EXPR,
363
                          boolean_type_node, tmp, arg);
364
 
365
  tmp = fold_build2_loc (input_location, up ? PLUS_EXPR : MINUS_EXPR, type,
366
                         intval, build_int_cst (type, 1));
367
  tmp = fold_build3_loc (input_location, COND_EXPR, type, cond, intval, tmp);
368
  return tmp;
369
}
370
 
371
 
372
/* Round to nearest integer, away from zero.  */
373
 
374
static tree
375
build_round_expr (tree arg, tree restype)
376
{
377
  tree argtype;
378
  tree fn;
379
  bool longlong;
380
  int argprec, resprec;
381
 
382
  argtype = TREE_TYPE (arg);
383
  argprec = TYPE_PRECISION (argtype);
384
  resprec = TYPE_PRECISION (restype);
385
 
386
  /* Depending on the type of the result, choose the long int intrinsic
387
     (lround family) or long long intrinsic (llround).  We might also
388
     need to convert the result afterwards.  */
389
  if (resprec <= LONG_TYPE_SIZE)
390
    longlong = false;
391
  else if (resprec <= LONG_LONG_TYPE_SIZE)
392
    longlong = true;
393
  else
394
    gcc_unreachable ();
395
 
396
  /* Now, depending on the argument type, we choose between intrinsics.  */
397
  if (longlong)
398
    fn = builtin_decl_for_precision (BUILT_IN_LLROUND, argprec);
399
  else
400
    fn = builtin_decl_for_precision (BUILT_IN_LROUND, argprec);
401
 
402
  return fold_convert (restype, build_call_expr_loc (input_location,
403
                                                 fn, 1, arg));
404
}
405
 
406
 
407
/* Convert a real to an integer using a specific rounding mode.
408
   Ideally we would just build the corresponding GENERIC node,
409
   however the RTL expander only actually supports FIX_TRUNC_EXPR.  */
410
 
411
static tree
412
build_fix_expr (stmtblock_t * pblock, tree arg, tree type,
413
               enum rounding_mode op)
414
{
415
  switch (op)
416
    {
417
    case RND_FLOOR:
418
      return build_fixbound_expr (pblock, arg, type, 0);
419
      break;
420
 
421
    case RND_CEIL:
422
      return build_fixbound_expr (pblock, arg, type, 1);
423
      break;
424
 
425
    case RND_ROUND:
426
      return build_round_expr (arg, type);
427
      break;
428
 
429
    case RND_TRUNC:
430
      return fold_build1_loc (input_location, FIX_TRUNC_EXPR, type, arg);
431
      break;
432
 
433
    default:
434
      gcc_unreachable ();
435
    }
436
}
437
 
438
 
439
/* Round a real value using the specified rounding mode.
440
   We use a temporary integer of that same kind size as the result.
441
   Values larger than those that can be represented by this kind are
442
   unchanged, as they will not be accurate enough to represent the
443
   rounding.
444
    huge = HUGE (KIND (a))
445
    aint (a) = ((a > huge) || (a < -huge)) ? a : (real)(int)a
446
   */
447
 
448
static void
449
gfc_conv_intrinsic_aint (gfc_se * se, gfc_expr * expr, enum rounding_mode op)
450
{
451
  tree type;
452
  tree itype;
453
  tree arg[2];
454
  tree tmp;
455
  tree cond;
456
  tree decl;
457
  mpfr_t huge;
458
  int n, nargs;
459
  int kind;
460
 
461
  kind = expr->ts.kind;
462
  nargs = gfc_intrinsic_argument_list_length (expr);
463
 
464
  decl = NULL_TREE;
465
  /* We have builtin functions for some cases.  */
466
  switch (op)
467
    {
468
    case RND_ROUND:
469
      decl = gfc_builtin_decl_for_float_kind (BUILT_IN_ROUND, kind);
470
      break;
471
 
472
    case RND_TRUNC:
473
      decl = gfc_builtin_decl_for_float_kind (BUILT_IN_TRUNC, kind);
474
      break;
475
 
476
    default:
477
      gcc_unreachable ();
478
    }
479
 
480
  /* Evaluate the argument.  */
481
  gcc_assert (expr->value.function.actual->expr);
482
  gfc_conv_intrinsic_function_args (se, expr, arg, nargs);
483
 
484
  /* Use a builtin function if one exists.  */
485
  if (decl != NULL_TREE)
486
    {
487
      se->expr = build_call_expr_loc (input_location, decl, 1, arg[0]);
488
      return;
489
    }
490
 
491
  /* This code is probably redundant, but we'll keep it lying around just
492
     in case.  */
493
  type = gfc_typenode_for_spec (&expr->ts);
494
  arg[0] = gfc_evaluate_now (arg[0], &se->pre);
495
 
496
  /* Test if the value is too large to handle sensibly.  */
497
  gfc_set_model_kind (kind);
498
  mpfr_init (huge);
499
  n = gfc_validate_kind (BT_INTEGER, kind, false);
500
  mpfr_set_z (huge, gfc_integer_kinds[n].huge, GFC_RND_MODE);
501
  tmp = gfc_conv_mpfr_to_tree (huge, kind, 0);
502
  cond = fold_build2_loc (input_location, LT_EXPR, boolean_type_node, arg[0],
503
                          tmp);
504
 
505
  mpfr_neg (huge, huge, GFC_RND_MODE);
506
  tmp = gfc_conv_mpfr_to_tree (huge, kind, 0);
507
  tmp = fold_build2_loc (input_location, GT_EXPR, boolean_type_node, arg[0],
508
                         tmp);
509
  cond = fold_build2_loc (input_location, TRUTH_AND_EXPR, boolean_type_node,
510
                          cond, tmp);
511
  itype = gfc_get_int_type (kind);
512
 
513
  tmp = build_fix_expr (&se->pre, arg[0], itype, op);
514
  tmp = convert (type, tmp);
515
  se->expr = fold_build3_loc (input_location, COND_EXPR, type, cond, tmp,
516
                              arg[0]);
517
  mpfr_clear (huge);
518
}
519
 
520
 
521
/* Convert to an integer using the specified rounding mode.  */
522
 
523
static void
524
gfc_conv_intrinsic_int (gfc_se * se, gfc_expr * expr, enum rounding_mode op)
525
{
526
  tree type;
527
  tree *args;
528
  int nargs;
529
 
530
  nargs = gfc_intrinsic_argument_list_length (expr);
531
  args = XALLOCAVEC (tree, nargs);
532
 
533
  /* Evaluate the argument, we process all arguments even though we only
534
     use the first one for code generation purposes.  */
535
  type = gfc_typenode_for_spec (&expr->ts);
536
  gcc_assert (expr->value.function.actual->expr);
537
  gfc_conv_intrinsic_function_args (se, expr, args, nargs);
538
 
539
  if (TREE_CODE (TREE_TYPE (args[0])) == INTEGER_TYPE)
540
    {
541
      /* Conversion to a different integer kind.  */
542
      se->expr = convert (type, args[0]);
543
    }
544
  else
545
    {
546
      /* Conversion from complex to non-complex involves taking the real
547
         component of the value.  */
548
      if (TREE_CODE (TREE_TYPE (args[0])) == COMPLEX_TYPE
549
          && expr->ts.type != BT_COMPLEX)
550
        {
551
          tree artype;
552
 
553
          artype = TREE_TYPE (TREE_TYPE (args[0]));
554
          args[0] = fold_build1_loc (input_location, REALPART_EXPR, artype,
555
                                     args[0]);
556
        }
557
 
558
      se->expr = build_fix_expr (&se->pre, args[0], type, op);
559
    }
560
}
561
 
562
 
563
/* Get the imaginary component of a value.  */
564
 
565
static void
566
gfc_conv_intrinsic_imagpart (gfc_se * se, gfc_expr * expr)
567
{
568
  tree arg;
569
 
570
  gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
571
  se->expr = fold_build1_loc (input_location, IMAGPART_EXPR,
572
                              TREE_TYPE (TREE_TYPE (arg)), arg);
573
}
574
 
575
 
576
/* Get the complex conjugate of a value.  */
577
 
578
static void
579
gfc_conv_intrinsic_conjg (gfc_se * se, gfc_expr * expr)
580
{
581
  tree arg;
582
 
583
  gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
584
  se->expr = fold_build1_loc (input_location, CONJ_EXPR, TREE_TYPE (arg), arg);
585
}
586
 
587
 
588
 
589
static tree
590
define_quad_builtin (const char *name, tree type, bool is_const)
591
{
592
  tree fndecl;
593
  fndecl = build_decl (input_location, FUNCTION_DECL, get_identifier (name),
594
                       type);
595
 
596
  /* Mark the decl as external.  */
597
  DECL_EXTERNAL (fndecl) = 1;
598
  TREE_PUBLIC (fndecl) = 1;
599
 
600
  /* Mark it __attribute__((const)).  */
601
  TREE_READONLY (fndecl) = is_const;
602
 
603
  rest_of_decl_compilation (fndecl, 1, 0);
604
 
605
  return fndecl;
606
}
607
 
608
 
609
 
610
/* Initialize function decls for library functions.  The external functions
611
   are created as required.  Builtin functions are added here.  */
612
 
613
void
614
gfc_build_intrinsic_lib_fndecls (void)
615
{
616
  gfc_intrinsic_map_t *m;
617
  tree quad_decls[END_BUILTINS + 1];
618
 
619
  if (gfc_real16_is_float128)
620
  {
621
    /* If we have soft-float types, we create the decls for their
622
       C99-like library functions.  For now, we only handle __float128
623
       q-suffixed functions.  */
624
 
625
    tree type, complex_type, func_1, func_2, func_cabs, func_frexp;
626
    tree func_lround, func_llround, func_scalbn, func_cpow;
627
 
628
    memset (quad_decls, 0, sizeof(tree) * (END_BUILTINS + 1));
629
 
630
    type = float128_type_node;
631
    complex_type = complex_float128_type_node;
632
    /* type (*) (type) */
633
    func_1 = build_function_type_list (type, type, NULL_TREE);
634
    /* long (*) (type) */
635
    func_lround = build_function_type_list (long_integer_type_node,
636
                                            type, NULL_TREE);
637
    /* long long (*) (type) */
638
    func_llround = build_function_type_list (long_long_integer_type_node,
639
                                             type, NULL_TREE);
640
    /* type (*) (type, type) */
641
    func_2 = build_function_type_list (type, type, type, NULL_TREE);
642
    /* type (*) (type, &int) */
643
    func_frexp
644
      = build_function_type_list (type,
645
                                  type,
646
                                  build_pointer_type (integer_type_node),
647
                                  NULL_TREE);
648
    /* type (*) (type, int) */
649
    func_scalbn = build_function_type_list (type,
650
                                            type, integer_type_node, NULL_TREE);
651
    /* type (*) (complex type) */
652
    func_cabs = build_function_type_list (type, complex_type, NULL_TREE);
653
    /* complex type (*) (complex type, complex type) */
654
    func_cpow
655
      = build_function_type_list (complex_type,
656
                                  complex_type, complex_type, NULL_TREE);
657
 
658
#define DEFINE_MATH_BUILTIN(ID, NAME, ARGTYPE)
659
#define DEFINE_MATH_BUILTIN_C(ID, NAME, ARGTYPE)
660
#define LIB_FUNCTION(ID, NAME, HAVE_COMPLEX)
661
 
662
    /* Only these built-ins are actually needed here. These are used directly
663
       from the code, when calling builtin_decl_for_precision() or
664
       builtin_decl_for_float_type(). The others are all constructed by
665
       gfc_get_intrinsic_lib_fndecl().  */
666
#define OTHER_BUILTIN(ID, NAME, TYPE, CONST) \
667
  quad_decls[BUILT_IN_ ## ID] = define_quad_builtin (NAME "q", func_ ## TYPE, CONST);
668
 
669
#include "mathbuiltins.def"
670
 
671
#undef OTHER_BUILTIN
672
#undef LIB_FUNCTION
673
#undef DEFINE_MATH_BUILTIN
674
#undef DEFINE_MATH_BUILTIN_C
675
 
676
  }
677
 
678
  /* Add GCC builtin functions.  */
679
  for (m = gfc_intrinsic_map;
680
       m->id != GFC_ISYM_NONE || m->double_built_in != END_BUILTINS; m++)
681
    {
682
      if (m->float_built_in != END_BUILTINS)
683
        m->real4_decl = builtin_decl_explicit (m->float_built_in);
684
      if (m->complex_float_built_in != END_BUILTINS)
685
        m->complex4_decl = builtin_decl_explicit (m->complex_float_built_in);
686
      if (m->double_built_in != END_BUILTINS)
687
        m->real8_decl = builtin_decl_explicit (m->double_built_in);
688
      if (m->complex_double_built_in != END_BUILTINS)
689
        m->complex8_decl = builtin_decl_explicit (m->complex_double_built_in);
690
 
691
      /* If real(kind=10) exists, it is always long double.  */
692
      if (m->long_double_built_in != END_BUILTINS)
693
        m->real10_decl = builtin_decl_explicit (m->long_double_built_in);
694
      if (m->complex_long_double_built_in != END_BUILTINS)
695
        m->complex10_decl
696
          = builtin_decl_explicit (m->complex_long_double_built_in);
697
 
698
      if (!gfc_real16_is_float128)
699
        {
700
          if (m->long_double_built_in != END_BUILTINS)
701
            m->real16_decl = builtin_decl_explicit (m->long_double_built_in);
702
          if (m->complex_long_double_built_in != END_BUILTINS)
703
            m->complex16_decl
704
              = builtin_decl_explicit (m->complex_long_double_built_in);
705
        }
706
      else if (quad_decls[m->double_built_in] != NULL_TREE)
707
        {
708
          /* Quad-precision function calls are constructed when first
709
             needed by builtin_decl_for_precision(), except for those
710
             that will be used directly (define by OTHER_BUILTIN).  */
711
          m->real16_decl = quad_decls[m->double_built_in];
712
        }
713
      else if (quad_decls[m->complex_double_built_in] != NULL_TREE)
714
        {
715
          /* Same thing for the complex ones.  */
716
          m->complex16_decl = quad_decls[m->double_built_in];
717
        }
718
    }
719
}
720
 
721
 
722
/* Create a fndecl for a simple intrinsic library function.  */
723
 
724
static tree
725
gfc_get_intrinsic_lib_fndecl (gfc_intrinsic_map_t * m, gfc_expr * expr)
726
{
727
  tree type;
728
  VEC(tree,gc) *argtypes;
729
  tree fndecl;
730
  gfc_actual_arglist *actual;
731
  tree *pdecl;
732
  gfc_typespec *ts;
733
  char name[GFC_MAX_SYMBOL_LEN + 3];
734
 
735
  ts = &expr->ts;
736
  if (ts->type == BT_REAL)
737
    {
738
      switch (ts->kind)
739
        {
740
        case 4:
741
          pdecl = &m->real4_decl;
742
          break;
743
        case 8:
744
          pdecl = &m->real8_decl;
745
          break;
746
        case 10:
747
          pdecl = &m->real10_decl;
748
          break;
749
        case 16:
750
          pdecl = &m->real16_decl;
751
          break;
752
        default:
753
          gcc_unreachable ();
754
        }
755
    }
756
  else if (ts->type == BT_COMPLEX)
757
    {
758
      gcc_assert (m->complex_available);
759
 
760
      switch (ts->kind)
761
        {
762
        case 4:
763
          pdecl = &m->complex4_decl;
764
          break;
765
        case 8:
766
          pdecl = &m->complex8_decl;
767
          break;
768
        case 10:
769
          pdecl = &m->complex10_decl;
770
          break;
771
        case 16:
772
          pdecl = &m->complex16_decl;
773
          break;
774
        default:
775
          gcc_unreachable ();
776
        }
777
    }
778
  else
779
    gcc_unreachable ();
780
 
781
  if (*pdecl)
782
    return *pdecl;
783
 
784
  if (m->libm_name)
785
    {
786
      int n = gfc_validate_kind (BT_REAL, ts->kind, false);
787
      if (gfc_real_kinds[n].c_float)
788
        snprintf (name, sizeof (name), "%s%s%s",
789
                  ts->type == BT_COMPLEX ? "c" : "", m->name, "f");
790
      else if (gfc_real_kinds[n].c_double)
791
        snprintf (name, sizeof (name), "%s%s",
792
                  ts->type == BT_COMPLEX ? "c" : "", m->name);
793
      else if (gfc_real_kinds[n].c_long_double)
794
        snprintf (name, sizeof (name), "%s%s%s",
795
                  ts->type == BT_COMPLEX ? "c" : "", m->name, "l");
796
      else if (gfc_real_kinds[n].c_float128)
797
        snprintf (name, sizeof (name), "%s%s%s",
798
                  ts->type == BT_COMPLEX ? "c" : "", m->name, "q");
799
      else
800
        gcc_unreachable ();
801
    }
802
  else
803
    {
804
      snprintf (name, sizeof (name), PREFIX ("%s_%c%d"), m->name,
805
                ts->type == BT_COMPLEX ? 'c' : 'r',
806
                ts->kind);
807
    }
808
 
809
  argtypes = NULL;
810
  for (actual = expr->value.function.actual; actual; actual = actual->next)
811
    {
812
      type = gfc_typenode_for_spec (&actual->expr->ts);
813
      VEC_safe_push (tree, gc, argtypes, type);
814
    }
815
  type = build_function_type_vec (gfc_typenode_for_spec (ts), argtypes);
816
  fndecl = build_decl (input_location,
817
                       FUNCTION_DECL, get_identifier (name), type);
818
 
819
  /* Mark the decl as external.  */
820
  DECL_EXTERNAL (fndecl) = 1;
821
  TREE_PUBLIC (fndecl) = 1;
822
 
823
  /* Mark it __attribute__((const)), if possible.  */
824
  TREE_READONLY (fndecl) = m->is_constant;
825
 
826
  rest_of_decl_compilation (fndecl, 1, 0);
827
 
828
  (*pdecl) = fndecl;
829
  return fndecl;
830
}
831
 
832
 
833
/* Convert an intrinsic function into an external or builtin call.  */
834
 
835
static void
836
gfc_conv_intrinsic_lib_function (gfc_se * se, gfc_expr * expr)
837
{
838
  gfc_intrinsic_map_t *m;
839
  tree fndecl;
840
  tree rettype;
841
  tree *args;
842
  unsigned int num_args;
843
  gfc_isym_id id;
844
 
845
  id = expr->value.function.isym->id;
846
  /* Find the entry for this function.  */
847
  for (m = gfc_intrinsic_map;
848
       m->id != GFC_ISYM_NONE || m->double_built_in != END_BUILTINS; m++)
849
    {
850
      if (id == m->id)
851
        break;
852
    }
853
 
854
  if (m->id == GFC_ISYM_NONE)
855
    {
856
      internal_error ("Intrinsic function %s(%d) not recognized",
857
                      expr->value.function.name, id);
858
    }
859
 
860
  /* Get the decl and generate the call.  */
861
  num_args = gfc_intrinsic_argument_list_length (expr);
862
  args = XALLOCAVEC (tree, num_args);
863
 
864
  gfc_conv_intrinsic_function_args (se, expr, args, num_args);
865
  fndecl = gfc_get_intrinsic_lib_fndecl (m, expr);
866
  rettype = TREE_TYPE (TREE_TYPE (fndecl));
867
 
868
  fndecl = build_addr (fndecl, current_function_decl);
869
  se->expr = build_call_array_loc (input_location, rettype, fndecl, num_args, args);
870
}
871
 
872
 
873
/* If bounds-checking is enabled, create code to verify at runtime that the
874
   string lengths for both expressions are the same (needed for e.g. MERGE).
875
   If bounds-checking is not enabled, does nothing.  */
876
 
877
void
878
gfc_trans_same_strlen_check (const char* intr_name, locus* where,
879
                             tree a, tree b, stmtblock_t* target)
880
{
881
  tree cond;
882
  tree name;
883
 
884
  /* If bounds-checking is disabled, do nothing.  */
885
  if (!(gfc_option.rtcheck & GFC_RTCHECK_BOUNDS))
886
    return;
887
 
888
  /* Compare the two string lengths.  */
889
  cond = fold_build2_loc (input_location, NE_EXPR, boolean_type_node, a, b);
890
 
891
  /* Output the runtime-check.  */
892
  name = gfc_build_cstring_const (intr_name);
893
  name = gfc_build_addr_expr (pchar_type_node, name);
894
  gfc_trans_runtime_check (true, false, cond, target, where,
895
                           "Unequal character lengths (%ld/%ld) in %s",
896
                           fold_convert (long_integer_type_node, a),
897
                           fold_convert (long_integer_type_node, b), name);
898
}
899
 
900
 
901
/* The EXPONENT(s) intrinsic function is translated into
902
       int ret;
903
       frexp (s, &ret);
904
       return ret;
905
 */
906
 
907
static void
908
gfc_conv_intrinsic_exponent (gfc_se *se, gfc_expr *expr)
909
{
910
  tree arg, type, res, tmp, frexp;
911
 
912
  frexp = gfc_builtin_decl_for_float_kind (BUILT_IN_FREXP,
913
                                       expr->value.function.actual->expr->ts.kind);
914
 
915
  gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
916
 
917
  res = gfc_create_var (integer_type_node, NULL);
918
  tmp = build_call_expr_loc (input_location, frexp, 2, arg,
919
                             gfc_build_addr_expr (NULL_TREE, res));
920
  gfc_add_expr_to_block (&se->pre, tmp);
921
 
922
  type = gfc_typenode_for_spec (&expr->ts);
923
  se->expr = fold_convert (type, res);
924
}
925
 
926
 
927
/* Convert the last ref of a scalar coarray from an AR_ELEMENT to an
928
   AR_FULL, suitable for the scalarizer.  */
929
 
930
static gfc_ss *
931
walk_coarray (gfc_expr *e)
932
{
933
  gfc_ss *ss;
934
 
935
  gcc_assert (gfc_get_corank (e) > 0);
936
 
937
  ss = gfc_walk_expr (e);
938
 
939
  /* Fix scalar coarray.  */
940
  if (ss == gfc_ss_terminator)
941
    {
942
      gfc_ref *ref;
943
 
944
      ref = e->ref;
945
      while (ref)
946
        {
947
          if (ref->type == REF_ARRAY
948
              && ref->u.ar.codimen > 0)
949
            break;
950
 
951
          ref = ref->next;
952
        }
953
 
954
      gcc_assert (ref != NULL);
955
      if (ref->u.ar.type == AR_ELEMENT)
956
        ref->u.ar.type = AR_SECTION;
957
      ss = gfc_reverse_ss (gfc_walk_array_ref (ss, e, ref));
958
    }
959
 
960
  return ss;
961
}
962
 
963
 
964
static void
965
trans_this_image (gfc_se * se, gfc_expr *expr)
966
{
967
  stmtblock_t loop;
968
  tree type, desc, dim_arg, cond, tmp, m, loop_var, exit_label, min_var,
969
       lbound, ubound, extent, ml;
970
  gfc_se argse;
971
  gfc_ss *ss;
972
  int rank, corank;
973
 
974
  /* The case -fcoarray=single is handled elsewhere.  */
975
  gcc_assert (gfc_option.coarray != GFC_FCOARRAY_SINGLE);
976
 
977
  gfc_init_coarray_decl (false);
978
 
979
  /* Argument-free version: THIS_IMAGE().  */
980
  if (expr->value.function.actual->expr == NULL)
981
    {
982
      se->expr = fold_convert (gfc_get_int_type (gfc_default_integer_kind),
983
                               gfort_gvar_caf_this_image);
984
      return;
985
    }
986
 
987
  /* Coarray-argument version: THIS_IMAGE(coarray [, dim]).  */
988
 
989
  type = gfc_get_int_type (gfc_default_integer_kind);
990
  corank = gfc_get_corank (expr->value.function.actual->expr);
991
  rank = expr->value.function.actual->expr->rank;
992
 
993
  /* Obtain the descriptor of the COARRAY.  */
994
  gfc_init_se (&argse, NULL);
995
  ss = walk_coarray (expr->value.function.actual->expr);
996
  gcc_assert (ss != gfc_ss_terminator);
997
  argse.want_coarray = 1;
998
  gfc_conv_expr_descriptor (&argse, expr->value.function.actual->expr, ss);
999
  gfc_add_block_to_block (&se->pre, &argse.pre);
1000
  gfc_add_block_to_block (&se->post, &argse.post);
1001
  desc = argse.expr;
1002
 
1003
  if (se->ss)
1004
    {
1005
      /* Create an implicit second parameter from the loop variable.  */
1006
      gcc_assert (!expr->value.function.actual->next->expr);
1007
      gcc_assert (corank > 0);
1008
      gcc_assert (se->loop->dimen == 1);
1009
      gcc_assert (se->ss->info->expr == expr);
1010
 
1011
      dim_arg = se->loop->loopvar[0];
1012
      dim_arg = fold_build2_loc (input_location, PLUS_EXPR,
1013
                                 gfc_array_index_type, dim_arg,
1014
                                 build_int_cst (TREE_TYPE (dim_arg), 1));
1015
      gfc_advance_se_ss_chain (se);
1016
    }
1017
  else
1018
    {
1019
      /* Use the passed DIM= argument.  */
1020
      gcc_assert (expr->value.function.actual->next->expr);
1021
      gfc_init_se (&argse, NULL);
1022
      gfc_conv_expr_type (&argse, expr->value.function.actual->next->expr,
1023
                          gfc_array_index_type);
1024
      gfc_add_block_to_block (&se->pre, &argse.pre);
1025
      dim_arg = argse.expr;
1026
 
1027
      if (INTEGER_CST_P (dim_arg))
1028
        {
1029
          int hi, co_dim;
1030
 
1031
          hi = TREE_INT_CST_HIGH (dim_arg);
1032
          co_dim = TREE_INT_CST_LOW (dim_arg);
1033
          if (hi || co_dim < 1
1034
              || co_dim > GFC_TYPE_ARRAY_CORANK (TREE_TYPE (desc)))
1035
            gfc_error ("'dim' argument of %s intrinsic at %L is not a valid "
1036
                       "dimension index", expr->value.function.isym->name,
1037
                       &expr->where);
1038
        }
1039
     else if (gfc_option.rtcheck & GFC_RTCHECK_BOUNDS)
1040
        {
1041
          dim_arg = gfc_evaluate_now (dim_arg, &se->pre);
1042
          cond = fold_build2_loc (input_location, LT_EXPR, boolean_type_node,
1043
                                  dim_arg,
1044
                                  build_int_cst (TREE_TYPE (dim_arg), 1));
1045
          tmp = gfc_rank_cst[GFC_TYPE_ARRAY_CORANK (TREE_TYPE (desc))];
1046
          tmp = fold_build2_loc (input_location, GT_EXPR, boolean_type_node,
1047
                                 dim_arg, tmp);
1048
          cond = fold_build2_loc (input_location, TRUTH_ORIF_EXPR,
1049
                                  boolean_type_node, cond, tmp);
1050
          gfc_trans_runtime_check (true, false, cond, &se->pre, &expr->where,
1051
                                   gfc_msg_fault);
1052
        }
1053
    }
1054
 
1055
  /* Used algorithm; cf. Fortran 2008, C.10. Note, due to the scalarizer,
1056
     one always has a dim_arg argument.
1057
 
1058
     m = this_image() - 1
1059
     if (corank == 1)
1060
       {
1061
         sub(1) = m + lcobound(corank)
1062
         return;
1063
       }
1064
     i = rank
1065
     min_var = min (rank + corank - 2, rank + dim_arg - 1)
1066
     for (;;)
1067
       {
1068
         extent = gfc_extent(i)
1069
         ml = m
1070
         m  = m/extent
1071
         if (i >= min_var)
1072
           goto exit_label
1073
         i++
1074
       }
1075
     exit_label:
1076
     sub(dim_arg) = (dim_arg < corank) ? ml - m*extent + lcobound(dim_arg)
1077
                                       : m + lcobound(corank)
1078
  */
1079
 
1080
  /* this_image () - 1.  */
1081
  tmp = fold_convert (type, gfort_gvar_caf_this_image);
1082
  tmp = fold_build2_loc (input_location, MINUS_EXPR, type, tmp,
1083
                       build_int_cst (type, 1));
1084
  if (corank == 1)
1085
    {
1086
      /* sub(1) = m + lcobound(corank).  */
1087
      lbound = gfc_conv_descriptor_lbound_get (desc,
1088
                        build_int_cst (TREE_TYPE (gfc_array_index_type),
1089
                                       corank+rank-1));
1090
      lbound = fold_convert (type, lbound);
1091
      tmp = fold_build2_loc (input_location, PLUS_EXPR, type, tmp, lbound);
1092
 
1093
      se->expr = tmp;
1094
      return;
1095
    }
1096
 
1097
  m = gfc_create_var (type, NULL);
1098
  ml = gfc_create_var (type, NULL);
1099
  loop_var = gfc_create_var (integer_type_node, NULL);
1100
  min_var = gfc_create_var (integer_type_node, NULL);
1101
 
1102
  /* m = this_image () - 1.  */
1103
  gfc_add_modify (&se->pre, m, tmp);
1104
 
1105
  /* min_var = min (rank + corank-2, rank + dim_arg - 1).  */
1106
  tmp = fold_build2_loc (input_location, PLUS_EXPR, integer_type_node,
1107
                         fold_convert (integer_type_node, dim_arg),
1108
                         build_int_cst (integer_type_node, rank - 1));
1109
  tmp = fold_build2_loc (input_location, MIN_EXPR, integer_type_node,
1110
                         build_int_cst (integer_type_node, rank + corank - 2),
1111
                         tmp);
1112
  gfc_add_modify (&se->pre, min_var, tmp);
1113
 
1114
  /* i = rank.  */
1115
  tmp = build_int_cst (integer_type_node, rank);
1116
  gfc_add_modify (&se->pre, loop_var, tmp);
1117
 
1118
  exit_label = gfc_build_label_decl (NULL_TREE);
1119
  TREE_USED (exit_label) = 1;
1120
 
1121
  /* Loop body.  */
1122
  gfc_init_block (&loop);
1123
 
1124
  /* ml = m.  */
1125
  gfc_add_modify (&loop, ml, m);
1126
 
1127
  /* extent = ...  */
1128
  lbound = gfc_conv_descriptor_lbound_get (desc, loop_var);
1129
  ubound = gfc_conv_descriptor_ubound_get (desc, loop_var);
1130
  extent = gfc_conv_array_extent_dim (lbound, ubound, NULL);
1131
  extent = fold_convert (type, extent);
1132
 
1133
  /* m = m/extent.  */
1134
  gfc_add_modify (&loop, m,
1135
                  fold_build2_loc (input_location, TRUNC_DIV_EXPR, type,
1136
                          m, extent));
1137
 
1138
  /* Exit condition:  if (i >= min_var) goto exit_label.  */
1139
  cond = fold_build2_loc (input_location, GE_EXPR, boolean_type_node, loop_var,
1140
                  min_var);
1141
  tmp = build1_v (GOTO_EXPR, exit_label);
1142
  tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node, cond, tmp,
1143
                         build_empty_stmt (input_location));
1144
  gfc_add_expr_to_block (&loop, tmp);
1145
 
1146
  /* Increment loop variable: i++.  */
1147
  gfc_add_modify (&loop, loop_var,
1148
                  fold_build2_loc (input_location, PLUS_EXPR, integer_type_node,
1149
                                   loop_var,
1150
                                   build_int_cst (integer_type_node, 1)));
1151
 
1152
  /* Making the loop... actually loop!  */
1153
  tmp = gfc_finish_block (&loop);
1154
  tmp = build1_v (LOOP_EXPR, tmp);
1155
  gfc_add_expr_to_block (&se->pre, tmp);
1156
 
1157
  /* The exit label.  */
1158
  tmp = build1_v (LABEL_EXPR, exit_label);
1159
  gfc_add_expr_to_block (&se->pre, tmp);
1160
 
1161
  /*  sub(co_dim) = (co_dim < corank) ? ml - m*extent + lcobound(dim_arg)
1162
                                      : m + lcobound(corank) */
1163
 
1164
  cond = fold_build2_loc (input_location, LT_EXPR, boolean_type_node, dim_arg,
1165
                          build_int_cst (TREE_TYPE (dim_arg), corank));
1166
 
1167
  lbound = gfc_conv_descriptor_lbound_get (desc,
1168
                fold_build2_loc (input_location, PLUS_EXPR,
1169
                                 gfc_array_index_type, dim_arg,
1170
                                 build_int_cst (TREE_TYPE (dim_arg), rank-1)));
1171
  lbound = fold_convert (type, lbound);
1172
 
1173
  tmp = fold_build2_loc (input_location, MINUS_EXPR, type, ml,
1174
                         fold_build2_loc (input_location, MULT_EXPR, type,
1175
                                          m, extent));
1176
  tmp = fold_build2_loc (input_location, PLUS_EXPR, type, tmp, lbound);
1177
 
1178
  se->expr = fold_build3_loc (input_location, COND_EXPR, type, cond, tmp,
1179
                              fold_build2_loc (input_location, PLUS_EXPR, type,
1180
                                               m, lbound));
1181
}
1182
 
1183
 
1184
static void
1185
trans_image_index (gfc_se * se, gfc_expr *expr)
1186
{
1187
  tree num_images, cond, coindex, type, lbound, ubound, desc, subdesc,
1188
       tmp, invalid_bound;
1189
  gfc_se argse, subse;
1190
  gfc_ss *ss, *subss;
1191
  int rank, corank, codim;
1192
 
1193
  type = gfc_get_int_type (gfc_default_integer_kind);
1194
  corank = gfc_get_corank (expr->value.function.actual->expr);
1195
  rank = expr->value.function.actual->expr->rank;
1196
 
1197
  /* Obtain the descriptor of the COARRAY.  */
1198
  gfc_init_se (&argse, NULL);
1199
  ss = walk_coarray (expr->value.function.actual->expr);
1200
  gcc_assert (ss != gfc_ss_terminator);
1201
  argse.want_coarray = 1;
1202
  gfc_conv_expr_descriptor (&argse, expr->value.function.actual->expr, ss);
1203
  gfc_add_block_to_block (&se->pre, &argse.pre);
1204
  gfc_add_block_to_block (&se->post, &argse.post);
1205
  desc = argse.expr;
1206
 
1207
  /* Obtain a handle to the SUB argument.  */
1208
  gfc_init_se (&subse, NULL);
1209
  subss = gfc_walk_expr (expr->value.function.actual->next->expr);
1210
  gcc_assert (subss != gfc_ss_terminator);
1211
  gfc_conv_expr_descriptor (&subse, expr->value.function.actual->next->expr,
1212
                            subss);
1213
  gfc_add_block_to_block (&se->pre, &subse.pre);
1214
  gfc_add_block_to_block (&se->post, &subse.post);
1215
  subdesc = build_fold_indirect_ref_loc (input_location,
1216
                        gfc_conv_descriptor_data_get (subse.expr));
1217
 
1218
  /* Fortran 2008 does not require that the values remain in the cobounds,
1219
     thus we need explicitly check this - and return 0 if they are exceeded.  */
1220
 
1221
  lbound = gfc_conv_descriptor_lbound_get (desc, gfc_rank_cst[rank+corank-1]);
1222
  tmp = gfc_build_array_ref (subdesc, gfc_rank_cst[corank-1], NULL);
1223
  invalid_bound = fold_build2_loc (input_location, LT_EXPR, boolean_type_node,
1224
                                 fold_convert (gfc_array_index_type, tmp),
1225
                                 lbound);
1226
 
1227
  for (codim = corank + rank - 2; codim >= rank; codim--)
1228
    {
1229
      lbound = gfc_conv_descriptor_lbound_get (desc, gfc_rank_cst[codim]);
1230
      ubound = gfc_conv_descriptor_ubound_get (desc, gfc_rank_cst[codim]);
1231
      tmp = gfc_build_array_ref (subdesc, gfc_rank_cst[codim-rank], NULL);
1232
      cond = fold_build2_loc (input_location, LT_EXPR, boolean_type_node,
1233
                              fold_convert (gfc_array_index_type, tmp),
1234
                              lbound);
1235
      invalid_bound = fold_build2_loc (input_location, TRUTH_OR_EXPR,
1236
                                       boolean_type_node, invalid_bound, cond);
1237
      cond = fold_build2_loc (input_location, GT_EXPR, boolean_type_node,
1238
                              fold_convert (gfc_array_index_type, tmp),
1239
                              ubound);
1240
      invalid_bound = fold_build2_loc (input_location, TRUTH_OR_EXPR,
1241
                                       boolean_type_node, invalid_bound, cond);
1242
    }
1243
 
1244
  invalid_bound = gfc_unlikely (invalid_bound);
1245
 
1246
 
1247
  /* See Fortran 2008, C.10 for the following algorithm.  */
1248
 
1249
  /* coindex = sub(corank) - lcobound(n).  */
1250
  coindex = fold_convert (gfc_array_index_type,
1251
                          gfc_build_array_ref (subdesc, gfc_rank_cst[corank-1],
1252
                                               NULL));
1253
  lbound = gfc_conv_descriptor_lbound_get (desc, gfc_rank_cst[rank+corank-1]);
1254
  coindex = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
1255
                             fold_convert (gfc_array_index_type, coindex),
1256
                             lbound);
1257
 
1258
  for (codim = corank + rank - 2; codim >= rank; codim--)
1259
    {
1260
      tree extent, ubound;
1261
 
1262
      /* coindex = coindex*extent(codim) + sub(codim) - lcobound(codim).  */
1263
      lbound = gfc_conv_descriptor_lbound_get (desc, gfc_rank_cst[codim]);
1264
      ubound = gfc_conv_descriptor_ubound_get (desc, gfc_rank_cst[codim]);
1265
      extent = gfc_conv_array_extent_dim (lbound, ubound, NULL);
1266
 
1267
      /* coindex *= extent.  */
1268
      coindex = fold_build2_loc (input_location, MULT_EXPR,
1269
                                 gfc_array_index_type, coindex, extent);
1270
 
1271
      /* coindex += sub(codim).  */
1272
      tmp = gfc_build_array_ref (subdesc, gfc_rank_cst[codim-rank], NULL);
1273
      coindex = fold_build2_loc (input_location, PLUS_EXPR,
1274
                                 gfc_array_index_type, coindex,
1275
                                 fold_convert (gfc_array_index_type, tmp));
1276
 
1277
      /* coindex -= lbound(codim).  */
1278
      lbound = gfc_conv_descriptor_lbound_get (desc, gfc_rank_cst[codim]);
1279
      coindex = fold_build2_loc (input_location, MINUS_EXPR,
1280
                                 gfc_array_index_type, coindex, lbound);
1281
    }
1282
 
1283
  coindex = fold_build2_loc (input_location, PLUS_EXPR, type,
1284
                             fold_convert(type, coindex),
1285
                             build_int_cst (type, 1));
1286
 
1287
  /* Return 0 if "coindex" exceeds num_images().  */
1288
 
1289
  if (gfc_option.coarray == GFC_FCOARRAY_SINGLE)
1290
    num_images = build_int_cst (type, 1);
1291
  else
1292
    {
1293
      gfc_init_coarray_decl (false);
1294
      num_images = fold_convert (type, gfort_gvar_caf_num_images);
1295
    }
1296
 
1297
  tmp = gfc_create_var (type, NULL);
1298
  gfc_add_modify (&se->pre, tmp, coindex);
1299
 
1300
  cond = fold_build2_loc (input_location, GT_EXPR, boolean_type_node, tmp,
1301
                          num_images);
1302
  cond = fold_build2_loc (input_location, TRUTH_OR_EXPR, boolean_type_node,
1303
                          cond,
1304
                          fold_convert (boolean_type_node, invalid_bound));
1305
  se->expr = fold_build3_loc (input_location, COND_EXPR, type, cond,
1306
                              build_int_cst (type, 0), tmp);
1307
}
1308
 
1309
 
1310
static void
1311
trans_num_images (gfc_se * se)
1312
{
1313
  gfc_init_coarray_decl (false);
1314
  se->expr = fold_convert (gfc_get_int_type (gfc_default_integer_kind),
1315
                           gfort_gvar_caf_num_images);
1316
}
1317
 
1318
 
1319
/* Evaluate a single upper or lower bound.  */
1320
/* TODO: bound intrinsic generates way too much unnecessary code.  */
1321
 
1322
static void
1323
gfc_conv_intrinsic_bound (gfc_se * se, gfc_expr * expr, int upper)
1324
{
1325
  gfc_actual_arglist *arg;
1326
  gfc_actual_arglist *arg2;
1327
  tree desc;
1328
  tree type;
1329
  tree bound;
1330
  tree tmp;
1331
  tree cond, cond1, cond3, cond4, size;
1332
  tree ubound;
1333
  tree lbound;
1334
  gfc_se argse;
1335
  gfc_ss *ss;
1336
  gfc_array_spec * as;
1337
 
1338
  arg = expr->value.function.actual;
1339
  arg2 = arg->next;
1340
 
1341
  if (se->ss)
1342
    {
1343
      /* Create an implicit second parameter from the loop variable.  */
1344
      gcc_assert (!arg2->expr);
1345
      gcc_assert (se->loop->dimen == 1);
1346
      gcc_assert (se->ss->info->expr == expr);
1347
      gfc_advance_se_ss_chain (se);
1348
      bound = se->loop->loopvar[0];
1349
      bound = fold_build2_loc (input_location, MINUS_EXPR,
1350
                               gfc_array_index_type, bound,
1351
                               se->loop->from[0]);
1352
    }
1353
  else
1354
    {
1355
      /* use the passed argument.  */
1356
      gcc_assert (arg2->expr);
1357
      gfc_init_se (&argse, NULL);
1358
      gfc_conv_expr_type (&argse, arg2->expr, gfc_array_index_type);
1359
      gfc_add_block_to_block (&se->pre, &argse.pre);
1360
      bound = argse.expr;
1361
      /* Convert from one based to zero based.  */
1362
      bound = fold_build2_loc (input_location, MINUS_EXPR,
1363
                               gfc_array_index_type, bound,
1364
                               gfc_index_one_node);
1365
    }
1366
 
1367
  /* TODO: don't re-evaluate the descriptor on each iteration.  */
1368
  /* Get a descriptor for the first parameter.  */
1369
  ss = gfc_walk_expr (arg->expr);
1370
  gcc_assert (ss != gfc_ss_terminator);
1371
  gfc_init_se (&argse, NULL);
1372
  gfc_conv_expr_descriptor (&argse, arg->expr, ss);
1373
  gfc_add_block_to_block (&se->pre, &argse.pre);
1374
  gfc_add_block_to_block (&se->post, &argse.post);
1375
 
1376
  desc = argse.expr;
1377
 
1378
  if (INTEGER_CST_P (bound))
1379
    {
1380
      int hi, low;
1381
 
1382
      hi = TREE_INT_CST_HIGH (bound);
1383
      low = TREE_INT_CST_LOW (bound);
1384
      if (hi || low < 0 || low >= GFC_TYPE_ARRAY_RANK (TREE_TYPE (desc)))
1385
        gfc_error ("'dim' argument of %s intrinsic at %L is not a valid "
1386
                   "dimension index", upper ? "UBOUND" : "LBOUND",
1387
                   &expr->where);
1388
    }
1389
  else
1390
    {
1391
      if (gfc_option.rtcheck & GFC_RTCHECK_BOUNDS)
1392
        {
1393
          bound = gfc_evaluate_now (bound, &se->pre);
1394
          cond = fold_build2_loc (input_location, LT_EXPR, boolean_type_node,
1395
                                  bound, build_int_cst (TREE_TYPE (bound), 0));
1396
          tmp = gfc_rank_cst[GFC_TYPE_ARRAY_RANK (TREE_TYPE (desc))];
1397
          tmp = fold_build2_loc (input_location, GE_EXPR, boolean_type_node,
1398
                                 bound, tmp);
1399
          cond = fold_build2_loc (input_location, TRUTH_ORIF_EXPR,
1400
                                  boolean_type_node, cond, tmp);
1401
          gfc_trans_runtime_check (true, false, cond, &se->pre, &expr->where,
1402
                                   gfc_msg_fault);
1403
        }
1404
    }
1405
 
1406
  ubound = gfc_conv_descriptor_ubound_get (desc, bound);
1407
  lbound = gfc_conv_descriptor_lbound_get (desc, bound);
1408
 
1409
  as = gfc_get_full_arrayspec_from_expr (arg->expr);
1410
 
1411
  /* 13.14.53: Result value for LBOUND
1412
 
1413
     Case (i): For an array section or for an array expression other than a
1414
               whole array or array structure component, LBOUND(ARRAY, DIM)
1415
               has the value 1.  For a whole array or array structure
1416
               component, LBOUND(ARRAY, DIM) has the value:
1417
                 (a) equal to the lower bound for subscript DIM of ARRAY if
1418
                     dimension DIM of ARRAY does not have extent zero
1419
                     or if ARRAY is an assumed-size array of rank DIM,
1420
              or (b) 1 otherwise.
1421
 
1422
     13.14.113: Result value for UBOUND
1423
 
1424
     Case (i): For an array section or for an array expression other than a
1425
               whole array or array structure component, UBOUND(ARRAY, DIM)
1426
               has the value equal to the number of elements in the given
1427
               dimension; otherwise, it has a value equal to the upper bound
1428
               for subscript DIM of ARRAY if dimension DIM of ARRAY does
1429
               not have size zero and has value zero if dimension DIM has
1430
               size zero.  */
1431
 
1432
  if (as)
1433
    {
1434
      tree stride = gfc_conv_descriptor_stride_get (desc, bound);
1435
 
1436
      cond1 = fold_build2_loc (input_location, GE_EXPR, boolean_type_node,
1437
                               ubound, lbound);
1438
      cond3 = fold_build2_loc (input_location, GE_EXPR, boolean_type_node,
1439
                               stride, gfc_index_zero_node);
1440
      cond3 = fold_build2_loc (input_location, TRUTH_AND_EXPR,
1441
                               boolean_type_node, cond3, cond1);
1442
      cond4 = fold_build2_loc (input_location, LT_EXPR, boolean_type_node,
1443
                               stride, gfc_index_zero_node);
1444
 
1445
      if (upper)
1446
        {
1447
          tree cond5;
1448
          cond = fold_build2_loc (input_location, TRUTH_OR_EXPR,
1449
                                  boolean_type_node, cond3, cond4);
1450
          cond5 = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node,
1451
                                   gfc_index_one_node, lbound);
1452
          cond5 = fold_build2_loc (input_location, TRUTH_AND_EXPR,
1453
                                   boolean_type_node, cond4, cond5);
1454
 
1455
          cond = fold_build2_loc (input_location, TRUTH_OR_EXPR,
1456
                                  boolean_type_node, cond, cond5);
1457
 
1458
          se->expr = fold_build3_loc (input_location, COND_EXPR,
1459
                                      gfc_array_index_type, cond,
1460
                                      ubound, gfc_index_zero_node);
1461
        }
1462
      else
1463
        {
1464
          if (as->type == AS_ASSUMED_SIZE)
1465
            cond = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node,
1466
                                    bound, build_int_cst (TREE_TYPE (bound),
1467
                                                          arg->expr->rank - 1));
1468
          else
1469
            cond = boolean_false_node;
1470
 
1471
          cond1 = fold_build2_loc (input_location, TRUTH_OR_EXPR,
1472
                                   boolean_type_node, cond3, cond4);
1473
          cond = fold_build2_loc (input_location, TRUTH_OR_EXPR,
1474
                                  boolean_type_node, cond, cond1);
1475
 
1476
          se->expr = fold_build3_loc (input_location, COND_EXPR,
1477
                                      gfc_array_index_type, cond,
1478
                                      lbound, gfc_index_one_node);
1479
        }
1480
    }
1481
  else
1482
    {
1483
      if (upper)
1484
        {
1485
          size = fold_build2_loc (input_location, MINUS_EXPR,
1486
                                  gfc_array_index_type, ubound, lbound);
1487
          se->expr = fold_build2_loc (input_location, PLUS_EXPR,
1488
                                      gfc_array_index_type, size,
1489
                                  gfc_index_one_node);
1490
          se->expr = fold_build2_loc (input_location, MAX_EXPR,
1491
                                      gfc_array_index_type, se->expr,
1492
                                      gfc_index_zero_node);
1493
        }
1494
      else
1495
        se->expr = gfc_index_one_node;
1496
    }
1497
 
1498
  type = gfc_typenode_for_spec (&expr->ts);
1499
  se->expr = convert (type, se->expr);
1500
}
1501
 
1502
 
1503
static void
1504
conv_intrinsic_cobound (gfc_se * se, gfc_expr * expr)
1505
{
1506
  gfc_actual_arglist *arg;
1507
  gfc_actual_arglist *arg2;
1508
  gfc_se argse;
1509
  gfc_ss *ss;
1510
  tree bound, resbound, resbound2, desc, cond, tmp;
1511
  tree type;
1512
  int corank;
1513
 
1514
  gcc_assert (expr->value.function.isym->id == GFC_ISYM_LCOBOUND
1515
              || expr->value.function.isym->id == GFC_ISYM_UCOBOUND
1516
              || expr->value.function.isym->id == GFC_ISYM_THIS_IMAGE);
1517
 
1518
  arg = expr->value.function.actual;
1519
  arg2 = arg->next;
1520
 
1521
  gcc_assert (arg->expr->expr_type == EXPR_VARIABLE);
1522
  corank = gfc_get_corank (arg->expr);
1523
 
1524
  ss = walk_coarray (arg->expr);
1525
  gcc_assert (ss != gfc_ss_terminator);
1526
  gfc_init_se (&argse, NULL);
1527
  argse.want_coarray = 1;
1528
 
1529
  gfc_conv_expr_descriptor (&argse, arg->expr, ss);
1530
  gfc_add_block_to_block (&se->pre, &argse.pre);
1531
  gfc_add_block_to_block (&se->post, &argse.post);
1532
  desc = argse.expr;
1533
 
1534
  if (se->ss)
1535
    {
1536
      /* Create an implicit second parameter from the loop variable.  */
1537
      gcc_assert (!arg2->expr);
1538
      gcc_assert (corank > 0);
1539
      gcc_assert (se->loop->dimen == 1);
1540
      gcc_assert (se->ss->info->expr == expr);
1541
 
1542
      bound = se->loop->loopvar[0];
1543
      bound = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
1544
                               bound, gfc_rank_cst[arg->expr->rank]);
1545
      gfc_advance_se_ss_chain (se);
1546
    }
1547
  else
1548
    {
1549
      /* use the passed argument.  */
1550
      gcc_assert (arg2->expr);
1551
      gfc_init_se (&argse, NULL);
1552
      gfc_conv_expr_type (&argse, arg2->expr, gfc_array_index_type);
1553
      gfc_add_block_to_block (&se->pre, &argse.pre);
1554
      bound = argse.expr;
1555
 
1556
      if (INTEGER_CST_P (bound))
1557
        {
1558
          int hi, low;
1559
 
1560
          hi = TREE_INT_CST_HIGH (bound);
1561
          low = TREE_INT_CST_LOW (bound);
1562
          if (hi || low < 1 || low > GFC_TYPE_ARRAY_CORANK (TREE_TYPE (desc)))
1563
            gfc_error ("'dim' argument of %s intrinsic at %L is not a valid "
1564
                       "dimension index", expr->value.function.isym->name,
1565
                       &expr->where);
1566
        }
1567
      else if (gfc_option.rtcheck & GFC_RTCHECK_BOUNDS)
1568
        {
1569
          bound = gfc_evaluate_now (bound, &se->pre);
1570
          cond = fold_build2_loc (input_location, LT_EXPR, boolean_type_node,
1571
                                  bound, build_int_cst (TREE_TYPE (bound), 1));
1572
          tmp = gfc_rank_cst[GFC_TYPE_ARRAY_CORANK (TREE_TYPE (desc))];
1573
          tmp = fold_build2_loc (input_location, GT_EXPR, boolean_type_node,
1574
                                 bound, tmp);
1575
          cond = fold_build2_loc (input_location, TRUTH_ORIF_EXPR,
1576
                                  boolean_type_node, cond, tmp);
1577
          gfc_trans_runtime_check (true, false, cond, &se->pre, &expr->where,
1578
                                   gfc_msg_fault);
1579
        }
1580
 
1581
 
1582
      /* Substract 1 to get to zero based and add dimensions.  */
1583
      switch (arg->expr->rank)
1584
        {
1585
        case 0:
1586
          bound = fold_build2_loc (input_location, MINUS_EXPR,
1587
                                   gfc_array_index_type, bound,
1588
                                   gfc_index_one_node);
1589
        case 1:
1590
          break;
1591
        default:
1592
          bound = fold_build2_loc (input_location, PLUS_EXPR,
1593
                                   gfc_array_index_type, bound,
1594
                                   gfc_rank_cst[arg->expr->rank - 1]);
1595
        }
1596
    }
1597
 
1598
  resbound = gfc_conv_descriptor_lbound_get (desc, bound);
1599
 
1600
  /* Handle UCOBOUND with special handling of the last codimension.  */
1601
  if (expr->value.function.isym->id == GFC_ISYM_UCOBOUND)
1602
    {
1603
      /* Last codimension: For -fcoarray=single just return
1604
         the lcobound - otherwise add
1605
           ceiling (real (num_images ()) / real (size)) - 1
1606
         = (num_images () + size - 1) / size - 1
1607
         = (num_images - 1) / size(),
1608
         where size is the product of the extent of all but the last
1609
         codimension.  */
1610
 
1611
      if (gfc_option.coarray != GFC_FCOARRAY_SINGLE && corank > 1)
1612
        {
1613
          tree cosize;
1614
 
1615
          gfc_init_coarray_decl (false);
1616
          cosize = gfc_conv_descriptor_cosize (desc, arg->expr->rank, corank);
1617
 
1618
          tmp = fold_build2_loc (input_location, MINUS_EXPR,
1619
                                 gfc_array_index_type,
1620
                                 fold_convert (gfc_array_index_type,
1621
                                               gfort_gvar_caf_num_images),
1622
                                 build_int_cst (gfc_array_index_type, 1));
1623
          tmp = fold_build2_loc (input_location, TRUNC_DIV_EXPR,
1624
                                 gfc_array_index_type, tmp,
1625
                                 fold_convert (gfc_array_index_type, cosize));
1626
          resbound = fold_build2_loc (input_location, PLUS_EXPR,
1627
                                      gfc_array_index_type, resbound, tmp);
1628
        }
1629
      else if (gfc_option.coarray != GFC_FCOARRAY_SINGLE)
1630
        {
1631
          /* ubound = lbound + num_images() - 1.  */
1632
          gfc_init_coarray_decl (false);
1633
          tmp = fold_build2_loc (input_location, MINUS_EXPR,
1634
                                 gfc_array_index_type,
1635
                                 fold_convert (gfc_array_index_type,
1636
                                               gfort_gvar_caf_num_images),
1637
                                 build_int_cst (gfc_array_index_type, 1));
1638
          resbound = fold_build2_loc (input_location, PLUS_EXPR,
1639
                                      gfc_array_index_type, resbound, tmp);
1640
        }
1641
 
1642
      if (corank > 1)
1643
        {
1644
          cond = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node,
1645
                                  bound,
1646
                                  build_int_cst (TREE_TYPE (bound),
1647
                                                 arg->expr->rank + corank - 1));
1648
 
1649
          resbound2 = gfc_conv_descriptor_ubound_get (desc, bound);
1650
          se->expr = fold_build3_loc (input_location, COND_EXPR,
1651
                                      gfc_array_index_type, cond,
1652
                                      resbound, resbound2);
1653
        }
1654
      else
1655
        se->expr = resbound;
1656
    }
1657
  else
1658
    se->expr = resbound;
1659
 
1660
  type = gfc_typenode_for_spec (&expr->ts);
1661
  se->expr = convert (type, se->expr);
1662
}
1663
 
1664
 
1665
static void
1666
gfc_conv_intrinsic_abs (gfc_se * se, gfc_expr * expr)
1667
{
1668
  tree arg, cabs;
1669
 
1670
  gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
1671
 
1672
  switch (expr->value.function.actual->expr->ts.type)
1673
    {
1674
    case BT_INTEGER:
1675
    case BT_REAL:
1676
      se->expr = fold_build1_loc (input_location, ABS_EXPR, TREE_TYPE (arg),
1677
                                  arg);
1678
      break;
1679
 
1680
    case BT_COMPLEX:
1681
      cabs = gfc_builtin_decl_for_float_kind (BUILT_IN_CABS, expr->ts.kind);
1682
      se->expr = build_call_expr_loc (input_location, cabs, 1, arg);
1683
      break;
1684
 
1685
    default:
1686
      gcc_unreachable ();
1687
    }
1688
}
1689
 
1690
 
1691
/* Create a complex value from one or two real components.  */
1692
 
1693
static void
1694
gfc_conv_intrinsic_cmplx (gfc_se * se, gfc_expr * expr, int both)
1695
{
1696
  tree real;
1697
  tree imag;
1698
  tree type;
1699
  tree *args;
1700
  unsigned int num_args;
1701
 
1702
  num_args = gfc_intrinsic_argument_list_length (expr);
1703
  args = XALLOCAVEC (tree, num_args);
1704
 
1705
  type = gfc_typenode_for_spec (&expr->ts);
1706
  gfc_conv_intrinsic_function_args (se, expr, args, num_args);
1707
  real = convert (TREE_TYPE (type), args[0]);
1708
  if (both)
1709
    imag = convert (TREE_TYPE (type), args[1]);
1710
  else if (TREE_CODE (TREE_TYPE (args[0])) == COMPLEX_TYPE)
1711
    {
1712
      imag = fold_build1_loc (input_location, IMAGPART_EXPR,
1713
                              TREE_TYPE (TREE_TYPE (args[0])), args[0]);
1714
      imag = convert (TREE_TYPE (type), imag);
1715
    }
1716
  else
1717
    imag = build_real_from_int_cst (TREE_TYPE (type), integer_zero_node);
1718
 
1719
  se->expr = fold_build2_loc (input_location, COMPLEX_EXPR, type, real, imag);
1720
}
1721
 
1722
/* Remainder function MOD(A, P) = A - INT(A / P) * P
1723
                      MODULO(A, P) = A - FLOOR (A / P) * P  */
1724
/* TODO: MOD(x, 0)  */
1725
 
1726
static void
1727
gfc_conv_intrinsic_mod (gfc_se * se, gfc_expr * expr, int modulo)
1728
{
1729
  tree type;
1730
  tree itype;
1731
  tree tmp;
1732
  tree test;
1733
  tree test2;
1734
  tree fmod;
1735
  mpfr_t huge;
1736
  int n, ikind;
1737
  tree args[2];
1738
 
1739
  gfc_conv_intrinsic_function_args (se, expr, args, 2);
1740
 
1741
  switch (expr->ts.type)
1742
    {
1743
    case BT_INTEGER:
1744
      /* Integer case is easy, we've got a builtin op.  */
1745
      type = TREE_TYPE (args[0]);
1746
 
1747
      if (modulo)
1748
       se->expr = fold_build2_loc (input_location, FLOOR_MOD_EXPR, type,
1749
                                   args[0], args[1]);
1750
      else
1751
       se->expr = fold_build2_loc (input_location, TRUNC_MOD_EXPR, type,
1752
                                   args[0], args[1]);
1753
      break;
1754
 
1755
    case BT_REAL:
1756
      fmod = NULL_TREE;
1757
      /* Check if we have a builtin fmod.  */
1758
      fmod = gfc_builtin_decl_for_float_kind (BUILT_IN_FMOD, expr->ts.kind);
1759
 
1760
      /* Use it if it exists.  */
1761
      if (fmod != NULL_TREE)
1762
        {
1763
          tmp = build_addr (fmod, current_function_decl);
1764
          se->expr = build_call_array_loc (input_location,
1765
                                       TREE_TYPE (TREE_TYPE (fmod)),
1766
                                       tmp, 2, args);
1767
          if (modulo == 0)
1768
            return;
1769
        }
1770
 
1771
      type = TREE_TYPE (args[0]);
1772
 
1773
      args[0] = gfc_evaluate_now (args[0], &se->pre);
1774
      args[1] = gfc_evaluate_now (args[1], &se->pre);
1775
 
1776
      /* Definition:
1777
         modulo = arg - floor (arg/arg2) * arg2, so
1778
                = test ? fmod (arg, arg2) : fmod (arg, arg2) + arg2,
1779
         where
1780
          test  = (fmod (arg, arg2) != 0) && ((arg < 0) xor (arg2 < 0))
1781
         thereby avoiding another division and retaining the accuracy
1782
         of the builtin function.  */
1783
      if (fmod != NULL_TREE && modulo)
1784
        {
1785
          tree zero = gfc_build_const (type, integer_zero_node);
1786
          tmp = gfc_evaluate_now (se->expr, &se->pre);
1787
          test = fold_build2_loc (input_location, LT_EXPR, boolean_type_node,
1788
                                  args[0], zero);
1789
          test2 = fold_build2_loc (input_location, LT_EXPR, boolean_type_node,
1790
                                   args[1], zero);
1791
          test2 = fold_build2_loc (input_location, TRUTH_XOR_EXPR,
1792
                                   boolean_type_node, test, test2);
1793
          test = fold_build2_loc (input_location, NE_EXPR, boolean_type_node,
1794
                                  tmp, zero);
1795
          test = fold_build2_loc (input_location, TRUTH_AND_EXPR,
1796
                                  boolean_type_node, test, test2);
1797
          test = gfc_evaluate_now (test, &se->pre);
1798
          se->expr = fold_build3_loc (input_location, COND_EXPR, type, test,
1799
                                  fold_build2_loc (input_location, PLUS_EXPR,
1800
                                                   type, tmp, args[1]), tmp);
1801
          return;
1802
        }
1803
 
1804
      /* If we do not have a built_in fmod, the calculation is going to
1805
         have to be done longhand.  */
1806
      tmp = fold_build2_loc (input_location, RDIV_EXPR, type, args[0], args[1]);
1807
 
1808
      /* Test if the value is too large to handle sensibly.  */
1809
      gfc_set_model_kind (expr->ts.kind);
1810
      mpfr_init (huge);
1811
      n = gfc_validate_kind (BT_INTEGER, expr->ts.kind, true);
1812
      ikind = expr->ts.kind;
1813
      if (n < 0)
1814
        {
1815
          n = gfc_validate_kind (BT_INTEGER, gfc_max_integer_kind, false);
1816
          ikind = gfc_max_integer_kind;
1817
        }
1818
      mpfr_set_z (huge, gfc_integer_kinds[n].huge, GFC_RND_MODE);
1819
      test = gfc_conv_mpfr_to_tree (huge, expr->ts.kind, 0);
1820
      test2 = fold_build2_loc (input_location, LT_EXPR, boolean_type_node,
1821
                               tmp, test);
1822
 
1823
      mpfr_neg (huge, huge, GFC_RND_MODE);
1824
      test = gfc_conv_mpfr_to_tree (huge, expr->ts.kind, 0);
1825
      test = fold_build2_loc (input_location, GT_EXPR, boolean_type_node, tmp,
1826
                              test);
1827
      test2 = fold_build2_loc (input_location, TRUTH_AND_EXPR,
1828
                               boolean_type_node, test, test2);
1829
 
1830
      itype = gfc_get_int_type (ikind);
1831
      if (modulo)
1832
       tmp = build_fix_expr (&se->pre, tmp, itype, RND_FLOOR);
1833
      else
1834
       tmp = build_fix_expr (&se->pre, tmp, itype, RND_TRUNC);
1835
      tmp = convert (type, tmp);
1836
      tmp = fold_build3_loc (input_location, COND_EXPR, type, test2, tmp,
1837
                             args[0]);
1838
      tmp = fold_build2_loc (input_location, MULT_EXPR, type, tmp, args[1]);
1839
      se->expr = fold_build2_loc (input_location, MINUS_EXPR, type, args[0],
1840
                                  tmp);
1841
      mpfr_clear (huge);
1842
      break;
1843
 
1844
    default:
1845
      gcc_unreachable ();
1846
    }
1847
}
1848
 
1849
/* DSHIFTL(I,J,S) = (I << S) | (J >> (BITSIZE(J) - S))
1850
   DSHIFTR(I,J,S) = (I << (BITSIZE(I) - S)) | (J >> S)
1851
   where the right shifts are logical (i.e. 0's are shifted in).
1852
   Because SHIFT_EXPR's want shifts strictly smaller than the integral
1853
   type width, we have to special-case both S == 0 and S == BITSIZE(J):
1854
     DSHIFTL(I,J,0) = I
1855
     DSHIFTL(I,J,BITSIZE) = J
1856
     DSHIFTR(I,J,0) = J
1857
     DSHIFTR(I,J,BITSIZE) = I.  */
1858
 
1859
static void
1860
gfc_conv_intrinsic_dshift (gfc_se * se, gfc_expr * expr, bool dshiftl)
1861
{
1862
  tree type, utype, stype, arg1, arg2, shift, res, left, right;
1863
  tree args[3], cond, tmp;
1864
  int bitsize;
1865
 
1866
  gfc_conv_intrinsic_function_args (se, expr, args, 3);
1867
 
1868
  gcc_assert (TREE_TYPE (args[0]) == TREE_TYPE (args[1]));
1869
  type = TREE_TYPE (args[0]);
1870
  bitsize = TYPE_PRECISION (type);
1871
  utype = unsigned_type_for (type);
1872
  stype = TREE_TYPE (args[2]);
1873
 
1874
  arg1 = gfc_evaluate_now (args[0], &se->pre);
1875
  arg2 = gfc_evaluate_now (args[1], &se->pre);
1876
  shift = gfc_evaluate_now (args[2], &se->pre);
1877
 
1878
  /* The generic case.  */
1879
  tmp = fold_build2_loc (input_location, MINUS_EXPR, stype,
1880
                         build_int_cst (stype, bitsize), shift);
1881
  left = fold_build2_loc (input_location, LSHIFT_EXPR, type,
1882
                          arg1, dshiftl ? shift : tmp);
1883
 
1884
  right = fold_build2_loc (input_location, RSHIFT_EXPR, utype,
1885
                           fold_convert (utype, arg2), dshiftl ? tmp : shift);
1886
  right = fold_convert (type, right);
1887
 
1888
  res = fold_build2_loc (input_location, BIT_IOR_EXPR, type, left, right);
1889
 
1890
  /* Special cases.  */
1891
  cond = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node, shift,
1892
                          build_int_cst (stype, 0));
1893
  res = fold_build3_loc (input_location, COND_EXPR, type, cond,
1894
                         dshiftl ? arg1 : arg2, res);
1895
 
1896
  cond = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node, shift,
1897
                          build_int_cst (stype, bitsize));
1898
  res = fold_build3_loc (input_location, COND_EXPR, type, cond,
1899
                         dshiftl ? arg2 : arg1, res);
1900
 
1901
  se->expr = res;
1902
}
1903
 
1904
 
1905
/* Positive difference DIM (x, y) = ((x - y) < 0) ? 0 : x - y.  */
1906
 
1907
static void
1908
gfc_conv_intrinsic_dim (gfc_se * se, gfc_expr * expr)
1909
{
1910
  tree val;
1911
  tree tmp;
1912
  tree type;
1913
  tree zero;
1914
  tree args[2];
1915
 
1916
  gfc_conv_intrinsic_function_args (se, expr, args, 2);
1917
  type = TREE_TYPE (args[0]);
1918
 
1919
  val = fold_build2_loc (input_location, MINUS_EXPR, type, args[0], args[1]);
1920
  val = gfc_evaluate_now (val, &se->pre);
1921
 
1922
  zero = gfc_build_const (type, integer_zero_node);
1923
  tmp = fold_build2_loc (input_location, LE_EXPR, boolean_type_node, val, zero);
1924
  se->expr = fold_build3_loc (input_location, COND_EXPR, type, tmp, zero, val);
1925
}
1926
 
1927
 
1928
/* SIGN(A, B) is absolute value of A times sign of B.
1929
   The real value versions use library functions to ensure the correct
1930
   handling of negative zero.  Integer case implemented as:
1931
   SIGN(A, B) = { tmp = (A ^ B) >> C; (A + tmp) ^ tmp }
1932
  */
1933
 
1934
static void
1935
gfc_conv_intrinsic_sign (gfc_se * se, gfc_expr * expr)
1936
{
1937
  tree tmp;
1938
  tree type;
1939
  tree args[2];
1940
 
1941
  gfc_conv_intrinsic_function_args (se, expr, args, 2);
1942
  if (expr->ts.type == BT_REAL)
1943
    {
1944
      tree abs;
1945
 
1946
      tmp = gfc_builtin_decl_for_float_kind (BUILT_IN_COPYSIGN, expr->ts.kind);
1947
      abs = gfc_builtin_decl_for_float_kind (BUILT_IN_FABS, expr->ts.kind);
1948
 
1949
      /* We explicitly have to ignore the minus sign. We do so by using
1950
         result = (arg1 == 0) ? abs(arg0) : copysign(arg0, arg1).  */
1951
      if (!gfc_option.flag_sign_zero
1952
          && MODE_HAS_SIGNED_ZEROS (TYPE_MODE (TREE_TYPE (args[1]))))
1953
        {
1954
          tree cond, zero;
1955
          zero = build_real_from_int_cst (TREE_TYPE (args[1]), integer_zero_node);
1956
          cond = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node,
1957
                                  args[1], zero);
1958
          se->expr = fold_build3_loc (input_location, COND_EXPR,
1959
                                  TREE_TYPE (args[0]), cond,
1960
                                  build_call_expr_loc (input_location, abs, 1,
1961
                                                       args[0]),
1962
                                  build_call_expr_loc (input_location, tmp, 2,
1963
                                                       args[0], args[1]));
1964
        }
1965
      else
1966
        se->expr = build_call_expr_loc (input_location, tmp, 2,
1967
                                        args[0], args[1]);
1968
      return;
1969
    }
1970
 
1971
  /* Having excluded floating point types, we know we are now dealing
1972
     with signed integer types.  */
1973
  type = TREE_TYPE (args[0]);
1974
 
1975
  /* Args[0] is used multiple times below.  */
1976
  args[0] = gfc_evaluate_now (args[0], &se->pre);
1977
 
1978
  /* Construct (A ^ B) >> 31, which generates a bit mask of all zeros if
1979
     the signs of A and B are the same, and of all ones if they differ.  */
1980
  tmp = fold_build2_loc (input_location, BIT_XOR_EXPR, type, args[0], args[1]);
1981
  tmp = fold_build2_loc (input_location, RSHIFT_EXPR, type, tmp,
1982
                         build_int_cst (type, TYPE_PRECISION (type) - 1));
1983
  tmp = gfc_evaluate_now (tmp, &se->pre);
1984
 
1985
  /* Construct (A + tmp) ^ tmp, which is A if tmp is zero, and -A if tmp]
1986
     is all ones (i.e. -1).  */
1987
  se->expr = fold_build2_loc (input_location, BIT_XOR_EXPR, type,
1988
                              fold_build2_loc (input_location, PLUS_EXPR,
1989
                                               type, args[0], tmp), tmp);
1990
}
1991
 
1992
 
1993
/* Test for the presence of an optional argument.  */
1994
 
1995
static void
1996
gfc_conv_intrinsic_present (gfc_se * se, gfc_expr * expr)
1997
{
1998
  gfc_expr *arg;
1999
 
2000
  arg = expr->value.function.actual->expr;
2001
  gcc_assert (arg->expr_type == EXPR_VARIABLE);
2002
  se->expr = gfc_conv_expr_present (arg->symtree->n.sym);
2003
  se->expr = convert (gfc_typenode_for_spec (&expr->ts), se->expr);
2004
}
2005
 
2006
 
2007
/* Calculate the double precision product of two single precision values.  */
2008
 
2009
static void
2010
gfc_conv_intrinsic_dprod (gfc_se * se, gfc_expr * expr)
2011
{
2012
  tree type;
2013
  tree args[2];
2014
 
2015
  gfc_conv_intrinsic_function_args (se, expr, args, 2);
2016
 
2017
  /* Convert the args to double precision before multiplying.  */
2018
  type = gfc_typenode_for_spec (&expr->ts);
2019
  args[0] = convert (type, args[0]);
2020
  args[1] = convert (type, args[1]);
2021
  se->expr = fold_build2_loc (input_location, MULT_EXPR, type, args[0],
2022
                              args[1]);
2023
}
2024
 
2025
 
2026
/* Return a length one character string containing an ascii character.  */
2027
 
2028
static void
2029
gfc_conv_intrinsic_char (gfc_se * se, gfc_expr * expr)
2030
{
2031
  tree arg[2];
2032
  tree var;
2033
  tree type;
2034
  unsigned int num_args;
2035
 
2036
  num_args = gfc_intrinsic_argument_list_length (expr);
2037
  gfc_conv_intrinsic_function_args (se, expr, arg, num_args);
2038
 
2039
  type = gfc_get_char_type (expr->ts.kind);
2040
  var = gfc_create_var (type, "char");
2041
 
2042
  arg[0] = fold_build1_loc (input_location, NOP_EXPR, type, arg[0]);
2043
  gfc_add_modify (&se->pre, var, arg[0]);
2044
  se->expr = gfc_build_addr_expr (build_pointer_type (type), var);
2045
  se->string_length = build_int_cst (gfc_charlen_type_node, 1);
2046
}
2047
 
2048
 
2049
static void
2050
gfc_conv_intrinsic_ctime (gfc_se * se, gfc_expr * expr)
2051
{
2052
  tree var;
2053
  tree len;
2054
  tree tmp;
2055
  tree cond;
2056
  tree fndecl;
2057
  tree *args;
2058
  unsigned int num_args;
2059
 
2060
  num_args = gfc_intrinsic_argument_list_length (expr) + 2;
2061
  args = XALLOCAVEC (tree, num_args);
2062
 
2063
  var = gfc_create_var (pchar_type_node, "pstr");
2064
  len = gfc_create_var (gfc_charlen_type_node, "len");
2065
 
2066
  gfc_conv_intrinsic_function_args (se, expr, &args[2], num_args - 2);
2067
  args[0] = gfc_build_addr_expr (NULL_TREE, var);
2068
  args[1] = gfc_build_addr_expr (NULL_TREE, len);
2069
 
2070
  fndecl = build_addr (gfor_fndecl_ctime, current_function_decl);
2071
  tmp = build_call_array_loc (input_location,
2072
                          TREE_TYPE (TREE_TYPE (gfor_fndecl_ctime)),
2073
                          fndecl, num_args, args);
2074
  gfc_add_expr_to_block (&se->pre, tmp);
2075
 
2076
  /* Free the temporary afterwards, if necessary.  */
2077
  cond = fold_build2_loc (input_location, GT_EXPR, boolean_type_node,
2078
                          len, build_int_cst (TREE_TYPE (len), 0));
2079
  tmp = gfc_call_free (var);
2080
  tmp = build3_v (COND_EXPR, cond, tmp, build_empty_stmt (input_location));
2081
  gfc_add_expr_to_block (&se->post, tmp);
2082
 
2083
  se->expr = var;
2084
  se->string_length = len;
2085
}
2086
 
2087
 
2088
static void
2089
gfc_conv_intrinsic_fdate (gfc_se * se, gfc_expr * expr)
2090
{
2091
  tree var;
2092
  tree len;
2093
  tree tmp;
2094
  tree cond;
2095
  tree fndecl;
2096
  tree *args;
2097
  unsigned int num_args;
2098
 
2099
  num_args = gfc_intrinsic_argument_list_length (expr) + 2;
2100
  args = XALLOCAVEC (tree, num_args);
2101
 
2102
  var = gfc_create_var (pchar_type_node, "pstr");
2103
  len = gfc_create_var (gfc_charlen_type_node, "len");
2104
 
2105
  gfc_conv_intrinsic_function_args (se, expr, &args[2], num_args - 2);
2106
  args[0] = gfc_build_addr_expr (NULL_TREE, var);
2107
  args[1] = gfc_build_addr_expr (NULL_TREE, len);
2108
 
2109
  fndecl = build_addr (gfor_fndecl_fdate, current_function_decl);
2110
  tmp = build_call_array_loc (input_location,
2111
                          TREE_TYPE (TREE_TYPE (gfor_fndecl_fdate)),
2112
                          fndecl, num_args, args);
2113
  gfc_add_expr_to_block (&se->pre, tmp);
2114
 
2115
  /* Free the temporary afterwards, if necessary.  */
2116
  cond = fold_build2_loc (input_location, GT_EXPR, boolean_type_node,
2117
                          len, build_int_cst (TREE_TYPE (len), 0));
2118
  tmp = gfc_call_free (var);
2119
  tmp = build3_v (COND_EXPR, cond, tmp, build_empty_stmt (input_location));
2120
  gfc_add_expr_to_block (&se->post, tmp);
2121
 
2122
  se->expr = var;
2123
  se->string_length = len;
2124
}
2125
 
2126
 
2127
/* Return a character string containing the tty name.  */
2128
 
2129
static void
2130
gfc_conv_intrinsic_ttynam (gfc_se * se, gfc_expr * expr)
2131
{
2132
  tree var;
2133
  tree len;
2134
  tree tmp;
2135
  tree cond;
2136
  tree fndecl;
2137
  tree *args;
2138
  unsigned int num_args;
2139
 
2140
  num_args = gfc_intrinsic_argument_list_length (expr) + 2;
2141
  args = XALLOCAVEC (tree, num_args);
2142
 
2143
  var = gfc_create_var (pchar_type_node, "pstr");
2144
  len = gfc_create_var (gfc_charlen_type_node, "len");
2145
 
2146
  gfc_conv_intrinsic_function_args (se, expr, &args[2], num_args - 2);
2147
  args[0] = gfc_build_addr_expr (NULL_TREE, var);
2148
  args[1] = gfc_build_addr_expr (NULL_TREE, len);
2149
 
2150
  fndecl = build_addr (gfor_fndecl_ttynam, current_function_decl);
2151
  tmp = build_call_array_loc (input_location,
2152
                          TREE_TYPE (TREE_TYPE (gfor_fndecl_ttynam)),
2153
                          fndecl, num_args, args);
2154
  gfc_add_expr_to_block (&se->pre, tmp);
2155
 
2156
  /* Free the temporary afterwards, if necessary.  */
2157
  cond = fold_build2_loc (input_location, GT_EXPR, boolean_type_node,
2158
                          len, build_int_cst (TREE_TYPE (len), 0));
2159
  tmp = gfc_call_free (var);
2160
  tmp = build3_v (COND_EXPR, cond, tmp, build_empty_stmt (input_location));
2161
  gfc_add_expr_to_block (&se->post, tmp);
2162
 
2163
  se->expr = var;
2164
  se->string_length = len;
2165
}
2166
 
2167
 
2168
/* Get the minimum/maximum value of all the parameters.
2169
    minmax (a1, a2, a3, ...)
2170
    {
2171
      mvar = a1;
2172
      if (a2 .op. mvar || isnan(mvar))
2173
        mvar = a2;
2174
      if (a3 .op. mvar || isnan(mvar))
2175
        mvar = a3;
2176
      ...
2177
      return mvar
2178
    }
2179
 */
2180
 
2181
/* TODO: Mismatching types can occur when specific names are used.
2182
   These should be handled during resolution.  */
2183
static void
2184
gfc_conv_intrinsic_minmax (gfc_se * se, gfc_expr * expr, enum tree_code op)
2185
{
2186
  tree tmp;
2187
  tree mvar;
2188
  tree val;
2189
  tree thencase;
2190
  tree *args;
2191
  tree type;
2192
  gfc_actual_arglist *argexpr;
2193
  unsigned int i, nargs;
2194
 
2195
  nargs = gfc_intrinsic_argument_list_length (expr);
2196
  args = XALLOCAVEC (tree, nargs);
2197
 
2198
  gfc_conv_intrinsic_function_args (se, expr, args, nargs);
2199
  type = gfc_typenode_for_spec (&expr->ts);
2200
 
2201
  argexpr = expr->value.function.actual;
2202
  if (TREE_TYPE (args[0]) != type)
2203
    args[0] = convert (type, args[0]);
2204
  /* Only evaluate the argument once.  */
2205
  if (TREE_CODE (args[0]) != VAR_DECL && !TREE_CONSTANT (args[0]))
2206
    args[0] = gfc_evaluate_now (args[0], &se->pre);
2207
 
2208
  mvar = gfc_create_var (type, "M");
2209
  gfc_add_modify (&se->pre, mvar, args[0]);
2210
  for (i = 1, argexpr = argexpr->next; i < nargs; i++)
2211
    {
2212
      tree cond, isnan;
2213
 
2214
      val = args[i];
2215
 
2216
      /* Handle absent optional arguments by ignoring the comparison.  */
2217
      if (argexpr->expr->expr_type == EXPR_VARIABLE
2218
          && argexpr->expr->symtree->n.sym->attr.optional
2219
          && TREE_CODE (val) == INDIRECT_REF)
2220
        cond = fold_build2_loc (input_location,
2221
                                NE_EXPR, boolean_type_node,
2222
                                TREE_OPERAND (val, 0),
2223
                        build_int_cst (TREE_TYPE (TREE_OPERAND (val, 0)), 0));
2224
      else
2225
      {
2226
        cond = NULL_TREE;
2227
 
2228
        /* Only evaluate the argument once.  */
2229
        if (TREE_CODE (val) != VAR_DECL && !TREE_CONSTANT (val))
2230
          val = gfc_evaluate_now (val, &se->pre);
2231
      }
2232
 
2233
      thencase = build2_v (MODIFY_EXPR, mvar, convert (type, val));
2234
 
2235
      tmp = fold_build2_loc (input_location, op, boolean_type_node,
2236
                             convert (type, val), mvar);
2237
 
2238
      /* FIXME: When the IEEE_ARITHMETIC module is implemented, the call to
2239
         __builtin_isnan might be made dependent on that module being loaded,
2240
         to help performance of programs that don't rely on IEEE semantics.  */
2241
      if (FLOAT_TYPE_P (TREE_TYPE (mvar)))
2242
        {
2243
          isnan = build_call_expr_loc (input_location,
2244
                                       builtin_decl_explicit (BUILT_IN_ISNAN),
2245
                                       1, mvar);
2246
          tmp = fold_build2_loc (input_location, TRUTH_OR_EXPR,
2247
                                 boolean_type_node, tmp,
2248
                                 fold_convert (boolean_type_node, isnan));
2249
        }
2250
      tmp = build3_v (COND_EXPR, tmp, thencase,
2251
                      build_empty_stmt (input_location));
2252
 
2253
      if (cond != NULL_TREE)
2254
        tmp = build3_v (COND_EXPR, cond, tmp,
2255
                        build_empty_stmt (input_location));
2256
 
2257
      gfc_add_expr_to_block (&se->pre, tmp);
2258
      argexpr = argexpr->next;
2259
    }
2260
  se->expr = mvar;
2261
}
2262
 
2263
 
2264
/* Generate library calls for MIN and MAX intrinsics for character
2265
   variables.  */
2266
static void
2267
gfc_conv_intrinsic_minmax_char (gfc_se * se, gfc_expr * expr, int op)
2268
{
2269
  tree *args;
2270
  tree var, len, fndecl, tmp, cond, function;
2271
  unsigned int nargs;
2272
 
2273
  nargs = gfc_intrinsic_argument_list_length (expr);
2274
  args = XALLOCAVEC (tree, nargs + 4);
2275
  gfc_conv_intrinsic_function_args (se, expr, &args[4], nargs);
2276
 
2277
  /* Create the result variables.  */
2278
  len = gfc_create_var (gfc_charlen_type_node, "len");
2279
  args[0] = gfc_build_addr_expr (NULL_TREE, len);
2280
  var = gfc_create_var (gfc_get_pchar_type (expr->ts.kind), "pstr");
2281
  args[1] = gfc_build_addr_expr (ppvoid_type_node, var);
2282
  args[2] = build_int_cst (integer_type_node, op);
2283
  args[3] = build_int_cst (integer_type_node, nargs / 2);
2284
 
2285
  if (expr->ts.kind == 1)
2286
    function = gfor_fndecl_string_minmax;
2287
  else if (expr->ts.kind == 4)
2288
    function = gfor_fndecl_string_minmax_char4;
2289
  else
2290
    gcc_unreachable ();
2291
 
2292
  /* Make the function call.  */
2293
  fndecl = build_addr (function, current_function_decl);
2294
  tmp = build_call_array_loc (input_location,
2295
                          TREE_TYPE (TREE_TYPE (function)), fndecl,
2296
                          nargs + 4, args);
2297
  gfc_add_expr_to_block (&se->pre, tmp);
2298
 
2299
  /* Free the temporary afterwards, if necessary.  */
2300
  cond = fold_build2_loc (input_location, GT_EXPR, boolean_type_node,
2301
                          len, build_int_cst (TREE_TYPE (len), 0));
2302
  tmp = gfc_call_free (var);
2303
  tmp = build3_v (COND_EXPR, cond, tmp, build_empty_stmt (input_location));
2304
  gfc_add_expr_to_block (&se->post, tmp);
2305
 
2306
  se->expr = var;
2307
  se->string_length = len;
2308
}
2309
 
2310
 
2311
/* Create a symbol node for this intrinsic.  The symbol from the frontend
2312
   has the generic name.  */
2313
 
2314
static gfc_symbol *
2315
gfc_get_symbol_for_expr (gfc_expr * expr)
2316
{
2317
  gfc_symbol *sym;
2318
 
2319
  /* TODO: Add symbols for intrinsic function to the global namespace.  */
2320
  gcc_assert (strlen (expr->value.function.name) <= GFC_MAX_SYMBOL_LEN - 5);
2321
  sym = gfc_new_symbol (expr->value.function.name, NULL);
2322
 
2323
  sym->ts = expr->ts;
2324
  sym->attr.external = 1;
2325
  sym->attr.function = 1;
2326
  sym->attr.always_explicit = 1;
2327
  sym->attr.proc = PROC_INTRINSIC;
2328
  sym->attr.flavor = FL_PROCEDURE;
2329
  sym->result = sym;
2330
  if (expr->rank > 0)
2331
    {
2332
      sym->attr.dimension = 1;
2333
      sym->as = gfc_get_array_spec ();
2334
      sym->as->type = AS_ASSUMED_SHAPE;
2335
      sym->as->rank = expr->rank;
2336
    }
2337
 
2338
  gfc_copy_formal_args_intr (sym, expr->value.function.isym);
2339
 
2340
  return sym;
2341
}
2342
 
2343
/* Generate a call to an external intrinsic function.  */
2344
static void
2345
gfc_conv_intrinsic_funcall (gfc_se * se, gfc_expr * expr)
2346
{
2347
  gfc_symbol *sym;
2348
  VEC(tree,gc) *append_args;
2349
 
2350
  gcc_assert (!se->ss || se->ss->info->expr == expr);
2351
 
2352
  if (se->ss)
2353
    gcc_assert (expr->rank > 0);
2354
  else
2355
    gcc_assert (expr->rank == 0);
2356
 
2357
  sym = gfc_get_symbol_for_expr (expr);
2358
 
2359
  /* Calls to libgfortran_matmul need to be appended special arguments,
2360
     to be able to call the BLAS ?gemm functions if required and possible.  */
2361
  append_args = NULL;
2362
  if (expr->value.function.isym->id == GFC_ISYM_MATMUL
2363
      && sym->ts.type != BT_LOGICAL)
2364
    {
2365
      tree cint = gfc_get_int_type (gfc_c_int_kind);
2366
 
2367
      if (gfc_option.flag_external_blas
2368
          && (sym->ts.type == BT_REAL || sym->ts.type == BT_COMPLEX)
2369
          && (sym->ts.kind == gfc_default_real_kind
2370
              || sym->ts.kind == gfc_default_double_kind))
2371
        {
2372
          tree gemm_fndecl;
2373
 
2374
          if (sym->ts.type == BT_REAL)
2375
            {
2376
              if (sym->ts.kind == gfc_default_real_kind)
2377
                gemm_fndecl = gfor_fndecl_sgemm;
2378
              else
2379
                gemm_fndecl = gfor_fndecl_dgemm;
2380
            }
2381
          else
2382
            {
2383
              if (sym->ts.kind == gfc_default_real_kind)
2384
                gemm_fndecl = gfor_fndecl_cgemm;
2385
              else
2386
                gemm_fndecl = gfor_fndecl_zgemm;
2387
            }
2388
 
2389
          append_args = VEC_alloc (tree, gc, 3);
2390
          VEC_quick_push (tree, append_args, build_int_cst (cint, 1));
2391
          VEC_quick_push (tree, append_args,
2392
                          build_int_cst (cint, gfc_option.blas_matmul_limit));
2393
          VEC_quick_push (tree, append_args,
2394
                          gfc_build_addr_expr (NULL_TREE, gemm_fndecl));
2395
        }
2396
      else
2397
        {
2398
          append_args = VEC_alloc (tree, gc, 3);
2399
          VEC_quick_push (tree, append_args, build_int_cst (cint, 0));
2400
          VEC_quick_push (tree, append_args, build_int_cst (cint, 0));
2401
          VEC_quick_push (tree, append_args, null_pointer_node);
2402
        }
2403
    }
2404
 
2405
  gfc_conv_procedure_call (se, sym, expr->value.function.actual, expr,
2406
                          append_args);
2407
  gfc_free_symbol (sym);
2408
}
2409
 
2410
/* ANY and ALL intrinsics. ANY->op == NE_EXPR, ALL->op == EQ_EXPR.
2411
   Implemented as
2412
    any(a)
2413
    {
2414
      forall (i=...)
2415
        if (a[i] != 0)
2416
          return 1
2417
      end forall
2418
      return 0
2419
    }
2420
    all(a)
2421
    {
2422
      forall (i=...)
2423
        if (a[i] == 0)
2424
          return 0
2425
      end forall
2426
      return 1
2427
    }
2428
 */
2429
static void
2430
gfc_conv_intrinsic_anyall (gfc_se * se, gfc_expr * expr, enum tree_code op)
2431
{
2432
  tree resvar;
2433
  stmtblock_t block;
2434
  stmtblock_t body;
2435
  tree type;
2436
  tree tmp;
2437
  tree found;
2438
  gfc_loopinfo loop;
2439
  gfc_actual_arglist *actual;
2440
  gfc_ss *arrayss;
2441
  gfc_se arrayse;
2442
  tree exit_label;
2443
 
2444
  if (se->ss)
2445
    {
2446
      gfc_conv_intrinsic_funcall (se, expr);
2447
      return;
2448
    }
2449
 
2450
  actual = expr->value.function.actual;
2451
  type = gfc_typenode_for_spec (&expr->ts);
2452
  /* Initialize the result.  */
2453
  resvar = gfc_create_var (type, "test");
2454
  if (op == EQ_EXPR)
2455
    tmp = convert (type, boolean_true_node);
2456
  else
2457
    tmp = convert (type, boolean_false_node);
2458
  gfc_add_modify (&se->pre, resvar, tmp);
2459
 
2460
  /* Walk the arguments.  */
2461
  arrayss = gfc_walk_expr (actual->expr);
2462
  gcc_assert (arrayss != gfc_ss_terminator);
2463
 
2464
  /* Initialize the scalarizer.  */
2465
  gfc_init_loopinfo (&loop);
2466
  exit_label = gfc_build_label_decl (NULL_TREE);
2467
  TREE_USED (exit_label) = 1;
2468
  gfc_add_ss_to_loop (&loop, arrayss);
2469
 
2470
  /* Initialize the loop.  */
2471
  gfc_conv_ss_startstride (&loop);
2472
  gfc_conv_loop_setup (&loop, &expr->where);
2473
 
2474
  gfc_mark_ss_chain_used (arrayss, 1);
2475
  /* Generate the loop body.  */
2476
  gfc_start_scalarized_body (&loop, &body);
2477
 
2478
  /* If the condition matches then set the return value.  */
2479
  gfc_start_block (&block);
2480
  if (op == EQ_EXPR)
2481
    tmp = convert (type, boolean_false_node);
2482
  else
2483
    tmp = convert (type, boolean_true_node);
2484
  gfc_add_modify (&block, resvar, tmp);
2485
 
2486
  /* And break out of the loop.  */
2487
  tmp = build1_v (GOTO_EXPR, exit_label);
2488
  gfc_add_expr_to_block (&block, tmp);
2489
 
2490
  found = gfc_finish_block (&block);
2491
 
2492
  /* Check this element.  */
2493
  gfc_init_se (&arrayse, NULL);
2494
  gfc_copy_loopinfo_to_se (&arrayse, &loop);
2495
  arrayse.ss = arrayss;
2496
  gfc_conv_expr_val (&arrayse, actual->expr);
2497
 
2498
  gfc_add_block_to_block (&body, &arrayse.pre);
2499
  tmp = fold_build2_loc (input_location, op, boolean_type_node, arrayse.expr,
2500
                         build_int_cst (TREE_TYPE (arrayse.expr), 0));
2501
  tmp = build3_v (COND_EXPR, tmp, found, build_empty_stmt (input_location));
2502
  gfc_add_expr_to_block (&body, tmp);
2503
  gfc_add_block_to_block (&body, &arrayse.post);
2504
 
2505
  gfc_trans_scalarizing_loops (&loop, &body);
2506
 
2507
  /* Add the exit label.  */
2508
  tmp = build1_v (LABEL_EXPR, exit_label);
2509
  gfc_add_expr_to_block (&loop.pre, tmp);
2510
 
2511
  gfc_add_block_to_block (&se->pre, &loop.pre);
2512
  gfc_add_block_to_block (&se->pre, &loop.post);
2513
  gfc_cleanup_loop (&loop);
2514
 
2515
  se->expr = resvar;
2516
}
2517
 
2518
/* COUNT(A) = Number of true elements in A.  */
2519
static void
2520
gfc_conv_intrinsic_count (gfc_se * se, gfc_expr * expr)
2521
{
2522
  tree resvar;
2523
  tree type;
2524
  stmtblock_t body;
2525
  tree tmp;
2526
  gfc_loopinfo loop;
2527
  gfc_actual_arglist *actual;
2528
  gfc_ss *arrayss;
2529
  gfc_se arrayse;
2530
 
2531
  if (se->ss)
2532
    {
2533
      gfc_conv_intrinsic_funcall (se, expr);
2534
      return;
2535
    }
2536
 
2537
  actual = expr->value.function.actual;
2538
 
2539
  type = gfc_typenode_for_spec (&expr->ts);
2540
  /* Initialize the result.  */
2541
  resvar = gfc_create_var (type, "count");
2542
  gfc_add_modify (&se->pre, resvar, build_int_cst (type, 0));
2543
 
2544
  /* Walk the arguments.  */
2545
  arrayss = gfc_walk_expr (actual->expr);
2546
  gcc_assert (arrayss != gfc_ss_terminator);
2547
 
2548
  /* Initialize the scalarizer.  */
2549
  gfc_init_loopinfo (&loop);
2550
  gfc_add_ss_to_loop (&loop, arrayss);
2551
 
2552
  /* Initialize the loop.  */
2553
  gfc_conv_ss_startstride (&loop);
2554
  gfc_conv_loop_setup (&loop, &expr->where);
2555
 
2556
  gfc_mark_ss_chain_used (arrayss, 1);
2557
  /* Generate the loop body.  */
2558
  gfc_start_scalarized_body (&loop, &body);
2559
 
2560
  tmp = fold_build2_loc (input_location, PLUS_EXPR, TREE_TYPE (resvar),
2561
                         resvar, build_int_cst (TREE_TYPE (resvar), 1));
2562
  tmp = build2_v (MODIFY_EXPR, resvar, tmp);
2563
 
2564
  gfc_init_se (&arrayse, NULL);
2565
  gfc_copy_loopinfo_to_se (&arrayse, &loop);
2566
  arrayse.ss = arrayss;
2567
  gfc_conv_expr_val (&arrayse, actual->expr);
2568
  tmp = build3_v (COND_EXPR, arrayse.expr, tmp,
2569
                  build_empty_stmt (input_location));
2570
 
2571
  gfc_add_block_to_block (&body, &arrayse.pre);
2572
  gfc_add_expr_to_block (&body, tmp);
2573
  gfc_add_block_to_block (&body, &arrayse.post);
2574
 
2575
  gfc_trans_scalarizing_loops (&loop, &body);
2576
 
2577
  gfc_add_block_to_block (&se->pre, &loop.pre);
2578
  gfc_add_block_to_block (&se->pre, &loop.post);
2579
  gfc_cleanup_loop (&loop);
2580
 
2581
  se->expr = resvar;
2582
}
2583
 
2584
 
2585
/* Update given gfc_se to have ss component pointing to the nested gfc_ss
2586
   struct and return the corresponding loopinfo.  */
2587
 
2588
static gfc_loopinfo *
2589
enter_nested_loop (gfc_se *se)
2590
{
2591
  se->ss = se->ss->nested_ss;
2592
  gcc_assert (se->ss == se->ss->loop->ss);
2593
 
2594
  return se->ss->loop;
2595
}
2596
 
2597
 
2598
/* Inline implementation of the sum and product intrinsics.  */
2599
static void
2600
gfc_conv_intrinsic_arith (gfc_se * se, gfc_expr * expr, enum tree_code op,
2601
                          bool norm2)
2602
{
2603
  tree resvar;
2604
  tree scale = NULL_TREE;
2605
  tree type;
2606
  stmtblock_t body;
2607
  stmtblock_t block;
2608
  tree tmp;
2609
  gfc_loopinfo loop, *ploop;
2610
  gfc_actual_arglist *arg_array, *arg_mask;
2611
  gfc_ss *arrayss = NULL;
2612
  gfc_ss *maskss = NULL;
2613
  gfc_se arrayse;
2614
  gfc_se maskse;
2615
  gfc_se *parent_se;
2616
  gfc_expr *arrayexpr;
2617
  gfc_expr *maskexpr;
2618
 
2619
  if (expr->rank > 0)
2620
    {
2621
      gcc_assert (gfc_inline_intrinsic_function_p (expr));
2622
      parent_se = se;
2623
    }
2624
  else
2625
    parent_se = NULL;
2626
 
2627
  type = gfc_typenode_for_spec (&expr->ts);
2628
  /* Initialize the result.  */
2629
  resvar = gfc_create_var (type, "val");
2630
  if (norm2)
2631
    {
2632
      /* result = 0.0;
2633
         scale = 1.0.  */
2634
      scale = gfc_create_var (type, "scale");
2635
      gfc_add_modify (&se->pre, scale,
2636
                      gfc_build_const (type, integer_one_node));
2637
      tmp = gfc_build_const (type, integer_zero_node);
2638
    }
2639
  else if (op == PLUS_EXPR || op == BIT_IOR_EXPR || op == BIT_XOR_EXPR)
2640
    tmp = gfc_build_const (type, integer_zero_node);
2641
  else if (op == NE_EXPR)
2642
    /* PARITY.  */
2643
    tmp = convert (type, boolean_false_node);
2644
  else if (op == BIT_AND_EXPR)
2645
    tmp = gfc_build_const (type, fold_build1_loc (input_location, NEGATE_EXPR,
2646
                                                  type, integer_one_node));
2647
  else
2648
    tmp = gfc_build_const (type, integer_one_node);
2649
 
2650
  gfc_add_modify (&se->pre, resvar, tmp);
2651
 
2652
  arg_array = expr->value.function.actual;
2653
 
2654
  arrayexpr = arg_array->expr;
2655
 
2656
  if (op == NE_EXPR || norm2)
2657
    /* PARITY and NORM2.  */
2658
    maskexpr = NULL;
2659
  else
2660
    {
2661
      arg_mask  = arg_array->next->next;
2662
      gcc_assert (arg_mask != NULL);
2663
      maskexpr = arg_mask->expr;
2664
    }
2665
 
2666
  if (expr->rank == 0)
2667
    {
2668
      /* Walk the arguments.  */
2669
      arrayss = gfc_walk_expr (arrayexpr);
2670
      gcc_assert (arrayss != gfc_ss_terminator);
2671
 
2672
      if (maskexpr && maskexpr->rank > 0)
2673
        {
2674
          maskss = gfc_walk_expr (maskexpr);
2675
          gcc_assert (maskss != gfc_ss_terminator);
2676
        }
2677
      else
2678
        maskss = NULL;
2679
 
2680
      /* Initialize the scalarizer.  */
2681
      gfc_init_loopinfo (&loop);
2682
      gfc_add_ss_to_loop (&loop, arrayss);
2683
      if (maskexpr && maskexpr->rank > 0)
2684
        gfc_add_ss_to_loop (&loop, maskss);
2685
 
2686
      /* Initialize the loop.  */
2687
      gfc_conv_ss_startstride (&loop);
2688
      gfc_conv_loop_setup (&loop, &expr->where);
2689
 
2690
      gfc_mark_ss_chain_used (arrayss, 1);
2691
      if (maskexpr && maskexpr->rank > 0)
2692
        gfc_mark_ss_chain_used (maskss, 1);
2693
 
2694
      ploop = &loop;
2695
    }
2696
  else
2697
    /* All the work has been done in the parent loops.  */
2698
    ploop = enter_nested_loop (se);
2699
 
2700
  gcc_assert (ploop);
2701
 
2702
  /* Generate the loop body.  */
2703
  gfc_start_scalarized_body (ploop, &body);
2704
 
2705
  /* If we have a mask, only add this element if the mask is set.  */
2706
  if (maskexpr && maskexpr->rank > 0)
2707
    {
2708
      gfc_init_se (&maskse, parent_se);
2709
      gfc_copy_loopinfo_to_se (&maskse, ploop);
2710
      if (expr->rank == 0)
2711
        maskse.ss = maskss;
2712
      gfc_conv_expr_val (&maskse, maskexpr);
2713
      gfc_add_block_to_block (&body, &maskse.pre);
2714
 
2715
      gfc_start_block (&block);
2716
    }
2717
  else
2718
    gfc_init_block (&block);
2719
 
2720
  /* Do the actual summation/product.  */
2721
  gfc_init_se (&arrayse, parent_se);
2722
  gfc_copy_loopinfo_to_se (&arrayse, ploop);
2723
  if (expr->rank == 0)
2724
    arrayse.ss = arrayss;
2725
  gfc_conv_expr_val (&arrayse, arrayexpr);
2726
  gfc_add_block_to_block (&block, &arrayse.pre);
2727
 
2728
  if (norm2)
2729
    {
2730
      /* if (x(i) != 0.0)
2731
           {
2732
             absX = abs(x(i))
2733
             if (absX > scale)
2734
               {
2735
                 val = scale/absX;
2736
                 result = 1.0 + result * val * val;
2737
                 scale = absX;
2738
               }
2739
             else
2740
               {
2741
                 val = absX/scale;
2742
                 result += val * val;
2743
               }
2744
           }  */
2745
      tree res1, res2, cond, absX, val;
2746
      stmtblock_t ifblock1, ifblock2, ifblock3;
2747
 
2748
      gfc_init_block (&ifblock1);
2749
 
2750
      absX = gfc_create_var (type, "absX");
2751
      gfc_add_modify (&ifblock1, absX,
2752
                      fold_build1_loc (input_location, ABS_EXPR, type,
2753
                                       arrayse.expr));
2754
      val = gfc_create_var (type, "val");
2755
      gfc_add_expr_to_block (&ifblock1, val);
2756
 
2757
      gfc_init_block (&ifblock2);
2758
      gfc_add_modify (&ifblock2, val,
2759
                      fold_build2_loc (input_location, RDIV_EXPR, type, scale,
2760
                                       absX));
2761
      res1 = fold_build2_loc (input_location, MULT_EXPR, type, val, val);
2762
      res1 = fold_build2_loc (input_location, MULT_EXPR, type, resvar, res1);
2763
      res1 = fold_build2_loc (input_location, PLUS_EXPR, type, res1,
2764
                              gfc_build_const (type, integer_one_node));
2765
      gfc_add_modify (&ifblock2, resvar, res1);
2766
      gfc_add_modify (&ifblock2, scale, absX);
2767
      res1 = gfc_finish_block (&ifblock2);
2768
 
2769
      gfc_init_block (&ifblock3);
2770
      gfc_add_modify (&ifblock3, val,
2771
                      fold_build2_loc (input_location, RDIV_EXPR, type, absX,
2772
                                       scale));
2773
      res2 = fold_build2_loc (input_location, MULT_EXPR, type, val, val);
2774
      res2 = fold_build2_loc (input_location, PLUS_EXPR, type, resvar, res2);
2775
      gfc_add_modify (&ifblock3, resvar, res2);
2776
      res2 = gfc_finish_block (&ifblock3);
2777
 
2778
      cond = fold_build2_loc (input_location, GT_EXPR, boolean_type_node,
2779
                              absX, scale);
2780
      tmp = build3_v (COND_EXPR, cond, res1, res2);
2781
      gfc_add_expr_to_block (&ifblock1, tmp);
2782
      tmp = gfc_finish_block (&ifblock1);
2783
 
2784
      cond = fold_build2_loc (input_location, NE_EXPR, boolean_type_node,
2785
                              arrayse.expr,
2786
                              gfc_build_const (type, integer_zero_node));
2787
 
2788
      tmp = build3_v (COND_EXPR, cond, tmp, build_empty_stmt (input_location));
2789
      gfc_add_expr_to_block (&block, tmp);
2790
    }
2791
  else
2792
    {
2793
      tmp = fold_build2_loc (input_location, op, type, resvar, arrayse.expr);
2794
      gfc_add_modify (&block, resvar, tmp);
2795
    }
2796
 
2797
  gfc_add_block_to_block (&block, &arrayse.post);
2798
 
2799
  if (maskexpr && maskexpr->rank > 0)
2800
    {
2801
      /* We enclose the above in if (mask) {...} .  */
2802
 
2803
      tmp = gfc_finish_block (&block);
2804
      tmp = build3_v (COND_EXPR, maskse.expr, tmp,
2805
                      build_empty_stmt (input_location));
2806
    }
2807
  else
2808
    tmp = gfc_finish_block (&block);
2809
  gfc_add_expr_to_block (&body, tmp);
2810
 
2811
  gfc_trans_scalarizing_loops (ploop, &body);
2812
 
2813
  /* For a scalar mask, enclose the loop in an if statement.  */
2814
  if (maskexpr && maskexpr->rank == 0)
2815
    {
2816
      gfc_init_block (&block);
2817
      gfc_add_block_to_block (&block, &ploop->pre);
2818
      gfc_add_block_to_block (&block, &ploop->post);
2819
      tmp = gfc_finish_block (&block);
2820
 
2821
      if (expr->rank > 0)
2822
        {
2823
          tmp = build3_v (COND_EXPR, se->ss->info->data.scalar.value, tmp,
2824
                          build_empty_stmt (input_location));
2825
          gfc_advance_se_ss_chain (se);
2826
        }
2827
      else
2828
        {
2829
          gcc_assert (expr->rank == 0);
2830
          gfc_init_se (&maskse, NULL);
2831
          gfc_conv_expr_val (&maskse, maskexpr);
2832
          tmp = build3_v (COND_EXPR, maskse.expr, tmp,
2833
                          build_empty_stmt (input_location));
2834
        }
2835
 
2836
      gfc_add_expr_to_block (&block, tmp);
2837
      gfc_add_block_to_block (&se->pre, &block);
2838
      gcc_assert (se->post.head == NULL);
2839
    }
2840
  else
2841
    {
2842
      gfc_add_block_to_block (&se->pre, &ploop->pre);
2843
      gfc_add_block_to_block (&se->pre, &ploop->post);
2844
    }
2845
 
2846
  if (expr->rank == 0)
2847
    gfc_cleanup_loop (ploop);
2848
 
2849
  if (norm2)
2850
    {
2851
      /* result = scale * sqrt(result).  */
2852
      tree sqrt;
2853
      sqrt = gfc_builtin_decl_for_float_kind (BUILT_IN_SQRT, expr->ts.kind);
2854
      resvar = build_call_expr_loc (input_location,
2855
                                    sqrt, 1, resvar);
2856
      resvar = fold_build2_loc (input_location, MULT_EXPR, type, scale, resvar);
2857
    }
2858
 
2859
  se->expr = resvar;
2860
}
2861
 
2862
 
2863
/* Inline implementation of the dot_product intrinsic. This function
2864
   is based on gfc_conv_intrinsic_arith (the previous function).  */
2865
static void
2866
gfc_conv_intrinsic_dot_product (gfc_se * se, gfc_expr * expr)
2867
{
2868
  tree resvar;
2869
  tree type;
2870
  stmtblock_t body;
2871
  stmtblock_t block;
2872
  tree tmp;
2873
  gfc_loopinfo loop;
2874
  gfc_actual_arglist *actual;
2875
  gfc_ss *arrayss1, *arrayss2;
2876
  gfc_se arrayse1, arrayse2;
2877
  gfc_expr *arrayexpr1, *arrayexpr2;
2878
 
2879
  type = gfc_typenode_for_spec (&expr->ts);
2880
 
2881
  /* Initialize the result.  */
2882
  resvar = gfc_create_var (type, "val");
2883
  if (expr->ts.type == BT_LOGICAL)
2884
    tmp = build_int_cst (type, 0);
2885
  else
2886
    tmp = gfc_build_const (type, integer_zero_node);
2887
 
2888
  gfc_add_modify (&se->pre, resvar, tmp);
2889
 
2890
  /* Walk argument #1.  */
2891
  actual = expr->value.function.actual;
2892
  arrayexpr1 = actual->expr;
2893
  arrayss1 = gfc_walk_expr (arrayexpr1);
2894
  gcc_assert (arrayss1 != gfc_ss_terminator);
2895
 
2896
  /* Walk argument #2.  */
2897
  actual = actual->next;
2898
  arrayexpr2 = actual->expr;
2899
  arrayss2 = gfc_walk_expr (arrayexpr2);
2900
  gcc_assert (arrayss2 != gfc_ss_terminator);
2901
 
2902
  /* Initialize the scalarizer.  */
2903
  gfc_init_loopinfo (&loop);
2904
  gfc_add_ss_to_loop (&loop, arrayss1);
2905
  gfc_add_ss_to_loop (&loop, arrayss2);
2906
 
2907
  /* Initialize the loop.  */
2908
  gfc_conv_ss_startstride (&loop);
2909
  gfc_conv_loop_setup (&loop, &expr->where);
2910
 
2911
  gfc_mark_ss_chain_used (arrayss1, 1);
2912
  gfc_mark_ss_chain_used (arrayss2, 1);
2913
 
2914
  /* Generate the loop body.  */
2915
  gfc_start_scalarized_body (&loop, &body);
2916
  gfc_init_block (&block);
2917
 
2918
  /* Make the tree expression for [conjg(]array1[)].  */
2919
  gfc_init_se (&arrayse1, NULL);
2920
  gfc_copy_loopinfo_to_se (&arrayse1, &loop);
2921
  arrayse1.ss = arrayss1;
2922
  gfc_conv_expr_val (&arrayse1, arrayexpr1);
2923
  if (expr->ts.type == BT_COMPLEX)
2924
    arrayse1.expr = fold_build1_loc (input_location, CONJ_EXPR, type,
2925
                                     arrayse1.expr);
2926
  gfc_add_block_to_block (&block, &arrayse1.pre);
2927
 
2928
  /* Make the tree expression for array2.  */
2929
  gfc_init_se (&arrayse2, NULL);
2930
  gfc_copy_loopinfo_to_se (&arrayse2, &loop);
2931
  arrayse2.ss = arrayss2;
2932
  gfc_conv_expr_val (&arrayse2, arrayexpr2);
2933
  gfc_add_block_to_block (&block, &arrayse2.pre);
2934
 
2935
  /* Do the actual product and sum.  */
2936
  if (expr->ts.type == BT_LOGICAL)
2937
    {
2938
      tmp = fold_build2_loc (input_location, TRUTH_AND_EXPR, type,
2939
                             arrayse1.expr, arrayse2.expr);
2940
      tmp = fold_build2_loc (input_location, TRUTH_OR_EXPR, type, resvar, tmp);
2941
    }
2942
  else
2943
    {
2944
      tmp = fold_build2_loc (input_location, MULT_EXPR, type, arrayse1.expr,
2945
                             arrayse2.expr);
2946
      tmp = fold_build2_loc (input_location, PLUS_EXPR, type, resvar, tmp);
2947
    }
2948
  gfc_add_modify (&block, resvar, tmp);
2949
 
2950
  /* Finish up the loop block and the loop.  */
2951
  tmp = gfc_finish_block (&block);
2952
  gfc_add_expr_to_block (&body, tmp);
2953
 
2954
  gfc_trans_scalarizing_loops (&loop, &body);
2955
  gfc_add_block_to_block (&se->pre, &loop.pre);
2956
  gfc_add_block_to_block (&se->pre, &loop.post);
2957
  gfc_cleanup_loop (&loop);
2958
 
2959
  se->expr = resvar;
2960
}
2961
 
2962
 
2963
/* Emit code for minloc or maxloc intrinsic.  There are many different cases
2964
   we need to handle.  For performance reasons we sometimes create two
2965
   loops instead of one, where the second one is much simpler.
2966
   Examples for minloc intrinsic:
2967
   1) Result is an array, a call is generated
2968
   2) Array mask is used and NaNs need to be supported:
2969
      limit = Infinity;
2970
      pos = 0;
2971
      S = from;
2972
      while (S <= to) {
2973
        if (mask[S]) {
2974
          if (pos == 0) pos = S + (1 - from);
2975
          if (a[S] <= limit) { limit = a[S]; pos = S + (1 - from); goto lab1; }
2976
        }
2977
        S++;
2978
      }
2979
      goto lab2;
2980
      lab1:;
2981
      while (S <= to) {
2982
        if (mask[S]) if (a[S] < limit) { limit = a[S]; pos = S + (1 - from); }
2983
        S++;
2984
      }
2985
      lab2:;
2986
   3) NaNs need to be supported, but it is known at compile time or cheaply
2987
      at runtime whether array is nonempty or not:
2988
      limit = Infinity;
2989
      pos = 0;
2990
      S = from;
2991
      while (S <= to) {
2992
        if (a[S] <= limit) { limit = a[S]; pos = S + (1 - from); goto lab1; }
2993
        S++;
2994
      }
2995
      if (from <= to) pos = 1;
2996
      goto lab2;
2997
      lab1:;
2998
      while (S <= to) {
2999
        if (a[S] < limit) { limit = a[S]; pos = S + (1 - from); }
3000
        S++;
3001
      }
3002
      lab2:;
3003
   4) NaNs aren't supported, array mask is used:
3004
      limit = infinities_supported ? Infinity : huge (limit);
3005
      pos = 0;
3006
      S = from;
3007
      while (S <= to) {
3008
        if (mask[S]) { limit = a[S]; pos = S + (1 - from); goto lab1; }
3009
        S++;
3010
      }
3011
      goto lab2;
3012
      lab1:;
3013
      while (S <= to) {
3014
        if (mask[S]) if (a[S] < limit) { limit = a[S]; pos = S + (1 - from); }
3015
        S++;
3016
      }
3017
      lab2:;
3018
   5) Same without array mask:
3019
      limit = infinities_supported ? Infinity : huge (limit);
3020
      pos = (from <= to) ? 1 : 0;
3021
      S = from;
3022
      while (S <= to) {
3023
        if (a[S] < limit) { limit = a[S]; pos = S + (1 - from); }
3024
        S++;
3025
      }
3026
   For 3) and 5), if mask is scalar, this all goes into a conditional,
3027
   setting pos = 0; in the else branch.  */
3028
 
3029
static void
3030
gfc_conv_intrinsic_minmaxloc (gfc_se * se, gfc_expr * expr, enum tree_code op)
3031
{
3032
  stmtblock_t body;
3033
  stmtblock_t block;
3034
  stmtblock_t ifblock;
3035
  stmtblock_t elseblock;
3036
  tree limit;
3037
  tree type;
3038
  tree tmp;
3039
  tree cond;
3040
  tree elsetmp;
3041
  tree ifbody;
3042
  tree offset;
3043
  tree nonempty;
3044
  tree lab1, lab2;
3045
  gfc_loopinfo loop;
3046
  gfc_actual_arglist *actual;
3047
  gfc_ss *arrayss;
3048
  gfc_ss *maskss;
3049
  gfc_se arrayse;
3050
  gfc_se maskse;
3051
  gfc_expr *arrayexpr;
3052
  gfc_expr *maskexpr;
3053
  tree pos;
3054
  int n;
3055
 
3056
  if (se->ss)
3057
    {
3058
      gfc_conv_intrinsic_funcall (se, expr);
3059
      return;
3060
    }
3061
 
3062
  /* Initialize the result.  */
3063
  pos = gfc_create_var (gfc_array_index_type, "pos");
3064
  offset = gfc_create_var (gfc_array_index_type, "offset");
3065
  type = gfc_typenode_for_spec (&expr->ts);
3066
 
3067
  /* Walk the arguments.  */
3068
  actual = expr->value.function.actual;
3069
  arrayexpr = actual->expr;
3070
  arrayss = gfc_walk_expr (arrayexpr);
3071
  gcc_assert (arrayss != gfc_ss_terminator);
3072
 
3073
  actual = actual->next->next;
3074
  gcc_assert (actual);
3075
  maskexpr = actual->expr;
3076
  nonempty = NULL;
3077
  if (maskexpr && maskexpr->rank != 0)
3078
    {
3079
      maskss = gfc_walk_expr (maskexpr);
3080
      gcc_assert (maskss != gfc_ss_terminator);
3081
    }
3082
  else
3083
    {
3084
      mpz_t asize;
3085
      if (gfc_array_size (arrayexpr, &asize) == SUCCESS)
3086
        {
3087
          nonempty = gfc_conv_mpz_to_tree (asize, gfc_index_integer_kind);
3088
          mpz_clear (asize);
3089
          nonempty = fold_build2_loc (input_location, GT_EXPR,
3090
                                      boolean_type_node, nonempty,
3091
                                      gfc_index_zero_node);
3092
        }
3093
      maskss = NULL;
3094
    }
3095
 
3096
  limit = gfc_create_var (gfc_typenode_for_spec (&arrayexpr->ts), "limit");
3097
  switch (arrayexpr->ts.type)
3098
    {
3099
    case BT_REAL:
3100
      tmp = gfc_build_inf_or_huge (TREE_TYPE (limit), arrayexpr->ts.kind);
3101
      break;
3102
 
3103
    case BT_INTEGER:
3104
      n = gfc_validate_kind (arrayexpr->ts.type, arrayexpr->ts.kind, false);
3105
      tmp = gfc_conv_mpz_to_tree (gfc_integer_kinds[n].huge,
3106
                                  arrayexpr->ts.kind);
3107
      break;
3108
 
3109
    default:
3110
      gcc_unreachable ();
3111
    }
3112
 
3113
  /* We start with the most negative possible value for MAXLOC, and the most
3114
     positive possible value for MINLOC. The most negative possible value is
3115
     -HUGE for BT_REAL and (-HUGE - 1) for BT_INTEGER; the most positive
3116
     possible value is HUGE in both cases.  */
3117
  if (op == GT_EXPR)
3118
    tmp = fold_build1_loc (input_location, NEGATE_EXPR, TREE_TYPE (tmp), tmp);
3119
  if (op == GT_EXPR && expr->ts.type == BT_INTEGER)
3120
    tmp = fold_build2_loc (input_location, MINUS_EXPR, TREE_TYPE (tmp), tmp,
3121
                           build_int_cst (type, 1));
3122
 
3123
  gfc_add_modify (&se->pre, limit, tmp);
3124
 
3125
  /* Initialize the scalarizer.  */
3126
  gfc_init_loopinfo (&loop);
3127
  gfc_add_ss_to_loop (&loop, arrayss);
3128
  if (maskss)
3129
    gfc_add_ss_to_loop (&loop, maskss);
3130
 
3131
  /* Initialize the loop.  */
3132
  gfc_conv_ss_startstride (&loop);
3133
 
3134
  /* The code generated can have more than one loop in sequence (see the
3135
     comment at the function header).  This doesn't work well with the
3136
     scalarizer, which changes arrays' offset when the scalarization loops
3137
     are generated (see gfc_trans_preloop_setup).  Fortunately, {min,max}loc
3138
     are  currently inlined in the scalar case only (for which loop is of rank
3139
     one).  As there is no dependency to care about in that case, there is no
3140
     temporary, so that we can use the scalarizer temporary code to handle
3141
     multiple loops.  Thus, we set temp_dim here, we call gfc_mark_ss_chain_used
3142
     with flag=3 later, and we use gfc_trans_scalarized_loop_boundary even later
3143
     to restore offset.
3144
     TODO: this prevents inlining of rank > 0 minmaxloc calls, so this
3145
     should eventually go away.  We could either create two loops properly,
3146
     or find another way to save/restore the array offsets between the two
3147
     loops (without conflicting with temporary management), or use a single
3148
     loop minmaxloc implementation.  See PR 31067.  */
3149
  loop.temp_dim = loop.dimen;
3150
  gfc_conv_loop_setup (&loop, &expr->where);
3151
 
3152
  gcc_assert (loop.dimen == 1);
3153
  if (nonempty == NULL && maskss == NULL && loop.from[0] && loop.to[0])
3154
    nonempty = fold_build2_loc (input_location, LE_EXPR, boolean_type_node,
3155
                                loop.from[0], loop.to[0]);
3156
 
3157
  lab1 = NULL;
3158
  lab2 = NULL;
3159
  /* Initialize the position to zero, following Fortran 2003.  We are free
3160
     to do this because Fortran 95 allows the result of an entirely false
3161
     mask to be processor dependent.  If we know at compile time the array
3162
     is non-empty and no MASK is used, we can initialize to 1 to simplify
3163
     the inner loop.  */
3164
  if (nonempty != NULL && !HONOR_NANS (DECL_MODE (limit)))
3165
    gfc_add_modify (&loop.pre, pos,
3166
                    fold_build3_loc (input_location, COND_EXPR,
3167
                                     gfc_array_index_type,
3168
                                     nonempty, gfc_index_one_node,
3169
                                     gfc_index_zero_node));
3170
  else
3171
    {
3172
      gfc_add_modify (&loop.pre, pos, gfc_index_zero_node);
3173
      lab1 = gfc_build_label_decl (NULL_TREE);
3174
      TREE_USED (lab1) = 1;
3175
      lab2 = gfc_build_label_decl (NULL_TREE);
3176
      TREE_USED (lab2) = 1;
3177
    }
3178
 
3179
  /* An offset must be added to the loop
3180
     counter to obtain the required position.  */
3181
  gcc_assert (loop.from[0]);
3182
 
3183
  tmp = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
3184
                         gfc_index_one_node, loop.from[0]);
3185
  gfc_add_modify (&loop.pre, offset, tmp);
3186
 
3187
  gfc_mark_ss_chain_used (arrayss, lab1 ? 3 : 1);
3188
  if (maskss)
3189
    gfc_mark_ss_chain_used (maskss, lab1 ? 3 : 1);
3190
  /* Generate the loop body.  */
3191
  gfc_start_scalarized_body (&loop, &body);
3192
 
3193
  /* If we have a mask, only check this element if the mask is set.  */
3194
  if (maskss)
3195
    {
3196
      gfc_init_se (&maskse, NULL);
3197
      gfc_copy_loopinfo_to_se (&maskse, &loop);
3198
      maskse.ss = maskss;
3199
      gfc_conv_expr_val (&maskse, maskexpr);
3200
      gfc_add_block_to_block (&body, &maskse.pre);
3201
 
3202
      gfc_start_block (&block);
3203
    }
3204
  else
3205
    gfc_init_block (&block);
3206
 
3207
  /* Compare with the current limit.  */
3208
  gfc_init_se (&arrayse, NULL);
3209
  gfc_copy_loopinfo_to_se (&arrayse, &loop);
3210
  arrayse.ss = arrayss;
3211
  gfc_conv_expr_val (&arrayse, arrayexpr);
3212
  gfc_add_block_to_block (&block, &arrayse.pre);
3213
 
3214
  /* We do the following if this is a more extreme value.  */
3215
  gfc_start_block (&ifblock);
3216
 
3217
  /* Assign the value to the limit...  */
3218
  gfc_add_modify (&ifblock, limit, arrayse.expr);
3219
 
3220
  if (nonempty == NULL && HONOR_NANS (DECL_MODE (limit)))
3221
    {
3222
      stmtblock_t ifblock2;
3223
      tree ifbody2;
3224
 
3225
      gfc_start_block (&ifblock2);
3226
      tmp = fold_build2_loc (input_location, PLUS_EXPR, TREE_TYPE (pos),
3227
                             loop.loopvar[0], offset);
3228
      gfc_add_modify (&ifblock2, pos, tmp);
3229
      ifbody2 = gfc_finish_block (&ifblock2);
3230
      cond = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node, pos,
3231
                              gfc_index_zero_node);
3232
      tmp = build3_v (COND_EXPR, cond, ifbody2,
3233
                      build_empty_stmt (input_location));
3234
      gfc_add_expr_to_block (&block, tmp);
3235
    }
3236
 
3237
  tmp = fold_build2_loc (input_location, PLUS_EXPR, TREE_TYPE (pos),
3238
                         loop.loopvar[0], offset);
3239
  gfc_add_modify (&ifblock, pos, tmp);
3240
 
3241
  if (lab1)
3242
    gfc_add_expr_to_block (&ifblock, build1_v (GOTO_EXPR, lab1));
3243
 
3244
  ifbody = gfc_finish_block (&ifblock);
3245
 
3246
  if (!lab1 || HONOR_NANS (DECL_MODE (limit)))
3247
    {
3248
      if (lab1)
3249
        cond = fold_build2_loc (input_location,
3250
                                op == GT_EXPR ? GE_EXPR : LE_EXPR,
3251
                                boolean_type_node, arrayse.expr, limit);
3252
      else
3253
        cond = fold_build2_loc (input_location, op, boolean_type_node,
3254
                                arrayse.expr, limit);
3255
 
3256
      ifbody = build3_v (COND_EXPR, cond, ifbody,
3257
                         build_empty_stmt (input_location));
3258
    }
3259
  gfc_add_expr_to_block (&block, ifbody);
3260
 
3261
  if (maskss)
3262
    {
3263
      /* We enclose the above in if (mask) {...}.  */
3264
      tmp = gfc_finish_block (&block);
3265
 
3266
      tmp = build3_v (COND_EXPR, maskse.expr, tmp,
3267
                      build_empty_stmt (input_location));
3268
    }
3269
  else
3270
    tmp = gfc_finish_block (&block);
3271
  gfc_add_expr_to_block (&body, tmp);
3272
 
3273
  if (lab1)
3274
    {
3275
      gfc_trans_scalarized_loop_boundary (&loop, &body);
3276
 
3277
      if (HONOR_NANS (DECL_MODE (limit)))
3278
        {
3279
          if (nonempty != NULL)
3280
            {
3281
              ifbody = build2_v (MODIFY_EXPR, pos, gfc_index_one_node);
3282
              tmp = build3_v (COND_EXPR, nonempty, ifbody,
3283
                              build_empty_stmt (input_location));
3284
              gfc_add_expr_to_block (&loop.code[0], tmp);
3285
            }
3286
        }
3287
 
3288
      gfc_add_expr_to_block (&loop.code[0], build1_v (GOTO_EXPR, lab2));
3289
      gfc_add_expr_to_block (&loop.code[0], build1_v (LABEL_EXPR, lab1));
3290
 
3291
      /* If we have a mask, only check this element if the mask is set.  */
3292
      if (maskss)
3293
        {
3294
          gfc_init_se (&maskse, NULL);
3295
          gfc_copy_loopinfo_to_se (&maskse, &loop);
3296
          maskse.ss = maskss;
3297
          gfc_conv_expr_val (&maskse, maskexpr);
3298
          gfc_add_block_to_block (&body, &maskse.pre);
3299
 
3300
          gfc_start_block (&block);
3301
        }
3302
      else
3303
        gfc_init_block (&block);
3304
 
3305
      /* Compare with the current limit.  */
3306
      gfc_init_se (&arrayse, NULL);
3307
      gfc_copy_loopinfo_to_se (&arrayse, &loop);
3308
      arrayse.ss = arrayss;
3309
      gfc_conv_expr_val (&arrayse, arrayexpr);
3310
      gfc_add_block_to_block (&block, &arrayse.pre);
3311
 
3312
      /* We do the following if this is a more extreme value.  */
3313
      gfc_start_block (&ifblock);
3314
 
3315
      /* Assign the value to the limit...  */
3316
      gfc_add_modify (&ifblock, limit, arrayse.expr);
3317
 
3318
      tmp = fold_build2_loc (input_location, PLUS_EXPR, TREE_TYPE (pos),
3319
                             loop.loopvar[0], offset);
3320
      gfc_add_modify (&ifblock, pos, tmp);
3321
 
3322
      ifbody = gfc_finish_block (&ifblock);
3323
 
3324
      cond = fold_build2_loc (input_location, op, boolean_type_node,
3325
                              arrayse.expr, limit);
3326
 
3327
      tmp = build3_v (COND_EXPR, cond, ifbody,
3328
                      build_empty_stmt (input_location));
3329
      gfc_add_expr_to_block (&block, tmp);
3330
 
3331
      if (maskss)
3332
        {
3333
          /* We enclose the above in if (mask) {...}.  */
3334
          tmp = gfc_finish_block (&block);
3335
 
3336
          tmp = build3_v (COND_EXPR, maskse.expr, tmp,
3337
                          build_empty_stmt (input_location));
3338
        }
3339
      else
3340
        tmp = gfc_finish_block (&block);
3341
      gfc_add_expr_to_block (&body, tmp);
3342
      /* Avoid initializing loopvar[0] again, it should be left where
3343
         it finished by the first loop.  */
3344
      loop.from[0] = loop.loopvar[0];
3345
    }
3346
 
3347
  gfc_trans_scalarizing_loops (&loop, &body);
3348
 
3349
  if (lab2)
3350
    gfc_add_expr_to_block (&loop.pre, build1_v (LABEL_EXPR, lab2));
3351
 
3352
  /* For a scalar mask, enclose the loop in an if statement.  */
3353
  if (maskexpr && maskss == NULL)
3354
    {
3355
      gfc_init_se (&maskse, NULL);
3356
      gfc_conv_expr_val (&maskse, maskexpr);
3357
      gfc_init_block (&block);
3358
      gfc_add_block_to_block (&block, &loop.pre);
3359
      gfc_add_block_to_block (&block, &loop.post);
3360
      tmp = gfc_finish_block (&block);
3361
 
3362
      /* For the else part of the scalar mask, just initialize
3363
         the pos variable the same way as above.  */
3364
 
3365
      gfc_init_block (&elseblock);
3366
      gfc_add_modify (&elseblock, pos, gfc_index_zero_node);
3367
      elsetmp = gfc_finish_block (&elseblock);
3368
 
3369
      tmp = build3_v (COND_EXPR, maskse.expr, tmp, elsetmp);
3370
      gfc_add_expr_to_block (&block, tmp);
3371
      gfc_add_block_to_block (&se->pre, &block);
3372
    }
3373
  else
3374
    {
3375
      gfc_add_block_to_block (&se->pre, &loop.pre);
3376
      gfc_add_block_to_block (&se->pre, &loop.post);
3377
    }
3378
  gfc_cleanup_loop (&loop);
3379
 
3380
  se->expr = convert (type, pos);
3381
}
3382
 
3383
/* Emit code for minval or maxval intrinsic.  There are many different cases
3384
   we need to handle.  For performance reasons we sometimes create two
3385
   loops instead of one, where the second one is much simpler.
3386
   Examples for minval intrinsic:
3387
   1) Result is an array, a call is generated
3388
   2) Array mask is used and NaNs need to be supported, rank 1:
3389
      limit = Infinity;
3390
      nonempty = false;
3391
      S = from;
3392
      while (S <= to) {
3393
        if (mask[S]) { nonempty = true; if (a[S] <= limit) goto lab; }
3394
        S++;
3395
      }
3396
      limit = nonempty ? NaN : huge (limit);
3397
      lab:
3398
      while (S <= to) { if(mask[S]) limit = min (a[S], limit); S++; }
3399
   3) NaNs need to be supported, but it is known at compile time or cheaply
3400
      at runtime whether array is nonempty or not, rank 1:
3401
      limit = Infinity;
3402
      S = from;
3403
      while (S <= to) { if (a[S] <= limit) goto lab; S++; }
3404
      limit = (from <= to) ? NaN : huge (limit);
3405
      lab:
3406
      while (S <= to) { limit = min (a[S], limit); S++; }
3407
   4) Array mask is used and NaNs need to be supported, rank > 1:
3408
      limit = Infinity;
3409
      nonempty = false;
3410
      fast = false;
3411
      S1 = from1;
3412
      while (S1 <= to1) {
3413
        S2 = from2;
3414
        while (S2 <= to2) {
3415
          if (mask[S1][S2]) {
3416
            if (fast) limit = min (a[S1][S2], limit);
3417
            else {
3418
              nonempty = true;
3419
              if (a[S1][S2] <= limit) {
3420
                limit = a[S1][S2];
3421
                fast = true;
3422
              }
3423
            }
3424
          }
3425
          S2++;
3426
        }
3427
        S1++;
3428
      }
3429
      if (!fast)
3430
        limit = nonempty ? NaN : huge (limit);
3431
   5) NaNs need to be supported, but it is known at compile time or cheaply
3432
      at runtime whether array is nonempty or not, rank > 1:
3433
      limit = Infinity;
3434
      fast = false;
3435
      S1 = from1;
3436
      while (S1 <= to1) {
3437
        S2 = from2;
3438
        while (S2 <= to2) {
3439
          if (fast) limit = min (a[S1][S2], limit);
3440
          else {
3441
            if (a[S1][S2] <= limit) {
3442
              limit = a[S1][S2];
3443
              fast = true;
3444
            }
3445
          }
3446
          S2++;
3447
        }
3448
        S1++;
3449
      }
3450
      if (!fast)
3451
        limit = (nonempty_array) ? NaN : huge (limit);
3452
   6) NaNs aren't supported, but infinities are.  Array mask is used:
3453
      limit = Infinity;
3454
      nonempty = false;
3455
      S = from;
3456
      while (S <= to) {
3457
        if (mask[S]) { nonempty = true; limit = min (a[S], limit); }
3458
        S++;
3459
      }
3460
      limit = nonempty ? limit : huge (limit);
3461
   7) Same without array mask:
3462
      limit = Infinity;
3463
      S = from;
3464
      while (S <= to) { limit = min (a[S], limit); S++; }
3465
      limit = (from <= to) ? limit : huge (limit);
3466
   8) Neither NaNs nor infinities are supported (-ffast-math or BT_INTEGER):
3467
      limit = huge (limit);
3468
      S = from;
3469
      while (S <= to) { limit = min (a[S], limit); S++); }
3470
      (or
3471
      while (S <= to) { if (mask[S]) limit = min (a[S], limit); S++; }
3472
      with array mask instead).
3473
   For 3), 5), 7) and 8), if mask is scalar, this all goes into a conditional,
3474
   setting limit = huge (limit); in the else branch.  */
3475
 
3476
static void
3477
gfc_conv_intrinsic_minmaxval (gfc_se * se, gfc_expr * expr, enum tree_code op)
3478
{
3479
  tree limit;
3480
  tree type;
3481
  tree tmp;
3482
  tree ifbody;
3483
  tree nonempty;
3484
  tree nonempty_var;
3485
  tree lab;
3486
  tree fast;
3487
  tree huge_cst = NULL, nan_cst = NULL;
3488
  stmtblock_t body;
3489
  stmtblock_t block, block2;
3490
  gfc_loopinfo loop;
3491
  gfc_actual_arglist *actual;
3492
  gfc_ss *arrayss;
3493
  gfc_ss *maskss;
3494
  gfc_se arrayse;
3495
  gfc_se maskse;
3496
  gfc_expr *arrayexpr;
3497
  gfc_expr *maskexpr;
3498
  int n;
3499
 
3500
  if (se->ss)
3501
    {
3502
      gfc_conv_intrinsic_funcall (se, expr);
3503
      return;
3504
    }
3505
 
3506
  type = gfc_typenode_for_spec (&expr->ts);
3507
  /* Initialize the result.  */
3508
  limit = gfc_create_var (type, "limit");
3509
  n = gfc_validate_kind (expr->ts.type, expr->ts.kind, false);
3510
  switch (expr->ts.type)
3511
    {
3512
    case BT_REAL:
3513
      huge_cst = gfc_conv_mpfr_to_tree (gfc_real_kinds[n].huge,
3514
                                        expr->ts.kind, 0);
3515
      if (HONOR_INFINITIES (DECL_MODE (limit)))
3516
        {
3517
          REAL_VALUE_TYPE real;
3518
          real_inf (&real);
3519
          tmp = build_real (type, real);
3520
        }
3521
      else
3522
        tmp = huge_cst;
3523
      if (HONOR_NANS (DECL_MODE (limit)))
3524
        {
3525
          REAL_VALUE_TYPE real;
3526
          real_nan (&real, "", 1, DECL_MODE (limit));
3527
          nan_cst = build_real (type, real);
3528
        }
3529
      break;
3530
 
3531
    case BT_INTEGER:
3532
      tmp = gfc_conv_mpz_to_tree (gfc_integer_kinds[n].huge, expr->ts.kind);
3533
      break;
3534
 
3535
    default:
3536
      gcc_unreachable ();
3537
    }
3538
 
3539
  /* We start with the most negative possible value for MAXVAL, and the most
3540
     positive possible value for MINVAL. The most negative possible value is
3541
     -HUGE for BT_REAL and (-HUGE - 1) for BT_INTEGER; the most positive
3542
     possible value is HUGE in both cases.  */
3543
  if (op == GT_EXPR)
3544
    {
3545
      tmp = fold_build1_loc (input_location, NEGATE_EXPR, TREE_TYPE (tmp), tmp);
3546
      if (huge_cst)
3547
        huge_cst = fold_build1_loc (input_location, NEGATE_EXPR,
3548
                                    TREE_TYPE (huge_cst), huge_cst);
3549
    }
3550
 
3551
  if (op == GT_EXPR && expr->ts.type == BT_INTEGER)
3552
    tmp = fold_build2_loc (input_location, MINUS_EXPR, TREE_TYPE (tmp),
3553
                           tmp, build_int_cst (type, 1));
3554
 
3555
  gfc_add_modify (&se->pre, limit, tmp);
3556
 
3557
  /* Walk the arguments.  */
3558
  actual = expr->value.function.actual;
3559
  arrayexpr = actual->expr;
3560
  arrayss = gfc_walk_expr (arrayexpr);
3561
  gcc_assert (arrayss != gfc_ss_terminator);
3562
 
3563
  actual = actual->next->next;
3564
  gcc_assert (actual);
3565
  maskexpr = actual->expr;
3566
  nonempty = NULL;
3567
  if (maskexpr && maskexpr->rank != 0)
3568
    {
3569
      maskss = gfc_walk_expr (maskexpr);
3570
      gcc_assert (maskss != gfc_ss_terminator);
3571
    }
3572
  else
3573
    {
3574
      mpz_t asize;
3575
      if (gfc_array_size (arrayexpr, &asize) == SUCCESS)
3576
        {
3577
          nonempty = gfc_conv_mpz_to_tree (asize, gfc_index_integer_kind);
3578
          mpz_clear (asize);
3579
          nonempty = fold_build2_loc (input_location, GT_EXPR,
3580
                                      boolean_type_node, nonempty,
3581
                                      gfc_index_zero_node);
3582
        }
3583
      maskss = NULL;
3584
    }
3585
 
3586
  /* Initialize the scalarizer.  */
3587
  gfc_init_loopinfo (&loop);
3588
  gfc_add_ss_to_loop (&loop, arrayss);
3589
  if (maskss)
3590
    gfc_add_ss_to_loop (&loop, maskss);
3591
 
3592
  /* Initialize the loop.  */
3593
  gfc_conv_ss_startstride (&loop);
3594
 
3595
  /* The code generated can have more than one loop in sequence (see the
3596
     comment at the function header).  This doesn't work well with the
3597
     scalarizer, which changes arrays' offset when the scalarization loops
3598
     are generated (see gfc_trans_preloop_setup).  Fortunately, {min,max}val
3599
     are  currently inlined in the scalar case only.  As there is no dependency
3600
     to care about in that case, there is no temporary, so that we can use the
3601
     scalarizer temporary code to handle multiple loops.  Thus, we set temp_dim
3602
     here, we call gfc_mark_ss_chain_used with flag=3 later, and we use
3603
     gfc_trans_scalarized_loop_boundary even later to restore offset.
3604
     TODO: this prevents inlining of rank > 0 minmaxval calls, so this
3605
     should eventually go away.  We could either create two loops properly,
3606
     or find another way to save/restore the array offsets between the two
3607
     loops (without conflicting with temporary management), or use a single
3608
     loop minmaxval implementation.  See PR 31067.  */
3609
  loop.temp_dim = loop.dimen;
3610
  gfc_conv_loop_setup (&loop, &expr->where);
3611
 
3612
  if (nonempty == NULL && maskss == NULL
3613
      && loop.dimen == 1 && loop.from[0] && loop.to[0])
3614
    nonempty = fold_build2_loc (input_location, LE_EXPR, boolean_type_node,
3615
                                loop.from[0], loop.to[0]);
3616
  nonempty_var = NULL;
3617
  if (nonempty == NULL
3618
      && (HONOR_INFINITIES (DECL_MODE (limit))
3619
          || HONOR_NANS (DECL_MODE (limit))))
3620
    {
3621
      nonempty_var = gfc_create_var (boolean_type_node, "nonempty");
3622
      gfc_add_modify (&se->pre, nonempty_var, boolean_false_node);
3623
      nonempty = nonempty_var;
3624
    }
3625
  lab = NULL;
3626
  fast = NULL;
3627
  if (HONOR_NANS (DECL_MODE (limit)))
3628
    {
3629
      if (loop.dimen == 1)
3630
        {
3631
          lab = gfc_build_label_decl (NULL_TREE);
3632
          TREE_USED (lab) = 1;
3633
        }
3634
      else
3635
        {
3636
          fast = gfc_create_var (boolean_type_node, "fast");
3637
          gfc_add_modify (&se->pre, fast, boolean_false_node);
3638
        }
3639
    }
3640
 
3641
  gfc_mark_ss_chain_used (arrayss, lab ? 3 : 1);
3642
  if (maskss)
3643
    gfc_mark_ss_chain_used (maskss, lab ? 3 : 1);
3644
  /* Generate the loop body.  */
3645
  gfc_start_scalarized_body (&loop, &body);
3646
 
3647
  /* If we have a mask, only add this element if the mask is set.  */
3648
  if (maskss)
3649
    {
3650
      gfc_init_se (&maskse, NULL);
3651
      gfc_copy_loopinfo_to_se (&maskse, &loop);
3652
      maskse.ss = maskss;
3653
      gfc_conv_expr_val (&maskse, maskexpr);
3654
      gfc_add_block_to_block (&body, &maskse.pre);
3655
 
3656
      gfc_start_block (&block);
3657
    }
3658
  else
3659
    gfc_init_block (&block);
3660
 
3661
  /* Compare with the current limit.  */
3662
  gfc_init_se (&arrayse, NULL);
3663
  gfc_copy_loopinfo_to_se (&arrayse, &loop);
3664
  arrayse.ss = arrayss;
3665
  gfc_conv_expr_val (&arrayse, arrayexpr);
3666
  gfc_add_block_to_block (&block, &arrayse.pre);
3667
 
3668
  gfc_init_block (&block2);
3669
 
3670
  if (nonempty_var)
3671
    gfc_add_modify (&block2, nonempty_var, boolean_true_node);
3672
 
3673
  if (HONOR_NANS (DECL_MODE (limit)))
3674
    {
3675
      tmp = fold_build2_loc (input_location, op == GT_EXPR ? GE_EXPR : LE_EXPR,
3676
                             boolean_type_node, arrayse.expr, limit);
3677
      if (lab)
3678
        ifbody = build1_v (GOTO_EXPR, lab);
3679
      else
3680
        {
3681
          stmtblock_t ifblock;
3682
 
3683
          gfc_init_block (&ifblock);
3684
          gfc_add_modify (&ifblock, limit, arrayse.expr);
3685
          gfc_add_modify (&ifblock, fast, boolean_true_node);
3686
          ifbody = gfc_finish_block (&ifblock);
3687
        }
3688
      tmp = build3_v (COND_EXPR, tmp, ifbody,
3689
                      build_empty_stmt (input_location));
3690
      gfc_add_expr_to_block (&block2, tmp);
3691
    }
3692
  else
3693
    {
3694
      /* MIN_EXPR/MAX_EXPR has unspecified behavior with NaNs or
3695
         signed zeros.  */
3696
      if (HONOR_SIGNED_ZEROS (DECL_MODE (limit)))
3697
        {
3698
          tmp = fold_build2_loc (input_location, op, boolean_type_node,
3699
                                 arrayse.expr, limit);
3700
          ifbody = build2_v (MODIFY_EXPR, limit, arrayse.expr);
3701
          tmp = build3_v (COND_EXPR, tmp, ifbody,
3702
                          build_empty_stmt (input_location));
3703
          gfc_add_expr_to_block (&block2, tmp);
3704
        }
3705
      else
3706
        {
3707
          tmp = fold_build2_loc (input_location,
3708
                                 op == GT_EXPR ? MAX_EXPR : MIN_EXPR,
3709
                                 type, arrayse.expr, limit);
3710
          gfc_add_modify (&block2, limit, tmp);
3711
        }
3712
    }
3713
 
3714
  if (fast)
3715
    {
3716
      tree elsebody = gfc_finish_block (&block2);
3717
 
3718
      /* MIN_EXPR/MAX_EXPR has unspecified behavior with NaNs or
3719
         signed zeros.  */
3720
      if (HONOR_NANS (DECL_MODE (limit))
3721
          || HONOR_SIGNED_ZEROS (DECL_MODE (limit)))
3722
        {
3723
          tmp = fold_build2_loc (input_location, op, boolean_type_node,
3724
                                 arrayse.expr, limit);
3725
          ifbody = build2_v (MODIFY_EXPR, limit, arrayse.expr);
3726
          ifbody = build3_v (COND_EXPR, tmp, ifbody,
3727
                             build_empty_stmt (input_location));
3728
        }
3729
      else
3730
        {
3731
          tmp = fold_build2_loc (input_location,
3732
                                 op == GT_EXPR ? MAX_EXPR : MIN_EXPR,
3733
                                 type, arrayse.expr, limit);
3734
          ifbody = build2_v (MODIFY_EXPR, limit, tmp);
3735
        }
3736
      tmp = build3_v (COND_EXPR, fast, ifbody, elsebody);
3737
      gfc_add_expr_to_block (&block, tmp);
3738
    }
3739
  else
3740
    gfc_add_block_to_block (&block, &block2);
3741
 
3742
  gfc_add_block_to_block (&block, &arrayse.post);
3743
 
3744
  tmp = gfc_finish_block (&block);
3745
  if (maskss)
3746
    /* We enclose the above in if (mask) {...}.  */
3747
    tmp = build3_v (COND_EXPR, maskse.expr, tmp,
3748
                    build_empty_stmt (input_location));
3749
  gfc_add_expr_to_block (&body, tmp);
3750
 
3751
  if (lab)
3752
    {
3753
      gfc_trans_scalarized_loop_boundary (&loop, &body);
3754
 
3755
      tmp = fold_build3_loc (input_location, COND_EXPR, type, nonempty,
3756
                             nan_cst, huge_cst);
3757
      gfc_add_modify (&loop.code[0], limit, tmp);
3758
      gfc_add_expr_to_block (&loop.code[0], build1_v (LABEL_EXPR, lab));
3759
 
3760
      /* If we have a mask, only add this element if the mask is set.  */
3761
      if (maskss)
3762
        {
3763
          gfc_init_se (&maskse, NULL);
3764
          gfc_copy_loopinfo_to_se (&maskse, &loop);
3765
          maskse.ss = maskss;
3766
          gfc_conv_expr_val (&maskse, maskexpr);
3767
          gfc_add_block_to_block (&body, &maskse.pre);
3768
 
3769
          gfc_start_block (&block);
3770
        }
3771
      else
3772
        gfc_init_block (&block);
3773
 
3774
      /* Compare with the current limit.  */
3775
      gfc_init_se (&arrayse, NULL);
3776
      gfc_copy_loopinfo_to_se (&arrayse, &loop);
3777
      arrayse.ss = arrayss;
3778
      gfc_conv_expr_val (&arrayse, arrayexpr);
3779
      gfc_add_block_to_block (&block, &arrayse.pre);
3780
 
3781
      /* MIN_EXPR/MAX_EXPR has unspecified behavior with NaNs or
3782
         signed zeros.  */
3783
      if (HONOR_NANS (DECL_MODE (limit))
3784
          || HONOR_SIGNED_ZEROS (DECL_MODE (limit)))
3785
        {
3786
          tmp = fold_build2_loc (input_location, op, boolean_type_node,
3787
                                 arrayse.expr, limit);
3788
          ifbody = build2_v (MODIFY_EXPR, limit, arrayse.expr);
3789
          tmp = build3_v (COND_EXPR, tmp, ifbody,
3790
                          build_empty_stmt (input_location));
3791
          gfc_add_expr_to_block (&block, tmp);
3792
        }
3793
      else
3794
        {
3795
          tmp = fold_build2_loc (input_location,
3796
                                 op == GT_EXPR ? MAX_EXPR : MIN_EXPR,
3797
                                 type, arrayse.expr, limit);
3798
          gfc_add_modify (&block, limit, tmp);
3799
        }
3800
 
3801
      gfc_add_block_to_block (&block, &arrayse.post);
3802
 
3803
      tmp = gfc_finish_block (&block);
3804
      if (maskss)
3805
        /* We enclose the above in if (mask) {...}.  */
3806
        tmp = build3_v (COND_EXPR, maskse.expr, tmp,
3807
                        build_empty_stmt (input_location));
3808
      gfc_add_expr_to_block (&body, tmp);
3809
      /* Avoid initializing loopvar[0] again, it should be left where
3810
         it finished by the first loop.  */
3811
      loop.from[0] = loop.loopvar[0];
3812
    }
3813
  gfc_trans_scalarizing_loops (&loop, &body);
3814
 
3815
  if (fast)
3816
    {
3817
      tmp = fold_build3_loc (input_location, COND_EXPR, type, nonempty,
3818
                             nan_cst, huge_cst);
3819
      ifbody = build2_v (MODIFY_EXPR, limit, tmp);
3820
      tmp = build3_v (COND_EXPR, fast, build_empty_stmt (input_location),
3821
                      ifbody);
3822
      gfc_add_expr_to_block (&loop.pre, tmp);
3823
    }
3824
  else if (HONOR_INFINITIES (DECL_MODE (limit)) && !lab)
3825
    {
3826
      tmp = fold_build3_loc (input_location, COND_EXPR, type, nonempty, limit,
3827
                             huge_cst);
3828
      gfc_add_modify (&loop.pre, limit, tmp);
3829
    }
3830
 
3831
  /* For a scalar mask, enclose the loop in an if statement.  */
3832
  if (maskexpr && maskss == NULL)
3833
    {
3834
      tree else_stmt;
3835
 
3836
      gfc_init_se (&maskse, NULL);
3837
      gfc_conv_expr_val (&maskse, maskexpr);
3838
      gfc_init_block (&block);
3839
      gfc_add_block_to_block (&block, &loop.pre);
3840
      gfc_add_block_to_block (&block, &loop.post);
3841
      tmp = gfc_finish_block (&block);
3842
 
3843
      if (HONOR_INFINITIES (DECL_MODE (limit)))
3844
        else_stmt = build2_v (MODIFY_EXPR, limit, huge_cst);
3845
      else
3846
        else_stmt = build_empty_stmt (input_location);
3847
      tmp = build3_v (COND_EXPR, maskse.expr, tmp, else_stmt);
3848
      gfc_add_expr_to_block (&block, tmp);
3849
      gfc_add_block_to_block (&se->pre, &block);
3850
    }
3851
  else
3852
    {
3853
      gfc_add_block_to_block (&se->pre, &loop.pre);
3854
      gfc_add_block_to_block (&se->pre, &loop.post);
3855
    }
3856
 
3857
  gfc_cleanup_loop (&loop);
3858
 
3859
  se->expr = limit;
3860
}
3861
 
3862
/* BTEST (i, pos) = (i & (1 << pos)) != 0.  */
3863
static void
3864
gfc_conv_intrinsic_btest (gfc_se * se, gfc_expr * expr)
3865
{
3866
  tree args[2];
3867
  tree type;
3868
  tree tmp;
3869
 
3870
  gfc_conv_intrinsic_function_args (se, expr, args, 2);
3871
  type = TREE_TYPE (args[0]);
3872
 
3873
  tmp = fold_build2_loc (input_location, LSHIFT_EXPR, type,
3874
                         build_int_cst (type, 1), args[1]);
3875
  tmp = fold_build2_loc (input_location, BIT_AND_EXPR, type, args[0], tmp);
3876
  tmp = fold_build2_loc (input_location, NE_EXPR, boolean_type_node, tmp,
3877
                         build_int_cst (type, 0));
3878
  type = gfc_typenode_for_spec (&expr->ts);
3879
  se->expr = convert (type, tmp);
3880
}
3881
 
3882
 
3883
/* Generate code for BGE, BGT, BLE and BLT intrinsics.  */
3884
static void
3885
gfc_conv_intrinsic_bitcomp (gfc_se * se, gfc_expr * expr, enum tree_code op)
3886
{
3887
  tree args[2];
3888
 
3889
  gfc_conv_intrinsic_function_args (se, expr, args, 2);
3890
 
3891
  /* Convert both arguments to the unsigned type of the same size.  */
3892
  args[0] = fold_convert (unsigned_type_for (TREE_TYPE (args[0])), args[0]);
3893
  args[1] = fold_convert (unsigned_type_for (TREE_TYPE (args[1])), args[1]);
3894
 
3895
  /* If they have unequal type size, convert to the larger one.  */
3896
  if (TYPE_PRECISION (TREE_TYPE (args[0]))
3897
      > TYPE_PRECISION (TREE_TYPE (args[1])))
3898
    args[1] = fold_convert (TREE_TYPE (args[0]), args[1]);
3899
  else if (TYPE_PRECISION (TREE_TYPE (args[1]))
3900
           > TYPE_PRECISION (TREE_TYPE (args[0])))
3901
    args[0] = fold_convert (TREE_TYPE (args[1]), args[0]);
3902
 
3903
  /* Now, we compare them.  */
3904
  se->expr = fold_build2_loc (input_location, op, boolean_type_node,
3905
                              args[0], args[1]);
3906
}
3907
 
3908
 
3909
/* Generate code to perform the specified operation.  */
3910
static void
3911
gfc_conv_intrinsic_bitop (gfc_se * se, gfc_expr * expr, enum tree_code op)
3912
{
3913
  tree args[2];
3914
 
3915
  gfc_conv_intrinsic_function_args (se, expr, args, 2);
3916
  se->expr = fold_build2_loc (input_location, op, TREE_TYPE (args[0]),
3917
                              args[0], args[1]);
3918
}
3919
 
3920
/* Bitwise not.  */
3921
static void
3922
gfc_conv_intrinsic_not (gfc_se * se, gfc_expr * expr)
3923
{
3924
  tree arg;
3925
 
3926
  gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
3927
  se->expr = fold_build1_loc (input_location, BIT_NOT_EXPR,
3928
                              TREE_TYPE (arg), arg);
3929
}
3930
 
3931
/* Set or clear a single bit.  */
3932
static void
3933
gfc_conv_intrinsic_singlebitop (gfc_se * se, gfc_expr * expr, int set)
3934
{
3935
  tree args[2];
3936
  tree type;
3937
  tree tmp;
3938
  enum tree_code op;
3939
 
3940
  gfc_conv_intrinsic_function_args (se, expr, args, 2);
3941
  type = TREE_TYPE (args[0]);
3942
 
3943
  tmp = fold_build2_loc (input_location, LSHIFT_EXPR, type,
3944
                         build_int_cst (type, 1), args[1]);
3945
  if (set)
3946
    op = BIT_IOR_EXPR;
3947
  else
3948
    {
3949
      op = BIT_AND_EXPR;
3950
      tmp = fold_build1_loc (input_location, BIT_NOT_EXPR, type, tmp);
3951
    }
3952
  se->expr = fold_build2_loc (input_location, op, type, args[0], tmp);
3953
}
3954
 
3955
/* Extract a sequence of bits.
3956
    IBITS(I, POS, LEN) = (I >> POS) & ~((~0) << LEN).  */
3957
static void
3958
gfc_conv_intrinsic_ibits (gfc_se * se, gfc_expr * expr)
3959
{
3960
  tree args[3];
3961
  tree type;
3962
  tree tmp;
3963
  tree mask;
3964
 
3965
  gfc_conv_intrinsic_function_args (se, expr, args, 3);
3966
  type = TREE_TYPE (args[0]);
3967
 
3968
  mask = build_int_cst (type, -1);
3969
  mask = fold_build2_loc (input_location, LSHIFT_EXPR, type, mask, args[2]);
3970
  mask = fold_build1_loc (input_location, BIT_NOT_EXPR, type, mask);
3971
 
3972
  tmp = fold_build2_loc (input_location, RSHIFT_EXPR, type, args[0], args[1]);
3973
 
3974
  se->expr = fold_build2_loc (input_location, BIT_AND_EXPR, type, tmp, mask);
3975
}
3976
 
3977
static void
3978
gfc_conv_intrinsic_shift (gfc_se * se, gfc_expr * expr, bool right_shift,
3979
                          bool arithmetic)
3980
{
3981
  tree args[2], type, num_bits, cond;
3982
 
3983
  gfc_conv_intrinsic_function_args (se, expr, args, 2);
3984
 
3985
  args[0] = gfc_evaluate_now (args[0], &se->pre);
3986
  args[1] = gfc_evaluate_now (args[1], &se->pre);
3987
  type = TREE_TYPE (args[0]);
3988
 
3989
  if (!arithmetic)
3990
    args[0] = fold_convert (unsigned_type_for (type), args[0]);
3991
  else
3992
    gcc_assert (right_shift);
3993
 
3994
  se->expr = fold_build2_loc (input_location,
3995
                              right_shift ? RSHIFT_EXPR : LSHIFT_EXPR,
3996
                              TREE_TYPE (args[0]), args[0], args[1]);
3997
 
3998
  if (!arithmetic)
3999
    se->expr = fold_convert (type, se->expr);
4000
 
4001
  /* The Fortran standard allows shift widths <= BIT_SIZE(I), whereas
4002
     gcc requires a shift width < BIT_SIZE(I), so we have to catch this
4003
     special case.  */
4004
  num_bits = build_int_cst (TREE_TYPE (args[1]), TYPE_PRECISION (type));
4005
  cond = fold_build2_loc (input_location, GE_EXPR, boolean_type_node,
4006
                          args[1], num_bits);
4007
 
4008
  se->expr = fold_build3_loc (input_location, COND_EXPR, type, cond,
4009
                              build_int_cst (type, 0), se->expr);
4010
}
4011
 
4012
/* ISHFT (I, SHIFT) = (abs (shift) >= BIT_SIZE (i))
4013
                        ? 0
4014
                        : ((shift >= 0) ? i << shift : i >> -shift)
4015
   where all shifts are logical shifts.  */
4016
static void
4017
gfc_conv_intrinsic_ishft (gfc_se * se, gfc_expr * expr)
4018
{
4019
  tree args[2];
4020
  tree type;
4021
  tree utype;
4022
  tree tmp;
4023
  tree width;
4024
  tree num_bits;
4025
  tree cond;
4026
  tree lshift;
4027
  tree rshift;
4028
 
4029
  gfc_conv_intrinsic_function_args (se, expr, args, 2);
4030
 
4031
  args[0] = gfc_evaluate_now (args[0], &se->pre);
4032
  args[1] = gfc_evaluate_now (args[1], &se->pre);
4033
 
4034
  type = TREE_TYPE (args[0]);
4035
  utype = unsigned_type_for (type);
4036
 
4037
  width = fold_build1_loc (input_location, ABS_EXPR, TREE_TYPE (args[1]),
4038
                           args[1]);
4039
 
4040
  /* Left shift if positive.  */
4041
  lshift = fold_build2_loc (input_location, LSHIFT_EXPR, type, args[0], width);
4042
 
4043
  /* Right shift if negative.
4044
     We convert to an unsigned type because we want a logical shift.
4045
     The standard doesn't define the case of shifting negative
4046
     numbers, and we try to be compatible with other compilers, most
4047
     notably g77, here.  */
4048
  rshift = fold_convert (type, fold_build2_loc (input_location, RSHIFT_EXPR,
4049
                                    utype, convert (utype, args[0]), width));
4050
 
4051
  tmp = fold_build2_loc (input_location, GE_EXPR, boolean_type_node, args[1],
4052
                         build_int_cst (TREE_TYPE (args[1]), 0));
4053
  tmp = fold_build3_loc (input_location, COND_EXPR, type, tmp, lshift, rshift);
4054
 
4055
  /* The Fortran standard allows shift widths <= BIT_SIZE(I), whereas
4056
     gcc requires a shift width < BIT_SIZE(I), so we have to catch this
4057
     special case.  */
4058
  num_bits = build_int_cst (TREE_TYPE (args[1]), TYPE_PRECISION (type));
4059
  cond = fold_build2_loc (input_location, GE_EXPR, boolean_type_node, width,
4060
                          num_bits);
4061
  se->expr = fold_build3_loc (input_location, COND_EXPR, type, cond,
4062
                              build_int_cst (type, 0), tmp);
4063
}
4064
 
4065
 
4066
/* Circular shift.  AKA rotate or barrel shift.  */
4067
 
4068
static void
4069
gfc_conv_intrinsic_ishftc (gfc_se * se, gfc_expr * expr)
4070
{
4071
  tree *args;
4072
  tree type;
4073
  tree tmp;
4074
  tree lrot;
4075
  tree rrot;
4076
  tree zero;
4077
  unsigned int num_args;
4078
 
4079
  num_args = gfc_intrinsic_argument_list_length (expr);
4080
  args = XALLOCAVEC (tree, num_args);
4081
 
4082
  gfc_conv_intrinsic_function_args (se, expr, args, num_args);
4083
 
4084
  if (num_args == 3)
4085
    {
4086
      /* Use a library function for the 3 parameter version.  */
4087
      tree int4type = gfc_get_int_type (4);
4088
 
4089
      type = TREE_TYPE (args[0]);
4090
      /* We convert the first argument to at least 4 bytes, and
4091
         convert back afterwards.  This removes the need for library
4092
         functions for all argument sizes, and function will be
4093
         aligned to at least 32 bits, so there's no loss.  */
4094
      if (expr->ts.kind < 4)
4095
        args[0] = convert (int4type, args[0]);
4096
 
4097
      /* Convert the SHIFT and SIZE args to INTEGER*4 otherwise we would
4098
         need loads of library  functions.  They cannot have values >
4099
         BIT_SIZE (I) so the conversion is safe.  */
4100
      args[1] = convert (int4type, args[1]);
4101
      args[2] = convert (int4type, args[2]);
4102
 
4103
      switch (expr->ts.kind)
4104
        {
4105
        case 1:
4106
        case 2:
4107
        case 4:
4108
          tmp = gfor_fndecl_math_ishftc4;
4109
          break;
4110
        case 8:
4111
          tmp = gfor_fndecl_math_ishftc8;
4112
          break;
4113
        case 16:
4114
          tmp = gfor_fndecl_math_ishftc16;
4115
          break;
4116
        default:
4117
          gcc_unreachable ();
4118
        }
4119
      se->expr = build_call_expr_loc (input_location,
4120
                                      tmp, 3, args[0], args[1], args[2]);
4121
      /* Convert the result back to the original type, if we extended
4122
         the first argument's width above.  */
4123
      if (expr->ts.kind < 4)
4124
        se->expr = convert (type, se->expr);
4125
 
4126
      return;
4127
    }
4128
  type = TREE_TYPE (args[0]);
4129
 
4130
  /* Evaluate arguments only once.  */
4131
  args[0] = gfc_evaluate_now (args[0], &se->pre);
4132
  args[1] = gfc_evaluate_now (args[1], &se->pre);
4133
 
4134
  /* Rotate left if positive.  */
4135
  lrot = fold_build2_loc (input_location, LROTATE_EXPR, type, args[0], args[1]);
4136
 
4137
  /* Rotate right if negative.  */
4138
  tmp = fold_build1_loc (input_location, NEGATE_EXPR, TREE_TYPE (args[1]),
4139
                         args[1]);
4140
  rrot = fold_build2_loc (input_location,RROTATE_EXPR, type, args[0], tmp);
4141
 
4142
  zero = build_int_cst (TREE_TYPE (args[1]), 0);
4143
  tmp = fold_build2_loc (input_location, GT_EXPR, boolean_type_node, args[1],
4144
                         zero);
4145
  rrot = fold_build3_loc (input_location, COND_EXPR, type, tmp, lrot, rrot);
4146
 
4147
  /* Do nothing if shift == 0.  */
4148
  tmp = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node, args[1],
4149
                         zero);
4150
  se->expr = fold_build3_loc (input_location, COND_EXPR, type, tmp, args[0],
4151
                              rrot);
4152
}
4153
 
4154
 
4155
/* LEADZ (i) = (i == 0) ? BIT_SIZE (i)
4156
                        : __builtin_clz(i) - (BIT_SIZE('int') - BIT_SIZE(i))
4157
 
4158
   The conditional expression is necessary because the result of LEADZ(0)
4159
   is defined, but the result of __builtin_clz(0) is undefined for most
4160
   targets.
4161
 
4162
   For INTEGER kinds smaller than the C 'int' type, we have to subtract the
4163
   difference in bit size between the argument of LEADZ and the C int.  */
4164
 
4165
static void
4166
gfc_conv_intrinsic_leadz (gfc_se * se, gfc_expr * expr)
4167
{
4168
  tree arg;
4169
  tree arg_type;
4170
  tree cond;
4171
  tree result_type;
4172
  tree leadz;
4173
  tree bit_size;
4174
  tree tmp;
4175
  tree func;
4176
  int s, argsize;
4177
 
4178
  gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
4179
  argsize = TYPE_PRECISION (TREE_TYPE (arg));
4180
 
4181
  /* Which variant of __builtin_clz* should we call?  */
4182
  if (argsize <= INT_TYPE_SIZE)
4183
    {
4184
      arg_type = unsigned_type_node;
4185
      func = builtin_decl_explicit (BUILT_IN_CLZ);
4186
    }
4187
  else if (argsize <= LONG_TYPE_SIZE)
4188
    {
4189
      arg_type = long_unsigned_type_node;
4190
      func = builtin_decl_explicit (BUILT_IN_CLZL);
4191
    }
4192
  else if (argsize <= LONG_LONG_TYPE_SIZE)
4193
    {
4194
      arg_type = long_long_unsigned_type_node;
4195
      func = builtin_decl_explicit (BUILT_IN_CLZLL);
4196
    }
4197
  else
4198
    {
4199
      gcc_assert (argsize == 2 * LONG_LONG_TYPE_SIZE);
4200
      arg_type = gfc_build_uint_type (argsize);
4201
      func = NULL_TREE;
4202
    }
4203
 
4204
  /* Convert the actual argument twice: first, to the unsigned type of the
4205
     same size; then, to the proper argument type for the built-in
4206
     function.  But the return type is of the default INTEGER kind.  */
4207
  arg = fold_convert (gfc_build_uint_type (argsize), arg);
4208
  arg = fold_convert (arg_type, arg);
4209
  arg = gfc_evaluate_now (arg, &se->pre);
4210
  result_type = gfc_get_int_type (gfc_default_integer_kind);
4211
 
4212
  /* Compute LEADZ for the case i .ne. 0.  */
4213
  if (func)
4214
    {
4215
      s = TYPE_PRECISION (arg_type) - argsize;
4216
      tmp = fold_convert (result_type,
4217
                          build_call_expr_loc (input_location, func,
4218
                                               1, arg));
4219
      leadz = fold_build2_loc (input_location, MINUS_EXPR, result_type,
4220
                               tmp, build_int_cst (result_type, s));
4221
    }
4222
  else
4223
    {
4224
      /* We end up here if the argument type is larger than 'long long'.
4225
         We generate this code:
4226
 
4227
            if (x & (ULL_MAX << ULL_SIZE) != 0)
4228
              return clzll ((unsigned long long) (x >> ULLSIZE));
4229
            else
4230
              return ULL_SIZE + clzll ((unsigned long long) x);
4231
         where ULL_MAX is the largest value that a ULL_MAX can hold
4232
         (0xFFFFFFFFFFFFFFFF for a 64-bit long long type), and ULLSIZE
4233
         is the bit-size of the long long type (64 in this example).  */
4234
      tree ullsize, ullmax, tmp1, tmp2, btmp;
4235
 
4236
      ullsize = build_int_cst (result_type, LONG_LONG_TYPE_SIZE);
4237
      ullmax = fold_build1_loc (input_location, BIT_NOT_EXPR,
4238
                                long_long_unsigned_type_node,
4239
                                build_int_cst (long_long_unsigned_type_node,
4240
                                               0));
4241
 
4242
      cond = fold_build2_loc (input_location, LSHIFT_EXPR, arg_type,
4243
                              fold_convert (arg_type, ullmax), ullsize);
4244
      cond = fold_build2_loc (input_location, BIT_AND_EXPR, arg_type,
4245
                              arg, cond);
4246
      cond = fold_build2_loc (input_location, NE_EXPR, boolean_type_node,
4247
                              cond, build_int_cst (arg_type, 0));
4248
 
4249
      tmp1 = fold_build2_loc (input_location, RSHIFT_EXPR, arg_type,
4250
                              arg, ullsize);
4251
      tmp1 = fold_convert (long_long_unsigned_type_node, tmp1);
4252
      btmp = builtin_decl_explicit (BUILT_IN_CLZLL);
4253
      tmp1 = fold_convert (result_type,
4254
                           build_call_expr_loc (input_location, btmp, 1, tmp1));
4255
 
4256
      tmp2 = fold_convert (long_long_unsigned_type_node, arg);
4257
      btmp = builtin_decl_explicit (BUILT_IN_CLZLL);
4258
      tmp2 = fold_convert (result_type,
4259
                           build_call_expr_loc (input_location, btmp, 1, tmp2));
4260
      tmp2 = fold_build2_loc (input_location, PLUS_EXPR, result_type,
4261
                              tmp2, ullsize);
4262
 
4263
      leadz = fold_build3_loc (input_location, COND_EXPR, result_type,
4264
                               cond, tmp1, tmp2);
4265
    }
4266
 
4267
  /* Build BIT_SIZE.  */
4268
  bit_size = build_int_cst (result_type, argsize);
4269
 
4270
  cond = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node,
4271
                          arg, build_int_cst (arg_type, 0));
4272
  se->expr = fold_build3_loc (input_location, COND_EXPR, result_type, cond,
4273
                              bit_size, leadz);
4274
}
4275
 
4276
 
4277
/* TRAILZ(i) = (i == 0) ? BIT_SIZE (i) : __builtin_ctz(i)
4278
 
4279
   The conditional expression is necessary because the result of TRAILZ(0)
4280
   is defined, but the result of __builtin_ctz(0) is undefined for most
4281
   targets.  */
4282
 
4283
static void
4284
gfc_conv_intrinsic_trailz (gfc_se * se, gfc_expr *expr)
4285
{
4286
  tree arg;
4287
  tree arg_type;
4288
  tree cond;
4289
  tree result_type;
4290
  tree trailz;
4291
  tree bit_size;
4292
  tree func;
4293
  int argsize;
4294
 
4295
  gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
4296
  argsize = TYPE_PRECISION (TREE_TYPE (arg));
4297
 
4298
  /* Which variant of __builtin_ctz* should we call?  */
4299
  if (argsize <= INT_TYPE_SIZE)
4300
    {
4301
      arg_type = unsigned_type_node;
4302
      func = builtin_decl_explicit (BUILT_IN_CTZ);
4303
    }
4304
  else if (argsize <= LONG_TYPE_SIZE)
4305
    {
4306
      arg_type = long_unsigned_type_node;
4307
      func = builtin_decl_explicit (BUILT_IN_CTZL);
4308
    }
4309
  else if (argsize <= LONG_LONG_TYPE_SIZE)
4310
    {
4311
      arg_type = long_long_unsigned_type_node;
4312
      func = builtin_decl_explicit (BUILT_IN_CTZLL);
4313
    }
4314
  else
4315
    {
4316
      gcc_assert (argsize == 2 * LONG_LONG_TYPE_SIZE);
4317
      arg_type = gfc_build_uint_type (argsize);
4318
      func = NULL_TREE;
4319
    }
4320
 
4321
  /* Convert the actual argument twice: first, to the unsigned type of the
4322
     same size; then, to the proper argument type for the built-in
4323
     function.  But the return type is of the default INTEGER kind.  */
4324
  arg = fold_convert (gfc_build_uint_type (argsize), arg);
4325
  arg = fold_convert (arg_type, arg);
4326
  arg = gfc_evaluate_now (arg, &se->pre);
4327
  result_type = gfc_get_int_type (gfc_default_integer_kind);
4328
 
4329
  /* Compute TRAILZ for the case i .ne. 0.  */
4330
  if (func)
4331
    trailz = fold_convert (result_type, build_call_expr_loc (input_location,
4332
                                                             func, 1, arg));
4333
  else
4334
    {
4335
      /* We end up here if the argument type is larger than 'long long'.
4336
         We generate this code:
4337
 
4338
            if ((x & ULL_MAX) == 0)
4339
              return ULL_SIZE + ctzll ((unsigned long long) (x >> ULLSIZE));
4340
            else
4341
              return ctzll ((unsigned long long) x);
4342
 
4343
         where ULL_MAX is the largest value that a ULL_MAX can hold
4344
         (0xFFFFFFFFFFFFFFFF for a 64-bit long long type), and ULLSIZE
4345
         is the bit-size of the long long type (64 in this example).  */
4346
      tree ullsize, ullmax, tmp1, tmp2, btmp;
4347
 
4348
      ullsize = build_int_cst (result_type, LONG_LONG_TYPE_SIZE);
4349
      ullmax = fold_build1_loc (input_location, BIT_NOT_EXPR,
4350
                                long_long_unsigned_type_node,
4351
                                build_int_cst (long_long_unsigned_type_node, 0));
4352
 
4353
      cond = fold_build2_loc (input_location, BIT_AND_EXPR, arg_type, arg,
4354
                              fold_convert (arg_type, ullmax));
4355
      cond = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node, cond,
4356
                              build_int_cst (arg_type, 0));
4357
 
4358
      tmp1 = fold_build2_loc (input_location, RSHIFT_EXPR, arg_type,
4359
                              arg, ullsize);
4360
      tmp1 = fold_convert (long_long_unsigned_type_node, tmp1);
4361
      btmp = builtin_decl_explicit (BUILT_IN_CTZLL);
4362
      tmp1 = fold_convert (result_type,
4363
                           build_call_expr_loc (input_location, btmp, 1, tmp1));
4364
      tmp1 = fold_build2_loc (input_location, PLUS_EXPR, result_type,
4365
                              tmp1, ullsize);
4366
 
4367
      tmp2 = fold_convert (long_long_unsigned_type_node, arg);
4368
      btmp = builtin_decl_explicit (BUILT_IN_CTZLL);
4369
      tmp2 = fold_convert (result_type,
4370
                           build_call_expr_loc (input_location, btmp, 1, tmp2));
4371
 
4372
      trailz = fold_build3_loc (input_location, COND_EXPR, result_type,
4373
                                cond, tmp1, tmp2);
4374
    }
4375
 
4376
  /* Build BIT_SIZE.  */
4377
  bit_size = build_int_cst (result_type, argsize);
4378
 
4379
  cond = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node,
4380
                          arg, build_int_cst (arg_type, 0));
4381
  se->expr = fold_build3_loc (input_location, COND_EXPR, result_type, cond,
4382
                              bit_size, trailz);
4383
}
4384
 
4385
/* Using __builtin_popcount for POPCNT and __builtin_parity for POPPAR;
4386
   for types larger than "long long", we call the long long built-in for
4387
   the lower and higher bits and combine the result.  */
4388
 
4389
static void
4390
gfc_conv_intrinsic_popcnt_poppar (gfc_se * se, gfc_expr *expr, int parity)
4391
{
4392
  tree arg;
4393
  tree arg_type;
4394
  tree result_type;
4395
  tree func;
4396
  int argsize;
4397
 
4398
  gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
4399
  argsize = TYPE_PRECISION (TREE_TYPE (arg));
4400
  result_type = gfc_get_int_type (gfc_default_integer_kind);
4401
 
4402
  /* Which variant of the builtin should we call?  */
4403
  if (argsize <= INT_TYPE_SIZE)
4404
    {
4405
      arg_type = unsigned_type_node;
4406
      func = builtin_decl_explicit (parity
4407
                                    ? BUILT_IN_PARITY
4408
                                    : BUILT_IN_POPCOUNT);
4409
    }
4410
  else if (argsize <= LONG_TYPE_SIZE)
4411
    {
4412
      arg_type = long_unsigned_type_node;
4413
      func = builtin_decl_explicit (parity
4414
                                    ? BUILT_IN_PARITYL
4415
                                    : BUILT_IN_POPCOUNTL);
4416
    }
4417
  else if (argsize <= LONG_LONG_TYPE_SIZE)
4418
    {
4419
      arg_type = long_long_unsigned_type_node;
4420
      func = builtin_decl_explicit (parity
4421
                                    ? BUILT_IN_PARITYLL
4422
                                    : BUILT_IN_POPCOUNTLL);
4423
    }
4424
  else
4425
    {
4426
      /* Our argument type is larger than 'long long', which mean none
4427
         of the POPCOUNT builtins covers it.  We thus call the 'long long'
4428
         variant multiple times, and add the results.  */
4429
      tree utype, arg2, call1, call2;
4430
 
4431
      /* For now, we only cover the case where argsize is twice as large
4432
         as 'long long'.  */
4433
      gcc_assert (argsize == 2 * LONG_LONG_TYPE_SIZE);
4434
 
4435
      func = builtin_decl_explicit (parity
4436
                                    ? BUILT_IN_PARITYLL
4437
                                    : BUILT_IN_POPCOUNTLL);
4438
 
4439
      /* Convert it to an integer, and store into a variable.  */
4440
      utype = gfc_build_uint_type (argsize);
4441
      arg = fold_convert (utype, arg);
4442
      arg = gfc_evaluate_now (arg, &se->pre);
4443
 
4444
      /* Call the builtin twice.  */
4445
      call1 = build_call_expr_loc (input_location, func, 1,
4446
                                   fold_convert (long_long_unsigned_type_node,
4447
                                                 arg));
4448
 
4449
      arg2 = fold_build2_loc (input_location, RSHIFT_EXPR, utype, arg,
4450
                              build_int_cst (utype, LONG_LONG_TYPE_SIZE));
4451
      call2 = build_call_expr_loc (input_location, func, 1,
4452
                                   fold_convert (long_long_unsigned_type_node,
4453
                                                 arg2));
4454
 
4455
      /* Combine the results.  */
4456
      if (parity)
4457
        se->expr = fold_build2_loc (input_location, BIT_XOR_EXPR, result_type,
4458
                                    call1, call2);
4459
      else
4460
        se->expr = fold_build2_loc (input_location, PLUS_EXPR, result_type,
4461
                                    call1, call2);
4462
 
4463
      return;
4464
    }
4465
 
4466
  /* Convert the actual argument twice: first, to the unsigned type of the
4467
     same size; then, to the proper argument type for the built-in
4468
     function.  */
4469
  arg = fold_convert (gfc_build_uint_type (argsize), arg);
4470
  arg = fold_convert (arg_type, arg);
4471
 
4472
  se->expr = fold_convert (result_type,
4473
                           build_call_expr_loc (input_location, func, 1, arg));
4474
}
4475
 
4476
 
4477
/* Process an intrinsic with unspecified argument-types that has an optional
4478
   argument (which could be of type character), e.g. EOSHIFT.  For those, we
4479
   need to append the string length of the optional argument if it is not
4480
   present and the type is really character.
4481
   primary specifies the position (starting at 1) of the non-optional argument
4482
   specifying the type and optional gives the position of the optional
4483
   argument in the arglist.  */
4484
 
4485
static void
4486
conv_generic_with_optional_char_arg (gfc_se* se, gfc_expr* expr,
4487
                                     unsigned primary, unsigned optional)
4488
{
4489
  gfc_actual_arglist* prim_arg;
4490
  gfc_actual_arglist* opt_arg;
4491
  unsigned cur_pos;
4492
  gfc_actual_arglist* arg;
4493
  gfc_symbol* sym;
4494
  VEC(tree,gc) *append_args;
4495
 
4496
  /* Find the two arguments given as position.  */
4497
  cur_pos = 0;
4498
  prim_arg = NULL;
4499
  opt_arg = NULL;
4500
  for (arg = expr->value.function.actual; arg; arg = arg->next)
4501
    {
4502
      ++cur_pos;
4503
 
4504
      if (cur_pos == primary)
4505
        prim_arg = arg;
4506
      if (cur_pos == optional)
4507
        opt_arg = arg;
4508
 
4509
      if (cur_pos >= primary && cur_pos >= optional)
4510
        break;
4511
    }
4512
  gcc_assert (prim_arg);
4513
  gcc_assert (prim_arg->expr);
4514
  gcc_assert (opt_arg);
4515
 
4516
  /* If we do have type CHARACTER and the optional argument is really absent,
4517
     append a dummy 0 as string length.  */
4518
  append_args = NULL;
4519
  if (prim_arg->expr->ts.type == BT_CHARACTER && !opt_arg->expr)
4520
    {
4521
      tree dummy;
4522
 
4523
      dummy = build_int_cst (gfc_charlen_type_node, 0);
4524
      append_args = VEC_alloc (tree, gc, 1);
4525
      VEC_quick_push (tree, append_args, dummy);
4526
    }
4527
 
4528
  /* Build the call itself.  */
4529
  sym = gfc_get_symbol_for_expr (expr);
4530
  gfc_conv_procedure_call (se, sym, expr->value.function.actual, expr,
4531
                          append_args);
4532
  free (sym);
4533
}
4534
 
4535
 
4536
/* The length of a character string.  */
4537
static void
4538
gfc_conv_intrinsic_len (gfc_se * se, gfc_expr * expr)
4539
{
4540
  tree len;
4541
  tree type;
4542
  tree decl;
4543
  gfc_symbol *sym;
4544
  gfc_se argse;
4545
  gfc_expr *arg;
4546
  gfc_ss *ss;
4547
 
4548
  gcc_assert (!se->ss);
4549
 
4550
  arg = expr->value.function.actual->expr;
4551
 
4552
  type = gfc_typenode_for_spec (&expr->ts);
4553
  switch (arg->expr_type)
4554
    {
4555
    case EXPR_CONSTANT:
4556
      len = build_int_cst (gfc_charlen_type_node, arg->value.character.length);
4557
      break;
4558
 
4559
    case EXPR_ARRAY:
4560
      /* Obtain the string length from the function used by
4561
         trans-array.c(gfc_trans_array_constructor).  */
4562
      len = NULL_TREE;
4563
      get_array_ctor_strlen (&se->pre, arg->value.constructor, &len);
4564
      break;
4565
 
4566
    case EXPR_VARIABLE:
4567
      if (arg->ref == NULL
4568
            || (arg->ref->next == NULL && arg->ref->type == REF_ARRAY))
4569
        {
4570
          /* This doesn't catch all cases.
4571
             See http://gcc.gnu.org/ml/fortran/2004-06/msg00165.html
4572
             and the surrounding thread.  */
4573
          sym = arg->symtree->n.sym;
4574
          decl = gfc_get_symbol_decl (sym);
4575
          if (decl == current_function_decl && sym->attr.function
4576
                && (sym->result == sym))
4577
            decl = gfc_get_fake_result_decl (sym, 0);
4578
 
4579
          len = sym->ts.u.cl->backend_decl;
4580
          gcc_assert (len);
4581
          break;
4582
        }
4583
 
4584
      /* Otherwise fall through.  */
4585
 
4586
    default:
4587
      /* Anybody stupid enough to do this deserves inefficient code.  */
4588
      ss = gfc_walk_expr (arg);
4589
      gfc_init_se (&argse, se);
4590
      if (ss == gfc_ss_terminator)
4591
        gfc_conv_expr (&argse, arg);
4592
      else
4593
        gfc_conv_expr_descriptor (&argse, arg, ss);
4594
      gfc_add_block_to_block (&se->pre, &argse.pre);
4595
      gfc_add_block_to_block (&se->post, &argse.post);
4596
      len = argse.string_length;
4597
      break;
4598
    }
4599
  se->expr = convert (type, len);
4600
}
4601
 
4602
/* The length of a character string not including trailing blanks.  */
4603
static void
4604
gfc_conv_intrinsic_len_trim (gfc_se * se, gfc_expr * expr)
4605
{
4606
  int kind = expr->value.function.actual->expr->ts.kind;
4607
  tree args[2], type, fndecl;
4608
 
4609
  gfc_conv_intrinsic_function_args (se, expr, args, 2);
4610
  type = gfc_typenode_for_spec (&expr->ts);
4611
 
4612
  if (kind == 1)
4613
    fndecl = gfor_fndecl_string_len_trim;
4614
  else if (kind == 4)
4615
    fndecl = gfor_fndecl_string_len_trim_char4;
4616
  else
4617
    gcc_unreachable ();
4618
 
4619
  se->expr = build_call_expr_loc (input_location,
4620
                              fndecl, 2, args[0], args[1]);
4621
  se->expr = convert (type, se->expr);
4622
}
4623
 
4624
 
4625
/* Returns the starting position of a substring within a string.  */
4626
 
4627
static void
4628
gfc_conv_intrinsic_index_scan_verify (gfc_se * se, gfc_expr * expr,
4629
                                      tree function)
4630
{
4631
  tree logical4_type_node = gfc_get_logical_type (4);
4632
  tree type;
4633
  tree fndecl;
4634
  tree *args;
4635
  unsigned int num_args;
4636
 
4637
  args = XALLOCAVEC (tree, 5);
4638
 
4639
  /* Get number of arguments; characters count double due to the
4640
     string length argument. Kind= is not passed to the library
4641
     and thus ignored.  */
4642
  if (expr->value.function.actual->next->next->expr == NULL)
4643
    num_args = 4;
4644
  else
4645
    num_args = 5;
4646
 
4647
  gfc_conv_intrinsic_function_args (se, expr, args, num_args);
4648
  type = gfc_typenode_for_spec (&expr->ts);
4649
 
4650
  if (num_args == 4)
4651
    args[4] = build_int_cst (logical4_type_node, 0);
4652
  else
4653
    args[4] = convert (logical4_type_node, args[4]);
4654
 
4655
  fndecl = build_addr (function, current_function_decl);
4656
  se->expr = build_call_array_loc (input_location,
4657
                               TREE_TYPE (TREE_TYPE (function)), fndecl,
4658
                               5, args);
4659
  se->expr = convert (type, se->expr);
4660
 
4661
}
4662
 
4663
/* The ascii value for a single character.  */
4664
static void
4665
gfc_conv_intrinsic_ichar (gfc_se * se, gfc_expr * expr)
4666
{
4667
  tree args[2], type, pchartype;
4668
 
4669
  gfc_conv_intrinsic_function_args (se, expr, args, 2);
4670
  gcc_assert (POINTER_TYPE_P (TREE_TYPE (args[1])));
4671
  pchartype = gfc_get_pchar_type (expr->value.function.actual->expr->ts.kind);
4672
  args[1] = fold_build1_loc (input_location, NOP_EXPR, pchartype, args[1]);
4673
  type = gfc_typenode_for_spec (&expr->ts);
4674
 
4675
  se->expr = build_fold_indirect_ref_loc (input_location,
4676
                                      args[1]);
4677
  se->expr = convert (type, se->expr);
4678
}
4679
 
4680
 
4681
/* Intrinsic ISNAN calls __builtin_isnan.  */
4682
 
4683
static void
4684
gfc_conv_intrinsic_isnan (gfc_se * se, gfc_expr * expr)
4685
{
4686
  tree arg;
4687
 
4688
  gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
4689
  se->expr = build_call_expr_loc (input_location,
4690
                                  builtin_decl_explicit (BUILT_IN_ISNAN),
4691
                                  1, arg);
4692
  STRIP_TYPE_NOPS (se->expr);
4693
  se->expr = fold_convert (gfc_typenode_for_spec (&expr->ts), se->expr);
4694
}
4695
 
4696
 
4697
/* Intrinsics IS_IOSTAT_END and IS_IOSTAT_EOR just need to compare
4698
   their argument against a constant integer value.  */
4699
 
4700
static void
4701
gfc_conv_has_intvalue (gfc_se * se, gfc_expr * expr, const int value)
4702
{
4703
  tree arg;
4704
 
4705
  gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
4706
  se->expr = fold_build2_loc (input_location, EQ_EXPR,
4707
                              gfc_typenode_for_spec (&expr->ts),
4708
                              arg, build_int_cst (TREE_TYPE (arg), value));
4709
}
4710
 
4711
 
4712
 
4713
/* MERGE (tsource, fsource, mask) = mask ? tsource : fsource.  */
4714
 
4715
static void
4716
gfc_conv_intrinsic_merge (gfc_se * se, gfc_expr * expr)
4717
{
4718
  tree tsource;
4719
  tree fsource;
4720
  tree mask;
4721
  tree type;
4722
  tree len, len2;
4723
  tree *args;
4724
  unsigned int num_args;
4725
 
4726
  num_args = gfc_intrinsic_argument_list_length (expr);
4727
  args = XALLOCAVEC (tree, num_args);
4728
 
4729
  gfc_conv_intrinsic_function_args (se, expr, args, num_args);
4730
  if (expr->ts.type != BT_CHARACTER)
4731
    {
4732
      tsource = args[0];
4733
      fsource = args[1];
4734
      mask = args[2];
4735
    }
4736
  else
4737
    {
4738
      /* We do the same as in the non-character case, but the argument
4739
         list is different because of the string length arguments. We
4740
         also have to set the string length for the result.  */
4741
      len = args[0];
4742
      tsource = args[1];
4743
      len2 = args[2];
4744
      fsource = args[3];
4745
      mask = args[4];
4746
 
4747
      gfc_trans_same_strlen_check ("MERGE intrinsic", &expr->where, len, len2,
4748
                                   &se->pre);
4749
      se->string_length = len;
4750
    }
4751
  type = TREE_TYPE (tsource);
4752
  se->expr = fold_build3_loc (input_location, COND_EXPR, type, mask, tsource,
4753
                              fold_convert (type, fsource));
4754
}
4755
 
4756
 
4757
/* MERGE_BITS (I, J, MASK) = (I & MASK) | (I & (~MASK)).  */
4758
 
4759
static void
4760
gfc_conv_intrinsic_merge_bits (gfc_se * se, gfc_expr * expr)
4761
{
4762
  tree args[3], mask, type;
4763
 
4764
  gfc_conv_intrinsic_function_args (se, expr, args, 3);
4765
  mask = gfc_evaluate_now (args[2], &se->pre);
4766
 
4767
  type = TREE_TYPE (args[0]);
4768
  gcc_assert (TREE_TYPE (args[1]) == type);
4769
  gcc_assert (TREE_TYPE (mask) == type);
4770
 
4771
  args[0] = fold_build2_loc (input_location, BIT_AND_EXPR, type, args[0], mask);
4772
  args[1] = fold_build2_loc (input_location, BIT_AND_EXPR, type, args[1],
4773
                             fold_build1_loc (input_location, BIT_NOT_EXPR,
4774
                                              type, mask));
4775
  se->expr = fold_build2_loc (input_location, BIT_IOR_EXPR, type,
4776
                              args[0], args[1]);
4777
}
4778
 
4779
 
4780
/* MASKL(n)  =  n == 0 ? 0 : (~0) << (BIT_SIZE - n)
4781
   MASKR(n)  =  n == BIT_SIZE ? ~0 : ~((~0) << n)  */
4782
 
4783
static void
4784
gfc_conv_intrinsic_mask (gfc_se * se, gfc_expr * expr, int left)
4785
{
4786
  tree arg, allones, type, utype, res, cond, bitsize;
4787
  int i;
4788
 
4789
  gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
4790
  arg = gfc_evaluate_now (arg, &se->pre);
4791
 
4792
  type = gfc_get_int_type (expr->ts.kind);
4793
  utype = unsigned_type_for (type);
4794
 
4795
  i = gfc_validate_kind (BT_INTEGER, expr->ts.kind, false);
4796
  bitsize = build_int_cst (TREE_TYPE (arg), gfc_integer_kinds[i].bit_size);
4797
 
4798
  allones = fold_build1_loc (input_location, BIT_NOT_EXPR, utype,
4799
                             build_int_cst (utype, 0));
4800
 
4801
  if (left)
4802
    {
4803
      /* Left-justified mask.  */
4804
      res = fold_build2_loc (input_location, MINUS_EXPR, TREE_TYPE (arg),
4805
                             bitsize, arg);
4806
      res = fold_build2_loc (input_location, LSHIFT_EXPR, utype, allones,
4807
                             fold_convert (utype, res));
4808
 
4809
      /* Special case arg == 0, because SHIFT_EXPR wants a shift strictly
4810
         smaller than type width.  */
4811
      cond = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node, arg,
4812
                              build_int_cst (TREE_TYPE (arg), 0));
4813
      res = fold_build3_loc (input_location, COND_EXPR, utype, cond,
4814
                             build_int_cst (utype, 0), res);
4815
    }
4816
  else
4817
    {
4818
      /* Right-justified mask.  */
4819
      res = fold_build2_loc (input_location, LSHIFT_EXPR, utype, allones,
4820
                             fold_convert (utype, arg));
4821
      res = fold_build1_loc (input_location, BIT_NOT_EXPR, utype, res);
4822
 
4823
      /* Special case agr == bit_size, because SHIFT_EXPR wants a shift
4824
         strictly smaller than type width.  */
4825
      cond = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node,
4826
                              arg, bitsize);
4827
      res = fold_build3_loc (input_location, COND_EXPR, utype,
4828
                             cond, allones, res);
4829
    }
4830
 
4831
  se->expr = fold_convert (type, res);
4832
}
4833
 
4834
 
4835
/* FRACTION (s) is translated into frexp (s, &dummy_int).  */
4836
static void
4837
gfc_conv_intrinsic_fraction (gfc_se * se, gfc_expr * expr)
4838
{
4839
  tree arg, type, tmp, frexp;
4840
 
4841
  frexp = gfc_builtin_decl_for_float_kind (BUILT_IN_FREXP, expr->ts.kind);
4842
 
4843
  type = gfc_typenode_for_spec (&expr->ts);
4844
  gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
4845
  tmp = gfc_create_var (integer_type_node, NULL);
4846
  se->expr = build_call_expr_loc (input_location, frexp, 2,
4847
                                  fold_convert (type, arg),
4848
                                  gfc_build_addr_expr (NULL_TREE, tmp));
4849
  se->expr = fold_convert (type, se->expr);
4850
}
4851
 
4852
 
4853
/* NEAREST (s, dir) is translated into
4854
     tmp = copysign (HUGE_VAL, dir);
4855
     return nextafter (s, tmp);
4856
 */
4857
static void
4858
gfc_conv_intrinsic_nearest (gfc_se * se, gfc_expr * expr)
4859
{
4860
  tree args[2], type, tmp, nextafter, copysign, huge_val;
4861
 
4862
  nextafter = gfc_builtin_decl_for_float_kind (BUILT_IN_NEXTAFTER, expr->ts.kind);
4863
  copysign = gfc_builtin_decl_for_float_kind (BUILT_IN_COPYSIGN, expr->ts.kind);
4864
 
4865
  type = gfc_typenode_for_spec (&expr->ts);
4866
  gfc_conv_intrinsic_function_args (se, expr, args, 2);
4867
 
4868
  huge_val = gfc_build_inf_or_huge (type, expr->ts.kind);
4869
  tmp = build_call_expr_loc (input_location, copysign, 2, huge_val,
4870
                             fold_convert (type, args[1]));
4871
  se->expr = build_call_expr_loc (input_location, nextafter, 2,
4872
                                  fold_convert (type, args[0]), tmp);
4873
  se->expr = fold_convert (type, se->expr);
4874
}
4875
 
4876
 
4877
/* SPACING (s) is translated into
4878
    int e;
4879
    if (s == 0)
4880
      res = tiny;
4881
    else
4882
    {
4883
      frexp (s, &e);
4884
      e = e - prec;
4885
      e = MAX_EXPR (e, emin);
4886
      res = scalbn (1., e);
4887
    }
4888
    return res;
4889
 
4890
 where prec is the precision of s, gfc_real_kinds[k].digits,
4891
       emin is min_exponent - 1, gfc_real_kinds[k].min_exponent - 1,
4892
   and tiny is tiny(s), gfc_real_kinds[k].tiny.  */
4893
 
4894
static void
4895
gfc_conv_intrinsic_spacing (gfc_se * se, gfc_expr * expr)
4896
{
4897
  tree arg, type, prec, emin, tiny, res, e;
4898
  tree cond, tmp, frexp, scalbn;
4899
  int k;
4900
  stmtblock_t block;
4901
 
4902
  k = gfc_validate_kind (BT_REAL, expr->ts.kind, false);
4903
  prec = build_int_cst (integer_type_node, gfc_real_kinds[k].digits);
4904
  emin = build_int_cst (integer_type_node, gfc_real_kinds[k].min_exponent - 1);
4905
  tiny = gfc_conv_mpfr_to_tree (gfc_real_kinds[k].tiny, expr->ts.kind, 0);
4906
 
4907
  frexp = gfc_builtin_decl_for_float_kind (BUILT_IN_FREXP, expr->ts.kind);
4908
  scalbn = gfc_builtin_decl_for_float_kind (BUILT_IN_SCALBN, expr->ts.kind);
4909
 
4910
  gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
4911
  arg = gfc_evaluate_now (arg, &se->pre);
4912
 
4913
  type = gfc_typenode_for_spec (&expr->ts);
4914
  e = gfc_create_var (integer_type_node, NULL);
4915
  res = gfc_create_var (type, NULL);
4916
 
4917
 
4918
  /* Build the block for s /= 0.  */
4919
  gfc_start_block (&block);
4920
  tmp = build_call_expr_loc (input_location, frexp, 2, arg,
4921
                             gfc_build_addr_expr (NULL_TREE, e));
4922
  gfc_add_expr_to_block (&block, tmp);
4923
 
4924
  tmp = fold_build2_loc (input_location, MINUS_EXPR, integer_type_node, e,
4925
                         prec);
4926
  gfc_add_modify (&block, e, fold_build2_loc (input_location, MAX_EXPR,
4927
                                              integer_type_node, tmp, emin));
4928
 
4929
  tmp = build_call_expr_loc (input_location, scalbn, 2,
4930
                         build_real_from_int_cst (type, integer_one_node), e);
4931
  gfc_add_modify (&block, res, tmp);
4932
 
4933
  /* Finish by building the IF statement.  */
4934
  cond = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node, arg,
4935
                          build_real_from_int_cst (type, integer_zero_node));
4936
  tmp = build3_v (COND_EXPR, cond, build2_v (MODIFY_EXPR, res, tiny),
4937
                  gfc_finish_block (&block));
4938
 
4939
  gfc_add_expr_to_block (&se->pre, tmp);
4940
  se->expr = res;
4941
}
4942
 
4943
 
4944
/* RRSPACING (s) is translated into
4945
      int e;
4946
      real x;
4947
      x = fabs (s);
4948
      if (x != 0)
4949
      {
4950
        frexp (s, &e);
4951
        x = scalbn (x, precision - e);
4952
      }
4953
      return x;
4954
 
4955
 where precision is gfc_real_kinds[k].digits.  */
4956
 
4957
static void
4958
gfc_conv_intrinsic_rrspacing (gfc_se * se, gfc_expr * expr)
4959
{
4960
  tree arg, type, e, x, cond, stmt, tmp, frexp, scalbn, fabs;
4961
  int prec, k;
4962
  stmtblock_t block;
4963
 
4964
  k = gfc_validate_kind (BT_REAL, expr->ts.kind, false);
4965
  prec = gfc_real_kinds[k].digits;
4966
 
4967
  frexp = gfc_builtin_decl_for_float_kind (BUILT_IN_FREXP, expr->ts.kind);
4968
  scalbn = gfc_builtin_decl_for_float_kind (BUILT_IN_SCALBN, expr->ts.kind);
4969
  fabs = gfc_builtin_decl_for_float_kind (BUILT_IN_FABS, expr->ts.kind);
4970
 
4971
  type = gfc_typenode_for_spec (&expr->ts);
4972
  gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
4973
  arg = gfc_evaluate_now (arg, &se->pre);
4974
 
4975
  e = gfc_create_var (integer_type_node, NULL);
4976
  x = gfc_create_var (type, NULL);
4977
  gfc_add_modify (&se->pre, x,
4978
                  build_call_expr_loc (input_location, fabs, 1, arg));
4979
 
4980
 
4981
  gfc_start_block (&block);
4982
  tmp = build_call_expr_loc (input_location, frexp, 2, arg,
4983
                             gfc_build_addr_expr (NULL_TREE, e));
4984
  gfc_add_expr_to_block (&block, tmp);
4985
 
4986
  tmp = fold_build2_loc (input_location, MINUS_EXPR, integer_type_node,
4987
                         build_int_cst (integer_type_node, prec), e);
4988
  tmp = build_call_expr_loc (input_location, scalbn, 2, x, tmp);
4989
  gfc_add_modify (&block, x, tmp);
4990
  stmt = gfc_finish_block (&block);
4991
 
4992
  cond = fold_build2_loc (input_location, NE_EXPR, boolean_type_node, x,
4993
                          build_real_from_int_cst (type, integer_zero_node));
4994
  tmp = build3_v (COND_EXPR, cond, stmt, build_empty_stmt (input_location));
4995
  gfc_add_expr_to_block (&se->pre, tmp);
4996
 
4997
  se->expr = fold_convert (type, x);
4998
}
4999
 
5000
 
5001
/* SCALE (s, i) is translated into scalbn (s, i).  */
5002
static void
5003
gfc_conv_intrinsic_scale (gfc_se * se, gfc_expr * expr)
5004
{
5005
  tree args[2], type, scalbn;
5006
 
5007
  scalbn = gfc_builtin_decl_for_float_kind (BUILT_IN_SCALBN, expr->ts.kind);
5008
 
5009
  type = gfc_typenode_for_spec (&expr->ts);
5010
  gfc_conv_intrinsic_function_args (se, expr, args, 2);
5011
  se->expr = build_call_expr_loc (input_location, scalbn, 2,
5012
                                  fold_convert (type, args[0]),
5013
                                  fold_convert (integer_type_node, args[1]));
5014
  se->expr = fold_convert (type, se->expr);
5015
}
5016
 
5017
 
5018
/* SET_EXPONENT (s, i) is translated into
5019
   scalbn (frexp (s, &dummy_int), i).  */
5020
static void
5021
gfc_conv_intrinsic_set_exponent (gfc_se * se, gfc_expr * expr)
5022
{
5023
  tree args[2], type, tmp, frexp, scalbn;
5024
 
5025
  frexp = gfc_builtin_decl_for_float_kind (BUILT_IN_FREXP, expr->ts.kind);
5026
  scalbn = gfc_builtin_decl_for_float_kind (BUILT_IN_SCALBN, expr->ts.kind);
5027
 
5028
  type = gfc_typenode_for_spec (&expr->ts);
5029
  gfc_conv_intrinsic_function_args (se, expr, args, 2);
5030
 
5031
  tmp = gfc_create_var (integer_type_node, NULL);
5032
  tmp = build_call_expr_loc (input_location, frexp, 2,
5033
                             fold_convert (type, args[0]),
5034
                             gfc_build_addr_expr (NULL_TREE, tmp));
5035
  se->expr = build_call_expr_loc (input_location, scalbn, 2, tmp,
5036
                                  fold_convert (integer_type_node, args[1]));
5037
  se->expr = fold_convert (type, se->expr);
5038
}
5039
 
5040
 
5041
static void
5042
gfc_conv_intrinsic_size (gfc_se * se, gfc_expr * expr)
5043
{
5044
  gfc_actual_arglist *actual;
5045
  tree arg1;
5046
  tree type;
5047
  tree fncall0;
5048
  tree fncall1;
5049
  gfc_se argse;
5050
  gfc_ss *ss;
5051
 
5052
  gfc_init_se (&argse, NULL);
5053
  actual = expr->value.function.actual;
5054
 
5055
  if (actual->expr->ts.type == BT_CLASS)
5056
    gfc_add_class_array_ref (actual->expr);
5057
 
5058
  ss = gfc_walk_expr (actual->expr);
5059
  gcc_assert (ss != gfc_ss_terminator);
5060
  argse.want_pointer = 1;
5061
  argse.data_not_needed = 1;
5062
  gfc_conv_expr_descriptor (&argse, actual->expr, ss);
5063
  gfc_add_block_to_block (&se->pre, &argse.pre);
5064
  gfc_add_block_to_block (&se->post, &argse.post);
5065
  arg1 = gfc_evaluate_now (argse.expr, &se->pre);
5066
 
5067
  /* Build the call to size0.  */
5068
  fncall0 = build_call_expr_loc (input_location,
5069
                             gfor_fndecl_size0, 1, arg1);
5070
 
5071
  actual = actual->next;
5072
 
5073
  if (actual->expr)
5074
    {
5075
      gfc_init_se (&argse, NULL);
5076
      gfc_conv_expr_type (&argse, actual->expr,
5077
                          gfc_array_index_type);
5078
      gfc_add_block_to_block (&se->pre, &argse.pre);
5079
 
5080
      /* Unusually, for an intrinsic, size does not exclude
5081
         an optional arg2, so we must test for it.  */
5082
      if (actual->expr->expr_type == EXPR_VARIABLE
5083
            && actual->expr->symtree->n.sym->attr.dummy
5084
            && actual->expr->symtree->n.sym->attr.optional)
5085
        {
5086
          tree tmp;
5087
          /* Build the call to size1.  */
5088
          fncall1 = build_call_expr_loc (input_location,
5089
                                     gfor_fndecl_size1, 2,
5090
                                     arg1, argse.expr);
5091
 
5092
          gfc_init_se (&argse, NULL);
5093
          argse.want_pointer = 1;
5094
          argse.data_not_needed = 1;
5095
          gfc_conv_expr (&argse, actual->expr);
5096
          gfc_add_block_to_block (&se->pre, &argse.pre);
5097
          tmp = fold_build2_loc (input_location, NE_EXPR, boolean_type_node,
5098
                                 argse.expr, null_pointer_node);
5099
          tmp = gfc_evaluate_now (tmp, &se->pre);
5100
          se->expr = fold_build3_loc (input_location, COND_EXPR,
5101
                                      pvoid_type_node, tmp, fncall1, fncall0);
5102
        }
5103
      else
5104
        {
5105
          se->expr = NULL_TREE;
5106
          argse.expr = fold_build2_loc (input_location, MINUS_EXPR,
5107
                                        gfc_array_index_type,
5108
                                        argse.expr, gfc_index_one_node);
5109
        }
5110
    }
5111
  else if (expr->value.function.actual->expr->rank == 1)
5112
    {
5113
      argse.expr = gfc_index_zero_node;
5114
      se->expr = NULL_TREE;
5115
    }
5116
  else
5117
    se->expr = fncall0;
5118
 
5119
  if (se->expr == NULL_TREE)
5120
    {
5121
      tree ubound, lbound;
5122
 
5123
      arg1 = build_fold_indirect_ref_loc (input_location,
5124
                                      arg1);
5125
      ubound = gfc_conv_descriptor_ubound_get (arg1, argse.expr);
5126
      lbound = gfc_conv_descriptor_lbound_get (arg1, argse.expr);
5127
      se->expr = fold_build2_loc (input_location, MINUS_EXPR,
5128
                                  gfc_array_index_type, ubound, lbound);
5129
      se->expr = fold_build2_loc (input_location, PLUS_EXPR,
5130
                                  gfc_array_index_type,
5131
                                  se->expr, gfc_index_one_node);
5132
      se->expr = fold_build2_loc (input_location, MAX_EXPR,
5133
                                  gfc_array_index_type, se->expr,
5134
                                  gfc_index_zero_node);
5135
    }
5136
 
5137
  type = gfc_typenode_for_spec (&expr->ts);
5138
  se->expr = convert (type, se->expr);
5139
}
5140
 
5141
 
5142
/* Helper function to compute the size of a character variable,
5143
   excluding the terminating null characters.  The result has
5144
   gfc_array_index_type type.  */
5145
 
5146
static tree
5147
size_of_string_in_bytes (int kind, tree string_length)
5148
{
5149
  tree bytesize;
5150
  int i = gfc_validate_kind (BT_CHARACTER, kind, false);
5151
 
5152
  bytesize = build_int_cst (gfc_array_index_type,
5153
                            gfc_character_kinds[i].bit_size / 8);
5154
 
5155
  return fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
5156
                          bytesize,
5157
                          fold_convert (gfc_array_index_type, string_length));
5158
}
5159
 
5160
 
5161
static void
5162
gfc_conv_intrinsic_sizeof (gfc_se *se, gfc_expr *expr)
5163
{
5164
  gfc_expr *arg;
5165
  gfc_ss *ss;
5166
  gfc_se argse;
5167
  tree source_bytes;
5168
  tree type;
5169
  tree tmp;
5170
  tree lower;
5171
  tree upper;
5172
  int n;
5173
 
5174
  arg = expr->value.function.actual->expr;
5175
 
5176
  gfc_init_se (&argse, NULL);
5177
  ss = gfc_walk_expr (arg);
5178
 
5179
  if (ss == gfc_ss_terminator)
5180
    {
5181
      if (arg->ts.type == BT_CLASS)
5182
        gfc_add_data_component (arg);
5183
 
5184
      gfc_conv_expr_reference (&argse, arg);
5185
 
5186
      type = TREE_TYPE (build_fold_indirect_ref_loc (input_location,
5187
                                                 argse.expr));
5188
 
5189
      /* Obtain the source word length.  */
5190
      if (arg->ts.type == BT_CHARACTER)
5191
        se->expr = size_of_string_in_bytes (arg->ts.kind,
5192
                                            argse.string_length);
5193
      else
5194
        se->expr = fold_convert (gfc_array_index_type, size_in_bytes (type));
5195
    }
5196
  else
5197
    {
5198
      source_bytes = gfc_create_var (gfc_array_index_type, "bytes");
5199
      argse.want_pointer = 0;
5200
      gfc_conv_expr_descriptor (&argse, arg, ss);
5201
      type = gfc_get_element_type (TREE_TYPE (argse.expr));
5202
 
5203
      /* Obtain the argument's word length.  */
5204
      if (arg->ts.type == BT_CHARACTER)
5205
        tmp = size_of_string_in_bytes (arg->ts.kind, argse.string_length);
5206
      else
5207
        tmp = fold_convert (gfc_array_index_type,
5208
                            size_in_bytes (type));
5209
      gfc_add_modify (&argse.pre, source_bytes, tmp);
5210
 
5211
      /* Obtain the size of the array in bytes.  */
5212
      for (n = 0; n < arg->rank; n++)
5213
        {
5214
          tree idx;
5215
          idx = gfc_rank_cst[n];
5216
          lower = gfc_conv_descriptor_lbound_get (argse.expr, idx);
5217
          upper = gfc_conv_descriptor_ubound_get (argse.expr, idx);
5218
          tmp = fold_build2_loc (input_location, MINUS_EXPR,
5219
                                 gfc_array_index_type, upper, lower);
5220
          tmp = fold_build2_loc (input_location, PLUS_EXPR,
5221
                                 gfc_array_index_type, tmp, gfc_index_one_node);
5222
          tmp = fold_build2_loc (input_location, MULT_EXPR,
5223
                                 gfc_array_index_type, tmp, source_bytes);
5224
          gfc_add_modify (&argse.pre, source_bytes, tmp);
5225
        }
5226
      se->expr = source_bytes;
5227
    }
5228
 
5229
  gfc_add_block_to_block (&se->pre, &argse.pre);
5230
}
5231
 
5232
 
5233
static void
5234
gfc_conv_intrinsic_storage_size (gfc_se *se, gfc_expr *expr)
5235
{
5236
  gfc_expr *arg;
5237
  gfc_ss *ss;
5238
  gfc_se argse,eight;
5239
  tree type, result_type, tmp;
5240
 
5241
  arg = expr->value.function.actual->expr;
5242
  gfc_init_se (&eight, NULL);
5243
  gfc_conv_expr (&eight, gfc_get_int_expr (expr->ts.kind, NULL, 8));
5244
 
5245
  gfc_init_se (&argse, NULL);
5246
  ss = gfc_walk_expr (arg);
5247
  result_type = gfc_get_int_type (expr->ts.kind);
5248
 
5249
  if (ss == gfc_ss_terminator)
5250
    {
5251
      if (arg->ts.type == BT_CLASS)
5252
      {
5253
        gfc_add_vptr_component (arg);
5254
        gfc_add_size_component (arg);
5255
        gfc_conv_expr (&argse, arg);
5256
        tmp = fold_convert (result_type, argse.expr);
5257
        goto done;
5258
      }
5259
 
5260
      gfc_conv_expr_reference (&argse, arg);
5261
      type = TREE_TYPE (build_fold_indirect_ref_loc (input_location,
5262
                                                     argse.expr));
5263
    }
5264
  else
5265
    {
5266
      argse.want_pointer = 0;
5267
      gfc_conv_expr_descriptor (&argse, arg, ss);
5268
      type = gfc_get_element_type (TREE_TYPE (argse.expr));
5269
    }
5270
 
5271
  /* Obtain the argument's word length.  */
5272
  if (arg->ts.type == BT_CHARACTER)
5273
    tmp = size_of_string_in_bytes (arg->ts.kind, argse.string_length);
5274
  else
5275
    tmp = fold_convert (result_type, size_in_bytes (type));
5276
 
5277
done:
5278
  se->expr = fold_build2_loc (input_location, MULT_EXPR, result_type, tmp,
5279
                              eight.expr);
5280
  gfc_add_block_to_block (&se->pre, &argse.pre);
5281
}
5282
 
5283
 
5284
/* Intrinsic string comparison functions.  */
5285
 
5286
static void
5287
gfc_conv_intrinsic_strcmp (gfc_se * se, gfc_expr * expr, enum tree_code op)
5288
{
5289
  tree args[4];
5290
 
5291
  gfc_conv_intrinsic_function_args (se, expr, args, 4);
5292
 
5293
  se->expr
5294
    = gfc_build_compare_string (args[0], args[1], args[2], args[3],
5295
                                expr->value.function.actual->expr->ts.kind,
5296
                                op);
5297
  se->expr = fold_build2_loc (input_location, op,
5298
                              gfc_typenode_for_spec (&expr->ts), se->expr,
5299
                              build_int_cst (TREE_TYPE (se->expr), 0));
5300
}
5301
 
5302
/* Generate a call to the adjustl/adjustr library function.  */
5303
static void
5304
gfc_conv_intrinsic_adjust (gfc_se * se, gfc_expr * expr, tree fndecl)
5305
{
5306
  tree args[3];
5307
  tree len;
5308
  tree type;
5309
  tree var;
5310
  tree tmp;
5311
 
5312
  gfc_conv_intrinsic_function_args (se, expr, &args[1], 2);
5313
  len = args[1];
5314
 
5315
  type = TREE_TYPE (args[2]);
5316
  var = gfc_conv_string_tmp (se, type, len);
5317
  args[0] = var;
5318
 
5319
  tmp = build_call_expr_loc (input_location,
5320
                         fndecl, 3, args[0], args[1], args[2]);
5321
  gfc_add_expr_to_block (&se->pre, tmp);
5322
  se->expr = var;
5323
  se->string_length = len;
5324
}
5325
 
5326
 
5327
/* Generate code for the TRANSFER intrinsic:
5328
        For scalar results:
5329
          DEST = TRANSFER (SOURCE, MOLD)
5330
        where:
5331
          typeof<DEST> = typeof<MOLD>
5332
        and:
5333
          MOLD is scalar.
5334
 
5335
        For array results:
5336
          DEST(1:N) = TRANSFER (SOURCE, MOLD[, SIZE])
5337
        where:
5338
          typeof<DEST> = typeof<MOLD>
5339
        and:
5340
          N = min (sizeof (SOURCE(:)), sizeof (DEST(:)),
5341
              sizeof (DEST(0) * SIZE).  */
5342
static void
5343
gfc_conv_intrinsic_transfer (gfc_se * se, gfc_expr * expr)
5344
{
5345
  tree tmp;
5346
  tree tmpdecl;
5347
  tree ptr;
5348
  tree extent;
5349
  tree source;
5350
  tree source_type;
5351
  tree source_bytes;
5352
  tree mold_type;
5353
  tree dest_word_len;
5354
  tree size_words;
5355
  tree size_bytes;
5356
  tree upper;
5357
  tree lower;
5358
  tree stmt;
5359
  gfc_actual_arglist *arg;
5360
  gfc_se argse;
5361
  gfc_ss *ss;
5362
  gfc_array_info *info;
5363
  stmtblock_t block;
5364
  int n;
5365
  bool scalar_mold;
5366
 
5367
  info = NULL;
5368
  if (se->loop)
5369
    info = &se->ss->info->data.array;
5370
 
5371
  /* Convert SOURCE.  The output from this stage is:-
5372
        source_bytes = length of the source in bytes
5373
        source = pointer to the source data.  */
5374
  arg = expr->value.function.actual;
5375
 
5376
  /* Ensure double transfer through LOGICAL preserves all
5377
     the needed bits.  */
5378
  if (arg->expr->expr_type == EXPR_FUNCTION
5379
        && arg->expr->value.function.esym == NULL
5380
        && arg->expr->value.function.isym != NULL
5381
        && arg->expr->value.function.isym->id == GFC_ISYM_TRANSFER
5382
        && arg->expr->ts.type == BT_LOGICAL
5383
        && expr->ts.type != arg->expr->ts.type)
5384
    arg->expr->value.function.name = "__transfer_in_transfer";
5385
 
5386
  gfc_init_se (&argse, NULL);
5387
  ss = gfc_walk_expr (arg->expr);
5388
 
5389
  source_bytes = gfc_create_var (gfc_array_index_type, NULL);
5390
 
5391
  /* Obtain the pointer to source and the length of source in bytes.  */
5392
  if (ss == gfc_ss_terminator)
5393
    {
5394
      gfc_conv_expr_reference (&argse, arg->expr);
5395
      source = argse.expr;
5396
 
5397
      source_type = TREE_TYPE (build_fold_indirect_ref_loc (input_location,
5398
                                                        argse.expr));
5399
 
5400
      /* Obtain the source word length.  */
5401
      if (arg->expr->ts.type == BT_CHARACTER)
5402
        tmp = size_of_string_in_bytes (arg->expr->ts.kind,
5403
                                       argse.string_length);
5404
      else
5405
        tmp = fold_convert (gfc_array_index_type,
5406
                            size_in_bytes (source_type));
5407
    }
5408
  else
5409
    {
5410
      argse.want_pointer = 0;
5411
      gfc_conv_expr_descriptor (&argse, arg->expr, ss);
5412
      source = gfc_conv_descriptor_data_get (argse.expr);
5413
      source_type = gfc_get_element_type (TREE_TYPE (argse.expr));
5414
 
5415
      /* Repack the source if not a full variable array.  */
5416
      if (arg->expr->expr_type == EXPR_VARIABLE
5417
              && arg->expr->ref->u.ar.type != AR_FULL)
5418
        {
5419
          tmp = gfc_build_addr_expr (NULL_TREE, argse.expr);
5420
 
5421
          if (gfc_option.warn_array_temp)
5422
            gfc_warning ("Creating array temporary at %L", &expr->where);
5423
 
5424
          source = build_call_expr_loc (input_location,
5425
                                    gfor_fndecl_in_pack, 1, tmp);
5426
          source = gfc_evaluate_now (source, &argse.pre);
5427
 
5428
          /* Free the temporary.  */
5429
          gfc_start_block (&block);
5430
          tmp = gfc_call_free (convert (pvoid_type_node, source));
5431
          gfc_add_expr_to_block (&block, tmp);
5432
          stmt = gfc_finish_block (&block);
5433
 
5434
          /* Clean up if it was repacked.  */
5435
          gfc_init_block (&block);
5436
          tmp = gfc_conv_array_data (argse.expr);
5437
          tmp = fold_build2_loc (input_location, NE_EXPR, boolean_type_node,
5438
                                 source, tmp);
5439
          tmp = build3_v (COND_EXPR, tmp, stmt,
5440
                          build_empty_stmt (input_location));
5441
          gfc_add_expr_to_block (&block, tmp);
5442
          gfc_add_block_to_block (&block, &se->post);
5443
          gfc_init_block (&se->post);
5444
          gfc_add_block_to_block (&se->post, &block);
5445
        }
5446
 
5447
      /* Obtain the source word length.  */
5448
      if (arg->expr->ts.type == BT_CHARACTER)
5449
        tmp = size_of_string_in_bytes (arg->expr->ts.kind,
5450
                                       argse.string_length);
5451
      else
5452
        tmp = fold_convert (gfc_array_index_type,
5453
                            size_in_bytes (source_type));
5454
 
5455
      /* Obtain the size of the array in bytes.  */
5456
      extent = gfc_create_var (gfc_array_index_type, NULL);
5457
      for (n = 0; n < arg->expr->rank; n++)
5458
        {
5459
          tree idx;
5460
          idx = gfc_rank_cst[n];
5461
          gfc_add_modify (&argse.pre, source_bytes, tmp);
5462
          lower = gfc_conv_descriptor_lbound_get (argse.expr, idx);
5463
          upper = gfc_conv_descriptor_ubound_get (argse.expr, idx);
5464
          tmp = fold_build2_loc (input_location, MINUS_EXPR,
5465
                                 gfc_array_index_type, upper, lower);
5466
          gfc_add_modify (&argse.pre, extent, tmp);
5467
          tmp = fold_build2_loc (input_location, PLUS_EXPR,
5468
                                 gfc_array_index_type, extent,
5469
                                 gfc_index_one_node);
5470
          tmp = fold_build2_loc (input_location, MULT_EXPR,
5471
                                 gfc_array_index_type, tmp, source_bytes);
5472
        }
5473
    }
5474
 
5475
  gfc_add_modify (&argse.pre, source_bytes, tmp);
5476
  gfc_add_block_to_block (&se->pre, &argse.pre);
5477
  gfc_add_block_to_block (&se->post, &argse.post);
5478
 
5479
  /* Now convert MOLD.  The outputs are:
5480
        mold_type = the TREE type of MOLD
5481
        dest_word_len = destination word length in bytes.  */
5482
  arg = arg->next;
5483
 
5484
  gfc_init_se (&argse, NULL);
5485
  ss = gfc_walk_expr (arg->expr);
5486
 
5487
  scalar_mold = arg->expr->rank == 0;
5488
 
5489
  if (ss == gfc_ss_terminator)
5490
    {
5491
      gfc_conv_expr_reference (&argse, arg->expr);
5492
      mold_type = TREE_TYPE (build_fold_indirect_ref_loc (input_location,
5493
                                                      argse.expr));
5494
    }
5495
  else
5496
    {
5497
      gfc_init_se (&argse, NULL);
5498
      argse.want_pointer = 0;
5499
      gfc_conv_expr_descriptor (&argse, arg->expr, ss);
5500
      mold_type = gfc_get_element_type (TREE_TYPE (argse.expr));
5501
    }
5502
 
5503
  gfc_add_block_to_block (&se->pre, &argse.pre);
5504
  gfc_add_block_to_block (&se->post, &argse.post);
5505
 
5506
  if (strcmp (expr->value.function.name, "__transfer_in_transfer") == 0)
5507
    {
5508
      /* If this TRANSFER is nested in another TRANSFER, use a type
5509
         that preserves all bits.  */
5510
      if (arg->expr->ts.type == BT_LOGICAL)
5511
        mold_type = gfc_get_int_type (arg->expr->ts.kind);
5512
    }
5513
 
5514
  if (arg->expr->ts.type == BT_CHARACTER)
5515
    {
5516
      tmp = size_of_string_in_bytes (arg->expr->ts.kind, argse.string_length);
5517
      mold_type = gfc_get_character_type_len (arg->expr->ts.kind, tmp);
5518
    }
5519
  else
5520
    tmp = fold_convert (gfc_array_index_type,
5521
                        size_in_bytes (mold_type));
5522
 
5523
  dest_word_len = gfc_create_var (gfc_array_index_type, NULL);
5524
  gfc_add_modify (&se->pre, dest_word_len, tmp);
5525
 
5526
  /* Finally convert SIZE, if it is present.  */
5527
  arg = arg->next;
5528
  size_words = gfc_create_var (gfc_array_index_type, NULL);
5529
 
5530
  if (arg->expr)
5531
    {
5532
      gfc_init_se (&argse, NULL);
5533
      gfc_conv_expr_reference (&argse, arg->expr);
5534
      tmp = convert (gfc_array_index_type,
5535
                     build_fold_indirect_ref_loc (input_location,
5536
                                              argse.expr));
5537
      gfc_add_block_to_block (&se->pre, &argse.pre);
5538
      gfc_add_block_to_block (&se->post, &argse.post);
5539
    }
5540
  else
5541
    tmp = NULL_TREE;
5542
 
5543
  /* Separate array and scalar results.  */
5544
  if (scalar_mold && tmp == NULL_TREE)
5545
    goto scalar_transfer;
5546
 
5547
  size_bytes = gfc_create_var (gfc_array_index_type, NULL);
5548
  if (tmp != NULL_TREE)
5549
    tmp = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
5550
                           tmp, dest_word_len);
5551
  else
5552
    tmp = source_bytes;
5553
 
5554
  gfc_add_modify (&se->pre, size_bytes, tmp);
5555
  gfc_add_modify (&se->pre, size_words,
5556
                       fold_build2_loc (input_location, CEIL_DIV_EXPR,
5557
                                        gfc_array_index_type,
5558
                                        size_bytes, dest_word_len));
5559
 
5560
  /* Evaluate the bounds of the result.  If the loop range exists, we have
5561
     to check if it is too large.  If so, we modify loop->to be consistent
5562
     with min(size, size(source)).  Otherwise, size is made consistent with
5563
     the loop range, so that the right number of bytes is transferred.*/
5564
  n = se->loop->order[0];
5565
  if (se->loop->to[n] != NULL_TREE)
5566
    {
5567
      tmp = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
5568
                             se->loop->to[n], se->loop->from[n]);
5569
      tmp = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
5570
                             tmp, gfc_index_one_node);
5571
      tmp = fold_build2_loc (input_location, MIN_EXPR, gfc_array_index_type,
5572
                         tmp, size_words);
5573
      gfc_add_modify (&se->pre, size_words, tmp);
5574
      gfc_add_modify (&se->pre, size_bytes,
5575
                           fold_build2_loc (input_location, MULT_EXPR,
5576
                                            gfc_array_index_type,
5577
                                            size_words, dest_word_len));
5578
      upper = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
5579
                               size_words, se->loop->from[n]);
5580
      upper = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
5581
                               upper, gfc_index_one_node);
5582
    }
5583
  else
5584
    {
5585
      upper = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
5586
                               size_words, gfc_index_one_node);
5587
      se->loop->from[n] = gfc_index_zero_node;
5588
    }
5589
 
5590
  se->loop->to[n] = upper;
5591
 
5592
  /* Build a destination descriptor, using the pointer, source, as the
5593
     data field.  */
5594
  gfc_trans_create_temp_array (&se->pre, &se->post, se->ss, mold_type,
5595
                               NULL_TREE, false, true, false, &expr->where);
5596
 
5597
  /* Cast the pointer to the result.  */
5598
  tmp = gfc_conv_descriptor_data_get (info->descriptor);
5599
  tmp = fold_convert (pvoid_type_node, tmp);
5600
 
5601
  /* Use memcpy to do the transfer.  */
5602
  tmp = build_call_expr_loc (input_location,
5603
                         builtin_decl_explicit (BUILT_IN_MEMCPY),
5604
                         3,
5605
                         tmp,
5606
                         fold_convert (pvoid_type_node, source),
5607
                         fold_build2_loc (input_location, MIN_EXPR,
5608
                                          gfc_array_index_type,
5609
                                          size_bytes, source_bytes));
5610
  gfc_add_expr_to_block (&se->pre, tmp);
5611
 
5612
  se->expr = info->descriptor;
5613
  if (expr->ts.type == BT_CHARACTER)
5614
    se->string_length = fold_convert (gfc_charlen_type_node, dest_word_len);
5615
 
5616
  return;
5617
 
5618
/* Deal with scalar results.  */
5619
scalar_transfer:
5620
  extent = fold_build2_loc (input_location, MIN_EXPR, gfc_array_index_type,
5621
                            dest_word_len, source_bytes);
5622
  extent = fold_build2_loc (input_location, MAX_EXPR, gfc_array_index_type,
5623
                            extent, gfc_index_zero_node);
5624
 
5625
  if (expr->ts.type == BT_CHARACTER)
5626
    {
5627
      tree direct;
5628
      tree indirect;
5629
 
5630
      ptr = convert (gfc_get_pchar_type (expr->ts.kind), source);
5631
      tmpdecl = gfc_create_var (gfc_get_pchar_type (expr->ts.kind),
5632
                                "transfer");
5633
 
5634
      /* If source is longer than the destination, use a pointer to
5635
         the source directly.  */
5636
      gfc_init_block (&block);
5637
      gfc_add_modify (&block, tmpdecl, ptr);
5638
      direct = gfc_finish_block (&block);
5639
 
5640
      /* Otherwise, allocate a string with the length of the destination
5641
         and copy the source into it.  */
5642
      gfc_init_block (&block);
5643
      tmp = gfc_get_pchar_type (expr->ts.kind);
5644
      tmp = gfc_call_malloc (&block, tmp, dest_word_len);
5645
      gfc_add_modify (&block, tmpdecl,
5646
                      fold_convert (TREE_TYPE (ptr), tmp));
5647
      tmp = build_call_expr_loc (input_location,
5648
                             builtin_decl_explicit (BUILT_IN_MEMCPY), 3,
5649
                             fold_convert (pvoid_type_node, tmpdecl),
5650
                             fold_convert (pvoid_type_node, ptr),
5651
                             extent);
5652
      gfc_add_expr_to_block (&block, tmp);
5653
      indirect = gfc_finish_block (&block);
5654
 
5655
      /* Wrap it up with the condition.  */
5656
      tmp = fold_build2_loc (input_location, LE_EXPR, boolean_type_node,
5657
                             dest_word_len, source_bytes);
5658
      tmp = build3_v (COND_EXPR, tmp, direct, indirect);
5659
      gfc_add_expr_to_block (&se->pre, tmp);
5660
 
5661
      se->expr = tmpdecl;
5662
      se->string_length = dest_word_len;
5663
    }
5664
  else
5665
    {
5666
      tmpdecl = gfc_create_var (mold_type, "transfer");
5667
 
5668
      ptr = convert (build_pointer_type (mold_type), source);
5669
 
5670
      /* Use memcpy to do the transfer.  */
5671
      tmp = gfc_build_addr_expr (NULL_TREE, tmpdecl);
5672
      tmp = build_call_expr_loc (input_location,
5673
                             builtin_decl_explicit (BUILT_IN_MEMCPY), 3,
5674
                             fold_convert (pvoid_type_node, tmp),
5675
                             fold_convert (pvoid_type_node, ptr),
5676
                             extent);
5677
      gfc_add_expr_to_block (&se->pre, tmp);
5678
 
5679
      se->expr = tmpdecl;
5680
    }
5681
}
5682
 
5683
 
5684
/* Generate code for the ALLOCATED intrinsic.
5685
   Generate inline code that directly check the address of the argument.  */
5686
 
5687
static void
5688
gfc_conv_allocated (gfc_se *se, gfc_expr *expr)
5689
{
5690
  gfc_actual_arglist *arg1;
5691
  gfc_se arg1se;
5692
  gfc_ss *ss1;
5693
  tree tmp;
5694
 
5695
  gfc_init_se (&arg1se, NULL);
5696
  arg1 = expr->value.function.actual;
5697
 
5698
  if (arg1->expr->ts.type == BT_CLASS)
5699
    {
5700
      /* Make sure that class array expressions have both a _data
5701
         component reference and an array reference....  */
5702
      if (CLASS_DATA (arg1->expr)->attr.dimension)
5703
        gfc_add_class_array_ref (arg1->expr);
5704
      /* .... whilst scalars only need the _data component.  */
5705
      else
5706
        gfc_add_data_component (arg1->expr);
5707
    }
5708
 
5709
  ss1 = gfc_walk_expr (arg1->expr);
5710
 
5711
  if (ss1 == gfc_ss_terminator)
5712
    {
5713
      /* Allocatable scalar.  */
5714
      arg1se.want_pointer = 1;
5715
      gfc_conv_expr (&arg1se, arg1->expr);
5716
      tmp = arg1se.expr;
5717
    }
5718
  else
5719
    {
5720
      /* Allocatable array.  */
5721
      arg1se.descriptor_only = 1;
5722
      gfc_conv_expr_descriptor (&arg1se, arg1->expr, ss1);
5723
      tmp = gfc_conv_descriptor_data_get (arg1se.expr);
5724
    }
5725
 
5726
  tmp = fold_build2_loc (input_location, NE_EXPR, boolean_type_node, tmp,
5727
                         fold_convert (TREE_TYPE (tmp), null_pointer_node));
5728
  se->expr = convert (gfc_typenode_for_spec (&expr->ts), tmp);
5729
}
5730
 
5731
 
5732
/* Generate code for the ASSOCIATED intrinsic.
5733
   If both POINTER and TARGET are arrays, generate a call to library function
5734
   _gfor_associated, and pass descriptors of POINTER and TARGET to it.
5735
   In other cases, generate inline code that directly compare the address of
5736
   POINTER with the address of TARGET.  */
5737
 
5738
static void
5739
gfc_conv_associated (gfc_se *se, gfc_expr *expr)
5740
{
5741
  gfc_actual_arglist *arg1;
5742
  gfc_actual_arglist *arg2;
5743
  gfc_se arg1se;
5744
  gfc_se arg2se;
5745
  tree tmp2;
5746
  tree tmp;
5747
  tree nonzero_charlen;
5748
  tree nonzero_arraylen;
5749
  gfc_ss *ss1, *ss2;
5750
 
5751
  gfc_init_se (&arg1se, NULL);
5752
  gfc_init_se (&arg2se, NULL);
5753
  arg1 = expr->value.function.actual;
5754
  if (arg1->expr->ts.type == BT_CLASS)
5755
    gfc_add_data_component (arg1->expr);
5756
  arg2 = arg1->next;
5757
  ss1 = gfc_walk_expr (arg1->expr);
5758
 
5759
  if (!arg2->expr)
5760
    {
5761
      /* No optional target.  */
5762
      if (ss1 == gfc_ss_terminator)
5763
        {
5764
          /* A pointer to a scalar.  */
5765
          arg1se.want_pointer = 1;
5766
          gfc_conv_expr (&arg1se, arg1->expr);
5767
          tmp2 = arg1se.expr;
5768
        }
5769
      else
5770
        {
5771
          /* A pointer to an array.  */
5772
          gfc_conv_expr_descriptor (&arg1se, arg1->expr, ss1);
5773
          tmp2 = gfc_conv_descriptor_data_get (arg1se.expr);
5774
        }
5775
      gfc_add_block_to_block (&se->pre, &arg1se.pre);
5776
      gfc_add_block_to_block (&se->post, &arg1se.post);
5777
      tmp = fold_build2_loc (input_location, NE_EXPR, boolean_type_node, tmp2,
5778
                             fold_convert (TREE_TYPE (tmp2), null_pointer_node));
5779
      se->expr = tmp;
5780
    }
5781
  else
5782
    {
5783
      /* An optional target.  */
5784
      if (arg2->expr->ts.type == BT_CLASS)
5785
        gfc_add_data_component (arg2->expr);
5786
      ss2 = gfc_walk_expr (arg2->expr);
5787
 
5788
      nonzero_charlen = NULL_TREE;
5789
      if (arg1->expr->ts.type == BT_CHARACTER)
5790
        nonzero_charlen = fold_build2_loc (input_location, NE_EXPR,
5791
                                           boolean_type_node,
5792
                                           arg1->expr->ts.u.cl->backend_decl,
5793
                                           integer_zero_node);
5794
 
5795
      if (ss1 == gfc_ss_terminator)
5796
        {
5797
          /* A pointer to a scalar.  */
5798
          gcc_assert (ss2 == gfc_ss_terminator);
5799
          arg1se.want_pointer = 1;
5800
          gfc_conv_expr (&arg1se, arg1->expr);
5801
          arg2se.want_pointer = 1;
5802
          gfc_conv_expr (&arg2se, arg2->expr);
5803
          gfc_add_block_to_block (&se->pre, &arg1se.pre);
5804
          gfc_add_block_to_block (&se->post, &arg1se.post);
5805
          tmp = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node,
5806
                                 arg1se.expr, arg2se.expr);
5807
          tmp2 = fold_build2_loc (input_location, NE_EXPR, boolean_type_node,
5808
                                  arg1se.expr, null_pointer_node);
5809
          se->expr = fold_build2_loc (input_location, TRUTH_AND_EXPR,
5810
                                      boolean_type_node, tmp, tmp2);
5811
        }
5812
      else
5813
        {
5814
          /* An array pointer of zero length is not associated if target is
5815
             present.  */
5816
          arg1se.descriptor_only = 1;
5817
          gfc_conv_expr_lhs (&arg1se, arg1->expr);
5818
          tmp = gfc_conv_descriptor_stride_get (arg1se.expr,
5819
                                            gfc_rank_cst[arg1->expr->rank - 1]);
5820
          nonzero_arraylen = fold_build2_loc (input_location, NE_EXPR,
5821
                                              boolean_type_node, tmp,
5822
                                              build_int_cst (TREE_TYPE (tmp), 0));
5823
 
5824
          /* A pointer to an array, call library function _gfor_associated.  */
5825
          gcc_assert (ss2 != gfc_ss_terminator);
5826
          arg1se.want_pointer = 1;
5827
          gfc_conv_expr_descriptor (&arg1se, arg1->expr, ss1);
5828
 
5829
          arg2se.want_pointer = 1;
5830
          gfc_conv_expr_descriptor (&arg2se, arg2->expr, ss2);
5831
          gfc_add_block_to_block (&se->pre, &arg2se.pre);
5832
          gfc_add_block_to_block (&se->post, &arg2se.post);
5833
          se->expr = build_call_expr_loc (input_location,
5834
                                      gfor_fndecl_associated, 2,
5835
                                      arg1se.expr, arg2se.expr);
5836
          se->expr = convert (boolean_type_node, se->expr);
5837
          se->expr = fold_build2_loc (input_location, TRUTH_AND_EXPR,
5838
                                      boolean_type_node, se->expr,
5839
                                      nonzero_arraylen);
5840
        }
5841
 
5842
      /* If target is present zero character length pointers cannot
5843
         be associated.  */
5844
      if (nonzero_charlen != NULL_TREE)
5845
        se->expr = fold_build2_loc (input_location, TRUTH_AND_EXPR,
5846
                                    boolean_type_node,
5847
                                    se->expr, nonzero_charlen);
5848
    }
5849
 
5850
  se->expr = convert (gfc_typenode_for_spec (&expr->ts), se->expr);
5851
}
5852
 
5853
 
5854
/* Generate code for the SAME_TYPE_AS intrinsic.
5855
   Generate inline code that directly checks the vindices.  */
5856
 
5857
static void
5858
gfc_conv_same_type_as (gfc_se *se, gfc_expr *expr)
5859
{
5860
  gfc_expr *a, *b;
5861
  gfc_se se1, se2;
5862
  tree tmp;
5863
 
5864
  gfc_init_se (&se1, NULL);
5865
  gfc_init_se (&se2, NULL);
5866
 
5867
  a = expr->value.function.actual->expr;
5868
  b = expr->value.function.actual->next->expr;
5869
 
5870
  if (a->ts.type == BT_CLASS)
5871
    {
5872
      gfc_add_vptr_component (a);
5873
      gfc_add_hash_component (a);
5874
    }
5875
  else if (a->ts.type == BT_DERIVED)
5876
    a = gfc_get_int_expr (gfc_default_integer_kind, NULL,
5877
                          a->ts.u.derived->hash_value);
5878
 
5879
  if (b->ts.type == BT_CLASS)
5880
    {
5881
      gfc_add_vptr_component (b);
5882
      gfc_add_hash_component (b);
5883
    }
5884
  else if (b->ts.type == BT_DERIVED)
5885
    b = gfc_get_int_expr (gfc_default_integer_kind, NULL,
5886
                          b->ts.u.derived->hash_value);
5887
 
5888
  gfc_conv_expr (&se1, a);
5889
  gfc_conv_expr (&se2, b);
5890
 
5891
  tmp = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node,
5892
                         se1.expr, fold_convert (TREE_TYPE (se1.expr), se2.expr));
5893
  se->expr = convert (gfc_typenode_for_spec (&expr->ts), tmp);
5894
}
5895
 
5896
 
5897
/* Generate code for SELECTED_CHAR_KIND (NAME) intrinsic function.  */
5898
 
5899
static void
5900
gfc_conv_intrinsic_sc_kind (gfc_se *se, gfc_expr *expr)
5901
{
5902
  tree args[2];
5903
 
5904
  gfc_conv_intrinsic_function_args (se, expr, args, 2);
5905
  se->expr = build_call_expr_loc (input_location,
5906
                              gfor_fndecl_sc_kind, 2, args[0], args[1]);
5907
  se->expr = fold_convert (gfc_typenode_for_spec (&expr->ts), se->expr);
5908
}
5909
 
5910
 
5911
/* Generate code for SELECTED_INT_KIND (R) intrinsic function.  */
5912
 
5913
static void
5914
gfc_conv_intrinsic_si_kind (gfc_se *se, gfc_expr *expr)
5915
{
5916
  tree arg, type;
5917
 
5918
  gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
5919
 
5920
  /* The argument to SELECTED_INT_KIND is INTEGER(4).  */
5921
  type = gfc_get_int_type (4);
5922
  arg = gfc_build_addr_expr (NULL_TREE, fold_convert (type, arg));
5923
 
5924
  /* Convert it to the required type.  */
5925
  type = gfc_typenode_for_spec (&expr->ts);
5926
  se->expr = build_call_expr_loc (input_location,
5927
                              gfor_fndecl_si_kind, 1, arg);
5928
  se->expr = fold_convert (type, se->expr);
5929
}
5930
 
5931
 
5932
/* Generate code for SELECTED_REAL_KIND (P, R, RADIX) intrinsic function.  */
5933
 
5934
static void
5935
gfc_conv_intrinsic_sr_kind (gfc_se *se, gfc_expr *expr)
5936
{
5937
  gfc_actual_arglist *actual;
5938
  tree type;
5939
  gfc_se argse;
5940
  VEC(tree,gc) *args = NULL;
5941
 
5942
  for (actual = expr->value.function.actual; actual; actual = actual->next)
5943
    {
5944
      gfc_init_se (&argse, se);
5945
 
5946
      /* Pass a NULL pointer for an absent arg.  */
5947
      if (actual->expr == NULL)
5948
        argse.expr = null_pointer_node;
5949
      else
5950
        {
5951
          gfc_typespec ts;
5952
          gfc_clear_ts (&ts);
5953
 
5954
          if (actual->expr->ts.kind != gfc_c_int_kind)
5955
            {
5956
              /* The arguments to SELECTED_REAL_KIND are INTEGER(4).  */
5957
              ts.type = BT_INTEGER;
5958
              ts.kind = gfc_c_int_kind;
5959
              gfc_convert_type (actual->expr, &ts, 2);
5960
            }
5961
          gfc_conv_expr_reference (&argse, actual->expr);
5962
        }
5963
 
5964
      gfc_add_block_to_block (&se->pre, &argse.pre);
5965
      gfc_add_block_to_block (&se->post, &argse.post);
5966
      VEC_safe_push (tree, gc, args, argse.expr);
5967
    }
5968
 
5969
  /* Convert it to the required type.  */
5970
  type = gfc_typenode_for_spec (&expr->ts);
5971
  se->expr = build_call_expr_loc_vec (input_location,
5972
                                      gfor_fndecl_sr_kind, args);
5973
  se->expr = fold_convert (type, se->expr);
5974
}
5975
 
5976
 
5977
/* Generate code for TRIM (A) intrinsic function.  */
5978
 
5979
static void
5980
gfc_conv_intrinsic_trim (gfc_se * se, gfc_expr * expr)
5981
{
5982
  tree var;
5983
  tree len;
5984
  tree addr;
5985
  tree tmp;
5986
  tree cond;
5987
  tree fndecl;
5988
  tree function;
5989
  tree *args;
5990
  unsigned int num_args;
5991
 
5992
  num_args = gfc_intrinsic_argument_list_length (expr) + 2;
5993
  args = XALLOCAVEC (tree, num_args);
5994
 
5995
  var = gfc_create_var (gfc_get_pchar_type (expr->ts.kind), "pstr");
5996
  addr = gfc_build_addr_expr (ppvoid_type_node, var);
5997
  len = gfc_create_var (gfc_charlen_type_node, "len");
5998
 
5999
  gfc_conv_intrinsic_function_args (se, expr, &args[2], num_args - 2);
6000
  args[0] = gfc_build_addr_expr (NULL_TREE, len);
6001
  args[1] = addr;
6002
 
6003
  if (expr->ts.kind == 1)
6004
    function = gfor_fndecl_string_trim;
6005
  else if (expr->ts.kind == 4)
6006
    function = gfor_fndecl_string_trim_char4;
6007
  else
6008
    gcc_unreachable ();
6009
 
6010
  fndecl = build_addr (function, current_function_decl);
6011
  tmp = build_call_array_loc (input_location,
6012
                          TREE_TYPE (TREE_TYPE (function)), fndecl,
6013
                          num_args, args);
6014
  gfc_add_expr_to_block (&se->pre, tmp);
6015
 
6016
  /* Free the temporary afterwards, if necessary.  */
6017
  cond = fold_build2_loc (input_location, GT_EXPR, boolean_type_node,
6018
                          len, build_int_cst (TREE_TYPE (len), 0));
6019
  tmp = gfc_call_free (var);
6020
  tmp = build3_v (COND_EXPR, cond, tmp, build_empty_stmt (input_location));
6021
  gfc_add_expr_to_block (&se->post, tmp);
6022
 
6023
  se->expr = var;
6024
  se->string_length = len;
6025
}
6026
 
6027
 
6028
/* Generate code for REPEAT (STRING, NCOPIES) intrinsic function.  */
6029
 
6030
static void
6031
gfc_conv_intrinsic_repeat (gfc_se * se, gfc_expr * expr)
6032
{
6033
  tree args[3], ncopies, dest, dlen, src, slen, ncopies_type;
6034
  tree type, cond, tmp, count, exit_label, n, max, largest;
6035
  tree size;
6036
  stmtblock_t block, body;
6037
  int i;
6038
 
6039
  /* We store in charsize the size of a character.  */
6040
  i = gfc_validate_kind (BT_CHARACTER, expr->ts.kind, false);
6041
  size = build_int_cst (size_type_node, gfc_character_kinds[i].bit_size / 8);
6042
 
6043
  /* Get the arguments.  */
6044
  gfc_conv_intrinsic_function_args (se, expr, args, 3);
6045
  slen = fold_convert (size_type_node, gfc_evaluate_now (args[0], &se->pre));
6046
  src = args[1];
6047
  ncopies = gfc_evaluate_now (args[2], &se->pre);
6048
  ncopies_type = TREE_TYPE (ncopies);
6049
 
6050
  /* Check that NCOPIES is not negative.  */
6051
  cond = fold_build2_loc (input_location, LT_EXPR, boolean_type_node, ncopies,
6052
                          build_int_cst (ncopies_type, 0));
6053
  gfc_trans_runtime_check (true, false, cond, &se->pre, &expr->where,
6054
                           "Argument NCOPIES of REPEAT intrinsic is negative "
6055
                           "(its value is %ld)",
6056
                           fold_convert (long_integer_type_node, ncopies));
6057
 
6058
  /* If the source length is zero, any non negative value of NCOPIES
6059
     is valid, and nothing happens.  */
6060
  n = gfc_create_var (ncopies_type, "ncopies");
6061
  cond = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node, slen,
6062
                          build_int_cst (size_type_node, 0));
6063
  tmp = fold_build3_loc (input_location, COND_EXPR, ncopies_type, cond,
6064
                         build_int_cst (ncopies_type, 0), ncopies);
6065
  gfc_add_modify (&se->pre, n, tmp);
6066
  ncopies = n;
6067
 
6068
  /* Check that ncopies is not too large: ncopies should be less than
6069
     (or equal to) MAX / slen, where MAX is the maximal integer of
6070
     the gfc_charlen_type_node type.  If slen == 0, we need a special
6071
     case to avoid the division by zero.  */
6072
  i = gfc_validate_kind (BT_INTEGER, gfc_charlen_int_kind, false);
6073
  max = gfc_conv_mpz_to_tree (gfc_integer_kinds[i].huge, gfc_charlen_int_kind);
6074
  max = fold_build2_loc (input_location, TRUNC_DIV_EXPR, size_type_node,
6075
                          fold_convert (size_type_node, max), slen);
6076
  largest = TYPE_PRECISION (size_type_node) > TYPE_PRECISION (ncopies_type)
6077
              ? size_type_node : ncopies_type;
6078
  cond = fold_build2_loc (input_location, GT_EXPR, boolean_type_node,
6079
                          fold_convert (largest, ncopies),
6080
                          fold_convert (largest, max));
6081
  tmp = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node, slen,
6082
                         build_int_cst (size_type_node, 0));
6083
  cond = fold_build3_loc (input_location, COND_EXPR, boolean_type_node, tmp,
6084
                          boolean_false_node, cond);
6085
  gfc_trans_runtime_check (true, false, cond, &se->pre, &expr->where,
6086
                           "Argument NCOPIES of REPEAT intrinsic is too large");
6087
 
6088
  /* Compute the destination length.  */
6089
  dlen = fold_build2_loc (input_location, MULT_EXPR, gfc_charlen_type_node,
6090
                          fold_convert (gfc_charlen_type_node, slen),
6091
                          fold_convert (gfc_charlen_type_node, ncopies));
6092
  type = gfc_get_character_type (expr->ts.kind, expr->ts.u.cl);
6093
  dest = gfc_conv_string_tmp (se, build_pointer_type (type), dlen);
6094
 
6095
  /* Generate the code to do the repeat operation:
6096
       for (i = 0; i < ncopies; i++)
6097
         memmove (dest + (i * slen * size), src, slen*size);  */
6098
  gfc_start_block (&block);
6099
  count = gfc_create_var (ncopies_type, "count");
6100
  gfc_add_modify (&block, count, build_int_cst (ncopies_type, 0));
6101
  exit_label = gfc_build_label_decl (NULL_TREE);
6102
 
6103
  /* Start the loop body.  */
6104
  gfc_start_block (&body);
6105
 
6106
  /* Exit the loop if count >= ncopies.  */
6107
  cond = fold_build2_loc (input_location, GE_EXPR, boolean_type_node, count,
6108
                          ncopies);
6109
  tmp = build1_v (GOTO_EXPR, exit_label);
6110
  TREE_USED (exit_label) = 1;
6111
  tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node, cond, tmp,
6112
                         build_empty_stmt (input_location));
6113
  gfc_add_expr_to_block (&body, tmp);
6114
 
6115
  /* Call memmove (dest + (i*slen*size), src, slen*size).  */
6116
  tmp = fold_build2_loc (input_location, MULT_EXPR, gfc_charlen_type_node,
6117
                         fold_convert (gfc_charlen_type_node, slen),
6118
                         fold_convert (gfc_charlen_type_node, count));
6119
  tmp = fold_build2_loc (input_location, MULT_EXPR, gfc_charlen_type_node,
6120
                         tmp, fold_convert (gfc_charlen_type_node, size));
6121
  tmp = fold_build_pointer_plus_loc (input_location,
6122
                                     fold_convert (pvoid_type_node, dest), tmp);
6123
  tmp = build_call_expr_loc (input_location,
6124
                             builtin_decl_explicit (BUILT_IN_MEMMOVE),
6125
                             3, tmp, src,
6126
                             fold_build2_loc (input_location, MULT_EXPR,
6127
                                              size_type_node, slen,
6128
                                              fold_convert (size_type_node,
6129
                                                            size)));
6130
  gfc_add_expr_to_block (&body, tmp);
6131
 
6132
  /* Increment count.  */
6133
  tmp = fold_build2_loc (input_location, PLUS_EXPR, ncopies_type,
6134
                         count, build_int_cst (TREE_TYPE (count), 1));
6135
  gfc_add_modify (&body, count, tmp);
6136
 
6137
  /* Build the loop.  */
6138
  tmp = build1_v (LOOP_EXPR, gfc_finish_block (&body));
6139
  gfc_add_expr_to_block (&block, tmp);
6140
 
6141
  /* Add the exit label.  */
6142
  tmp = build1_v (LABEL_EXPR, exit_label);
6143
  gfc_add_expr_to_block (&block, tmp);
6144
 
6145
  /* Finish the block.  */
6146
  tmp = gfc_finish_block (&block);
6147
  gfc_add_expr_to_block (&se->pre, tmp);
6148
 
6149
  /* Set the result value.  */
6150
  se->expr = dest;
6151
  se->string_length = dlen;
6152
}
6153
 
6154
 
6155
/* Generate code for the IARGC intrinsic.  */
6156
 
6157
static void
6158
gfc_conv_intrinsic_iargc (gfc_se * se, gfc_expr * expr)
6159
{
6160
  tree tmp;
6161
  tree fndecl;
6162
  tree type;
6163
 
6164
  /* Call the library function.  This always returns an INTEGER(4).  */
6165
  fndecl = gfor_fndecl_iargc;
6166
  tmp = build_call_expr_loc (input_location,
6167
                         fndecl, 0);
6168
 
6169
  /* Convert it to the required type.  */
6170
  type = gfc_typenode_for_spec (&expr->ts);
6171
  tmp = fold_convert (type, tmp);
6172
 
6173
  se->expr = tmp;
6174
}
6175
 
6176
 
6177
/* The loc intrinsic returns the address of its argument as
6178
   gfc_index_integer_kind integer.  */
6179
 
6180
static void
6181
gfc_conv_intrinsic_loc (gfc_se * se, gfc_expr * expr)
6182
{
6183
  tree temp_var;
6184
  gfc_expr *arg_expr;
6185
  gfc_ss *ss;
6186
 
6187
  gcc_assert (!se->ss);
6188
 
6189
  arg_expr = expr->value.function.actual->expr;
6190
  ss = gfc_walk_expr (arg_expr);
6191
  if (ss == gfc_ss_terminator)
6192
    gfc_conv_expr_reference (se, arg_expr);
6193
  else
6194
    gfc_conv_array_parameter (se, arg_expr, ss, true, NULL, NULL, NULL);
6195
  se->expr= convert (gfc_get_int_type (gfc_index_integer_kind), se->expr);
6196
 
6197
  /* Create a temporary variable for loc return value.  Without this,
6198
     we get an error an ICE in gcc/expr.c(expand_expr_addr_expr_1).  */
6199
  temp_var = gfc_create_var (gfc_get_int_type (gfc_index_integer_kind), NULL);
6200
  gfc_add_modify (&se->pre, temp_var, se->expr);
6201
  se->expr = temp_var;
6202
}
6203
 
6204
/* Generate code for an intrinsic function.  Some map directly to library
6205
   calls, others get special handling.  In some cases the name of the function
6206
   used depends on the type specifiers.  */
6207
 
6208
void
6209
gfc_conv_intrinsic_function (gfc_se * se, gfc_expr * expr)
6210
{
6211
  const char *name;
6212
  int lib, kind;
6213
  tree fndecl;
6214
 
6215
  name = &expr->value.function.name[2];
6216
 
6217
  if (expr->rank > 0)
6218
    {
6219
      lib = gfc_is_intrinsic_libcall (expr);
6220
      if (lib != 0)
6221
        {
6222
          if (lib == 1)
6223
            se->ignore_optional = 1;
6224
 
6225
          switch (expr->value.function.isym->id)
6226
            {
6227
            case GFC_ISYM_EOSHIFT:
6228
            case GFC_ISYM_PACK:
6229
            case GFC_ISYM_RESHAPE:
6230
              /* For all of those the first argument specifies the type and the
6231
                 third is optional.  */
6232
              conv_generic_with_optional_char_arg (se, expr, 1, 3);
6233
              break;
6234
 
6235
            default:
6236
              gfc_conv_intrinsic_funcall (se, expr);
6237
              break;
6238
            }
6239
 
6240
          return;
6241
        }
6242
    }
6243
 
6244
  switch (expr->value.function.isym->id)
6245
    {
6246
    case GFC_ISYM_NONE:
6247
      gcc_unreachable ();
6248
 
6249
    case GFC_ISYM_REPEAT:
6250
      gfc_conv_intrinsic_repeat (se, expr);
6251
      break;
6252
 
6253
    case GFC_ISYM_TRIM:
6254
      gfc_conv_intrinsic_trim (se, expr);
6255
      break;
6256
 
6257
    case GFC_ISYM_SC_KIND:
6258
      gfc_conv_intrinsic_sc_kind (se, expr);
6259
      break;
6260
 
6261
    case GFC_ISYM_SI_KIND:
6262
      gfc_conv_intrinsic_si_kind (se, expr);
6263
      break;
6264
 
6265
    case GFC_ISYM_SR_KIND:
6266
      gfc_conv_intrinsic_sr_kind (se, expr);
6267
      break;
6268
 
6269
    case GFC_ISYM_EXPONENT:
6270
      gfc_conv_intrinsic_exponent (se, expr);
6271
      break;
6272
 
6273
    case GFC_ISYM_SCAN:
6274
      kind = expr->value.function.actual->expr->ts.kind;
6275
      if (kind == 1)
6276
       fndecl = gfor_fndecl_string_scan;
6277
      else if (kind == 4)
6278
       fndecl = gfor_fndecl_string_scan_char4;
6279
      else
6280
       gcc_unreachable ();
6281
 
6282
      gfc_conv_intrinsic_index_scan_verify (se, expr, fndecl);
6283
      break;
6284
 
6285
    case GFC_ISYM_VERIFY:
6286
      kind = expr->value.function.actual->expr->ts.kind;
6287
      if (kind == 1)
6288
       fndecl = gfor_fndecl_string_verify;
6289
      else if (kind == 4)
6290
       fndecl = gfor_fndecl_string_verify_char4;
6291
      else
6292
       gcc_unreachable ();
6293
 
6294
      gfc_conv_intrinsic_index_scan_verify (se, expr, fndecl);
6295
      break;
6296
 
6297
    case GFC_ISYM_ALLOCATED:
6298
      gfc_conv_allocated (se, expr);
6299
      break;
6300
 
6301
    case GFC_ISYM_ASSOCIATED:
6302
      gfc_conv_associated(se, expr);
6303
      break;
6304
 
6305
    case GFC_ISYM_SAME_TYPE_AS:
6306
      gfc_conv_same_type_as (se, expr);
6307
      break;
6308
 
6309
    case GFC_ISYM_ABS:
6310
      gfc_conv_intrinsic_abs (se, expr);
6311
      break;
6312
 
6313
    case GFC_ISYM_ADJUSTL:
6314
      if (expr->ts.kind == 1)
6315
       fndecl = gfor_fndecl_adjustl;
6316
      else if (expr->ts.kind == 4)
6317
       fndecl = gfor_fndecl_adjustl_char4;
6318
      else
6319
       gcc_unreachable ();
6320
 
6321
      gfc_conv_intrinsic_adjust (se, expr, fndecl);
6322
      break;
6323
 
6324
    case GFC_ISYM_ADJUSTR:
6325
      if (expr->ts.kind == 1)
6326
       fndecl = gfor_fndecl_adjustr;
6327
      else if (expr->ts.kind == 4)
6328
       fndecl = gfor_fndecl_adjustr_char4;
6329
      else
6330
       gcc_unreachable ();
6331
 
6332
      gfc_conv_intrinsic_adjust (se, expr, fndecl);
6333
      break;
6334
 
6335
    case GFC_ISYM_AIMAG:
6336
      gfc_conv_intrinsic_imagpart (se, expr);
6337
      break;
6338
 
6339
    case GFC_ISYM_AINT:
6340
      gfc_conv_intrinsic_aint (se, expr, RND_TRUNC);
6341
      break;
6342
 
6343
    case GFC_ISYM_ALL:
6344
      gfc_conv_intrinsic_anyall (se, expr, EQ_EXPR);
6345
      break;
6346
 
6347
    case GFC_ISYM_ANINT:
6348
      gfc_conv_intrinsic_aint (se, expr, RND_ROUND);
6349
      break;
6350
 
6351
    case GFC_ISYM_AND:
6352
      gfc_conv_intrinsic_bitop (se, expr, BIT_AND_EXPR);
6353
      break;
6354
 
6355
    case GFC_ISYM_ANY:
6356
      gfc_conv_intrinsic_anyall (se, expr, NE_EXPR);
6357
      break;
6358
 
6359
    case GFC_ISYM_BTEST:
6360
      gfc_conv_intrinsic_btest (se, expr);
6361
      break;
6362
 
6363
    case GFC_ISYM_BGE:
6364
      gfc_conv_intrinsic_bitcomp (se, expr, GE_EXPR);
6365
      break;
6366
 
6367
    case GFC_ISYM_BGT:
6368
      gfc_conv_intrinsic_bitcomp (se, expr, GT_EXPR);
6369
      break;
6370
 
6371
    case GFC_ISYM_BLE:
6372
      gfc_conv_intrinsic_bitcomp (se, expr, LE_EXPR);
6373
      break;
6374
 
6375
    case GFC_ISYM_BLT:
6376
      gfc_conv_intrinsic_bitcomp (se, expr, LT_EXPR);
6377
      break;
6378
 
6379
    case GFC_ISYM_ACHAR:
6380
    case GFC_ISYM_CHAR:
6381
      gfc_conv_intrinsic_char (se, expr);
6382
      break;
6383
 
6384
    case GFC_ISYM_CONVERSION:
6385
    case GFC_ISYM_REAL:
6386
    case GFC_ISYM_LOGICAL:
6387
    case GFC_ISYM_DBLE:
6388
      gfc_conv_intrinsic_conversion (se, expr);
6389
      break;
6390
 
6391
      /* Integer conversions are handled separately to make sure we get the
6392
         correct rounding mode.  */
6393
    case GFC_ISYM_INT:
6394
    case GFC_ISYM_INT2:
6395
    case GFC_ISYM_INT8:
6396
    case GFC_ISYM_LONG:
6397
      gfc_conv_intrinsic_int (se, expr, RND_TRUNC);
6398
      break;
6399
 
6400
    case GFC_ISYM_NINT:
6401
      gfc_conv_intrinsic_int (se, expr, RND_ROUND);
6402
      break;
6403
 
6404
    case GFC_ISYM_CEILING:
6405
      gfc_conv_intrinsic_int (se, expr, RND_CEIL);
6406
      break;
6407
 
6408
    case GFC_ISYM_FLOOR:
6409
      gfc_conv_intrinsic_int (se, expr, RND_FLOOR);
6410
      break;
6411
 
6412
    case GFC_ISYM_MOD:
6413
      gfc_conv_intrinsic_mod (se, expr, 0);
6414
      break;
6415
 
6416
    case GFC_ISYM_MODULO:
6417
      gfc_conv_intrinsic_mod (se, expr, 1);
6418
      break;
6419
 
6420
    case GFC_ISYM_CMPLX:
6421
      gfc_conv_intrinsic_cmplx (se, expr, name[5] == '1');
6422
      break;
6423
 
6424
    case GFC_ISYM_COMMAND_ARGUMENT_COUNT:
6425
      gfc_conv_intrinsic_iargc (se, expr);
6426
      break;
6427
 
6428
    case GFC_ISYM_COMPLEX:
6429
      gfc_conv_intrinsic_cmplx (se, expr, 1);
6430
      break;
6431
 
6432
    case GFC_ISYM_CONJG:
6433
      gfc_conv_intrinsic_conjg (se, expr);
6434
      break;
6435
 
6436
    case GFC_ISYM_COUNT:
6437
      gfc_conv_intrinsic_count (se, expr);
6438
      break;
6439
 
6440
    case GFC_ISYM_CTIME:
6441
      gfc_conv_intrinsic_ctime (se, expr);
6442
      break;
6443
 
6444
    case GFC_ISYM_DIM:
6445
      gfc_conv_intrinsic_dim (se, expr);
6446
      break;
6447
 
6448
    case GFC_ISYM_DOT_PRODUCT:
6449
      gfc_conv_intrinsic_dot_product (se, expr);
6450
      break;
6451
 
6452
    case GFC_ISYM_DPROD:
6453
      gfc_conv_intrinsic_dprod (se, expr);
6454
      break;
6455
 
6456
    case GFC_ISYM_DSHIFTL:
6457
      gfc_conv_intrinsic_dshift (se, expr, true);
6458
      break;
6459
 
6460
    case GFC_ISYM_DSHIFTR:
6461
      gfc_conv_intrinsic_dshift (se, expr, false);
6462
      break;
6463
 
6464
    case GFC_ISYM_FDATE:
6465
      gfc_conv_intrinsic_fdate (se, expr);
6466
      break;
6467
 
6468
    case GFC_ISYM_FRACTION:
6469
      gfc_conv_intrinsic_fraction (se, expr);
6470
      break;
6471
 
6472
    case GFC_ISYM_IALL:
6473
      gfc_conv_intrinsic_arith (se, expr, BIT_AND_EXPR, false);
6474
      break;
6475
 
6476
    case GFC_ISYM_IAND:
6477
      gfc_conv_intrinsic_bitop (se, expr, BIT_AND_EXPR);
6478
      break;
6479
 
6480
    case GFC_ISYM_IANY:
6481
      gfc_conv_intrinsic_arith (se, expr, BIT_IOR_EXPR, false);
6482
      break;
6483
 
6484
    case GFC_ISYM_IBCLR:
6485
      gfc_conv_intrinsic_singlebitop (se, expr, 0);
6486
      break;
6487
 
6488
    case GFC_ISYM_IBITS:
6489
      gfc_conv_intrinsic_ibits (se, expr);
6490
      break;
6491
 
6492
    case GFC_ISYM_IBSET:
6493
      gfc_conv_intrinsic_singlebitop (se, expr, 1);
6494
      break;
6495
 
6496
    case GFC_ISYM_IACHAR:
6497
    case GFC_ISYM_ICHAR:
6498
      /* We assume ASCII character sequence.  */
6499
      gfc_conv_intrinsic_ichar (se, expr);
6500
      break;
6501
 
6502
    case GFC_ISYM_IARGC:
6503
      gfc_conv_intrinsic_iargc (se, expr);
6504
      break;
6505
 
6506
    case GFC_ISYM_IEOR:
6507
      gfc_conv_intrinsic_bitop (se, expr, BIT_XOR_EXPR);
6508
      break;
6509
 
6510
    case GFC_ISYM_INDEX:
6511
      kind = expr->value.function.actual->expr->ts.kind;
6512
      if (kind == 1)
6513
       fndecl = gfor_fndecl_string_index;
6514
      else if (kind == 4)
6515
       fndecl = gfor_fndecl_string_index_char4;
6516
      else
6517
       gcc_unreachable ();
6518
 
6519
      gfc_conv_intrinsic_index_scan_verify (se, expr, fndecl);
6520
      break;
6521
 
6522
    case GFC_ISYM_IOR:
6523
      gfc_conv_intrinsic_bitop (se, expr, BIT_IOR_EXPR);
6524
      break;
6525
 
6526
    case GFC_ISYM_IPARITY:
6527
      gfc_conv_intrinsic_arith (se, expr, BIT_XOR_EXPR, false);
6528
      break;
6529
 
6530
    case GFC_ISYM_IS_IOSTAT_END:
6531
      gfc_conv_has_intvalue (se, expr, LIBERROR_END);
6532
      break;
6533
 
6534
    case GFC_ISYM_IS_IOSTAT_EOR:
6535
      gfc_conv_has_intvalue (se, expr, LIBERROR_EOR);
6536
      break;
6537
 
6538
    case GFC_ISYM_ISNAN:
6539
      gfc_conv_intrinsic_isnan (se, expr);
6540
      break;
6541
 
6542
    case GFC_ISYM_LSHIFT:
6543
      gfc_conv_intrinsic_shift (se, expr, false, false);
6544
      break;
6545
 
6546
    case GFC_ISYM_RSHIFT:
6547
      gfc_conv_intrinsic_shift (se, expr, true, true);
6548
      break;
6549
 
6550
    case GFC_ISYM_SHIFTA:
6551
      gfc_conv_intrinsic_shift (se, expr, true, true);
6552
      break;
6553
 
6554
    case GFC_ISYM_SHIFTL:
6555
      gfc_conv_intrinsic_shift (se, expr, false, false);
6556
      break;
6557
 
6558
    case GFC_ISYM_SHIFTR:
6559
      gfc_conv_intrinsic_shift (se, expr, true, false);
6560
      break;
6561
 
6562
    case GFC_ISYM_ISHFT:
6563
      gfc_conv_intrinsic_ishft (se, expr);
6564
      break;
6565
 
6566
    case GFC_ISYM_ISHFTC:
6567
      gfc_conv_intrinsic_ishftc (se, expr);
6568
      break;
6569
 
6570
    case GFC_ISYM_LEADZ:
6571
      gfc_conv_intrinsic_leadz (se, expr);
6572
      break;
6573
 
6574
    case GFC_ISYM_TRAILZ:
6575
      gfc_conv_intrinsic_trailz (se, expr);
6576
      break;
6577
 
6578
    case GFC_ISYM_POPCNT:
6579
      gfc_conv_intrinsic_popcnt_poppar (se, expr, 0);
6580
      break;
6581
 
6582
    case GFC_ISYM_POPPAR:
6583
      gfc_conv_intrinsic_popcnt_poppar (se, expr, 1);
6584
      break;
6585
 
6586
    case GFC_ISYM_LBOUND:
6587
      gfc_conv_intrinsic_bound (se, expr, 0);
6588
      break;
6589
 
6590
    case GFC_ISYM_LCOBOUND:
6591
      conv_intrinsic_cobound (se, expr);
6592
      break;
6593
 
6594
    case GFC_ISYM_TRANSPOSE:
6595
      /* The scalarizer has already been set up for reversed dimension access
6596
         order ; now we just get the argument value normally.  */
6597
      gfc_conv_expr (se, expr->value.function.actual->expr);
6598
      break;
6599
 
6600
    case GFC_ISYM_LEN:
6601
      gfc_conv_intrinsic_len (se, expr);
6602
      break;
6603
 
6604
    case GFC_ISYM_LEN_TRIM:
6605
      gfc_conv_intrinsic_len_trim (se, expr);
6606
      break;
6607
 
6608
    case GFC_ISYM_LGE:
6609
      gfc_conv_intrinsic_strcmp (se, expr, GE_EXPR);
6610
      break;
6611
 
6612
    case GFC_ISYM_LGT:
6613
      gfc_conv_intrinsic_strcmp (se, expr, GT_EXPR);
6614
      break;
6615
 
6616
    case GFC_ISYM_LLE:
6617
      gfc_conv_intrinsic_strcmp (se, expr, LE_EXPR);
6618
      break;
6619
 
6620
    case GFC_ISYM_LLT:
6621
      gfc_conv_intrinsic_strcmp (se, expr, LT_EXPR);
6622
      break;
6623
 
6624
    case GFC_ISYM_MASKL:
6625
      gfc_conv_intrinsic_mask (se, expr, 1);
6626
      break;
6627
 
6628
    case GFC_ISYM_MASKR:
6629
      gfc_conv_intrinsic_mask (se, expr, 0);
6630
      break;
6631
 
6632
    case GFC_ISYM_MAX:
6633
      if (expr->ts.type == BT_CHARACTER)
6634
        gfc_conv_intrinsic_minmax_char (se, expr, 1);
6635
      else
6636
        gfc_conv_intrinsic_minmax (se, expr, GT_EXPR);
6637
      break;
6638
 
6639
    case GFC_ISYM_MAXLOC:
6640
      gfc_conv_intrinsic_minmaxloc (se, expr, GT_EXPR);
6641
      break;
6642
 
6643
    case GFC_ISYM_MAXVAL:
6644
      gfc_conv_intrinsic_minmaxval (se, expr, GT_EXPR);
6645
      break;
6646
 
6647
    case GFC_ISYM_MERGE:
6648
      gfc_conv_intrinsic_merge (se, expr);
6649
      break;
6650
 
6651
    case GFC_ISYM_MERGE_BITS:
6652
      gfc_conv_intrinsic_merge_bits (se, expr);
6653
      break;
6654
 
6655
    case GFC_ISYM_MIN:
6656
      if (expr->ts.type == BT_CHARACTER)
6657
        gfc_conv_intrinsic_minmax_char (se, expr, -1);
6658
      else
6659
        gfc_conv_intrinsic_minmax (se, expr, LT_EXPR);
6660
      break;
6661
 
6662
    case GFC_ISYM_MINLOC:
6663
      gfc_conv_intrinsic_minmaxloc (se, expr, LT_EXPR);
6664
      break;
6665
 
6666
    case GFC_ISYM_MINVAL:
6667
      gfc_conv_intrinsic_minmaxval (se, expr, LT_EXPR);
6668
      break;
6669
 
6670
    case GFC_ISYM_NEAREST:
6671
      gfc_conv_intrinsic_nearest (se, expr);
6672
      break;
6673
 
6674
    case GFC_ISYM_NORM2:
6675
      gfc_conv_intrinsic_arith (se, expr, PLUS_EXPR, true);
6676
      break;
6677
 
6678
    case GFC_ISYM_NOT:
6679
      gfc_conv_intrinsic_not (se, expr);
6680
      break;
6681
 
6682
    case GFC_ISYM_OR:
6683
      gfc_conv_intrinsic_bitop (se, expr, BIT_IOR_EXPR);
6684
      break;
6685
 
6686
    case GFC_ISYM_PARITY:
6687
      gfc_conv_intrinsic_arith (se, expr, NE_EXPR, false);
6688
      break;
6689
 
6690
    case GFC_ISYM_PRESENT:
6691
      gfc_conv_intrinsic_present (se, expr);
6692
      break;
6693
 
6694
    case GFC_ISYM_PRODUCT:
6695
      gfc_conv_intrinsic_arith (se, expr, MULT_EXPR, false);
6696
      break;
6697
 
6698
    case GFC_ISYM_RRSPACING:
6699
      gfc_conv_intrinsic_rrspacing (se, expr);
6700
      break;
6701
 
6702
    case GFC_ISYM_SET_EXPONENT:
6703
      gfc_conv_intrinsic_set_exponent (se, expr);
6704
      break;
6705
 
6706
    case GFC_ISYM_SCALE:
6707
      gfc_conv_intrinsic_scale (se, expr);
6708
      break;
6709
 
6710
    case GFC_ISYM_SIGN:
6711
      gfc_conv_intrinsic_sign (se, expr);
6712
      break;
6713
 
6714
    case GFC_ISYM_SIZE:
6715
      gfc_conv_intrinsic_size (se, expr);
6716
      break;
6717
 
6718
    case GFC_ISYM_SIZEOF:
6719
    case GFC_ISYM_C_SIZEOF:
6720
      gfc_conv_intrinsic_sizeof (se, expr);
6721
      break;
6722
 
6723
    case GFC_ISYM_STORAGE_SIZE:
6724
      gfc_conv_intrinsic_storage_size (se, expr);
6725
      break;
6726
 
6727
    case GFC_ISYM_SPACING:
6728
      gfc_conv_intrinsic_spacing (se, expr);
6729
      break;
6730
 
6731
    case GFC_ISYM_SUM:
6732
      gfc_conv_intrinsic_arith (se, expr, PLUS_EXPR, false);
6733
      break;
6734
 
6735
    case GFC_ISYM_TRANSFER:
6736
      if (se->ss && se->ss->info->useflags)
6737
        /* Access the previously obtained result.  */
6738
        gfc_conv_tmp_array_ref (se);
6739
      else
6740
        gfc_conv_intrinsic_transfer (se, expr);
6741
      break;
6742
 
6743
    case GFC_ISYM_TTYNAM:
6744
      gfc_conv_intrinsic_ttynam (se, expr);
6745
      break;
6746
 
6747
    case GFC_ISYM_UBOUND:
6748
      gfc_conv_intrinsic_bound (se, expr, 1);
6749
      break;
6750
 
6751
    case GFC_ISYM_UCOBOUND:
6752
      conv_intrinsic_cobound (se, expr);
6753
      break;
6754
 
6755
    case GFC_ISYM_XOR:
6756
      gfc_conv_intrinsic_bitop (se, expr, BIT_XOR_EXPR);
6757
      break;
6758
 
6759
    case GFC_ISYM_LOC:
6760
      gfc_conv_intrinsic_loc (se, expr);
6761
      break;
6762
 
6763
    case GFC_ISYM_THIS_IMAGE:
6764
      /* For num_images() == 1, handle as LCOBOUND.  */
6765
      if (expr->value.function.actual->expr
6766
          && gfc_option.coarray == GFC_FCOARRAY_SINGLE)
6767
        conv_intrinsic_cobound (se, expr);
6768
      else
6769
        trans_this_image (se, expr);
6770
      break;
6771
 
6772
    case GFC_ISYM_IMAGE_INDEX:
6773
      trans_image_index (se, expr);
6774
      break;
6775
 
6776
    case GFC_ISYM_NUM_IMAGES:
6777
      trans_num_images (se);
6778
      break;
6779
 
6780
    case GFC_ISYM_ACCESS:
6781
    case GFC_ISYM_CHDIR:
6782
    case GFC_ISYM_CHMOD:
6783
    case GFC_ISYM_DTIME:
6784
    case GFC_ISYM_ETIME:
6785
    case GFC_ISYM_EXTENDS_TYPE_OF:
6786
    case GFC_ISYM_FGET:
6787
    case GFC_ISYM_FGETC:
6788
    case GFC_ISYM_FNUM:
6789
    case GFC_ISYM_FPUT:
6790
    case GFC_ISYM_FPUTC:
6791
    case GFC_ISYM_FSTAT:
6792
    case GFC_ISYM_FTELL:
6793
    case GFC_ISYM_GETCWD:
6794
    case GFC_ISYM_GETGID:
6795
    case GFC_ISYM_GETPID:
6796
    case GFC_ISYM_GETUID:
6797
    case GFC_ISYM_HOSTNM:
6798
    case GFC_ISYM_KILL:
6799
    case GFC_ISYM_IERRNO:
6800
    case GFC_ISYM_IRAND:
6801
    case GFC_ISYM_ISATTY:
6802
    case GFC_ISYM_JN2:
6803
    case GFC_ISYM_LINK:
6804
    case GFC_ISYM_LSTAT:
6805
    case GFC_ISYM_MALLOC:
6806
    case GFC_ISYM_MATMUL:
6807
    case GFC_ISYM_MCLOCK:
6808
    case GFC_ISYM_MCLOCK8:
6809
    case GFC_ISYM_RAND:
6810
    case GFC_ISYM_RENAME:
6811
    case GFC_ISYM_SECOND:
6812
    case GFC_ISYM_SECNDS:
6813
    case GFC_ISYM_SIGNAL:
6814
    case GFC_ISYM_STAT:
6815
    case GFC_ISYM_SYMLNK:
6816
    case GFC_ISYM_SYSTEM:
6817
    case GFC_ISYM_TIME:
6818
    case GFC_ISYM_TIME8:
6819
    case GFC_ISYM_UMASK:
6820
    case GFC_ISYM_UNLINK:
6821
    case GFC_ISYM_YN2:
6822
      gfc_conv_intrinsic_funcall (se, expr);
6823
      break;
6824
 
6825
    case GFC_ISYM_EOSHIFT:
6826
    case GFC_ISYM_PACK:
6827
    case GFC_ISYM_RESHAPE:
6828
      /* For those, expr->rank should always be >0 and thus the if above the
6829
         switch should have matched.  */
6830
      gcc_unreachable ();
6831
      break;
6832
 
6833
    default:
6834
      gfc_conv_intrinsic_lib_function (se, expr);
6835
      break;
6836
    }
6837
}
6838
 
6839
 
6840
static gfc_ss *
6841
walk_inline_intrinsic_transpose (gfc_ss *ss, gfc_expr *expr)
6842
{
6843
  gfc_ss *arg_ss, *tmp_ss;
6844
  gfc_actual_arglist *arg;
6845
 
6846
  arg = expr->value.function.actual;
6847
 
6848
  gcc_assert (arg->expr);
6849
 
6850
  arg_ss = gfc_walk_subexpr (gfc_ss_terminator, arg->expr);
6851
  gcc_assert (arg_ss != gfc_ss_terminator);
6852
 
6853
  for (tmp_ss = arg_ss; ; tmp_ss = tmp_ss->next)
6854
    {
6855
      if (tmp_ss->info->type != GFC_SS_SCALAR
6856
          && tmp_ss->info->type != GFC_SS_REFERENCE)
6857
        {
6858
          int tmp_dim;
6859
 
6860
          gcc_assert (tmp_ss->dimen == 2);
6861
 
6862
          /* We just invert dimensions.  */
6863
          tmp_dim = tmp_ss->dim[0];
6864
          tmp_ss->dim[0] = tmp_ss->dim[1];
6865
          tmp_ss->dim[1] = tmp_dim;
6866
        }
6867
 
6868
      /* Stop when tmp_ss points to the last valid element of the chain...  */
6869
      if (tmp_ss->next == gfc_ss_terminator)
6870
        break;
6871
    }
6872
 
6873
  /* ... so that we can attach the rest of the chain to it.  */
6874
  tmp_ss->next = ss;
6875
 
6876
  return arg_ss;
6877
}
6878
 
6879
 
6880
/* Move the given dimension of the given gfc_ss list to a nested gfc_ss list.
6881
   This has the side effect of reversing the nested list, so there is no
6882
   need to call gfc_reverse_ss on it (the given list is assumed not to be
6883
   reversed yet).   */
6884
 
6885
static gfc_ss *
6886
nest_loop_dimension (gfc_ss *ss, int dim)
6887
{
6888
  int ss_dim, i;
6889
  gfc_ss *new_ss, *prev_ss = gfc_ss_terminator;
6890
  gfc_loopinfo *new_loop;
6891
 
6892
  gcc_assert (ss != gfc_ss_terminator);
6893
 
6894
  for (; ss != gfc_ss_terminator; ss = ss->next)
6895
    {
6896
      new_ss = gfc_get_ss ();
6897
      new_ss->next = prev_ss;
6898
      new_ss->parent = ss;
6899
      new_ss->info = ss->info;
6900
      new_ss->info->refcount++;
6901
      if (ss->dimen != 0)
6902
        {
6903
          gcc_assert (ss->info->type != GFC_SS_SCALAR
6904
                      && ss->info->type != GFC_SS_REFERENCE);
6905
 
6906
          new_ss->dimen = 1;
6907
          new_ss->dim[0] = ss->dim[dim];
6908
 
6909
          gcc_assert (dim < ss->dimen);
6910
 
6911
          ss_dim = --ss->dimen;
6912
          for (i = dim; i < ss_dim; i++)
6913
            ss->dim[i] = ss->dim[i + 1];
6914
 
6915
          ss->dim[ss_dim] = 0;
6916
        }
6917
      prev_ss = new_ss;
6918
 
6919
      if (ss->nested_ss)
6920
        {
6921
          ss->nested_ss->parent = new_ss;
6922
          new_ss->nested_ss = ss->nested_ss;
6923
        }
6924
      ss->nested_ss = new_ss;
6925
    }
6926
 
6927
  new_loop = gfc_get_loopinfo ();
6928
  gfc_init_loopinfo (new_loop);
6929
 
6930
  gcc_assert (prev_ss != NULL);
6931
  gcc_assert (prev_ss != gfc_ss_terminator);
6932
  gfc_add_ss_to_loop (new_loop, prev_ss);
6933
  return new_ss->parent;
6934
}
6935
 
6936
 
6937
/* Create the gfc_ss list for the SUM/PRODUCT arguments when the function
6938
   is to be inlined.  */
6939
 
6940
static gfc_ss *
6941
walk_inline_intrinsic_arith (gfc_ss *ss, gfc_expr *expr)
6942
{
6943
  gfc_ss *tmp_ss, *tail, *array_ss;
6944
  gfc_actual_arglist *arg1, *arg2, *arg3;
6945
  int sum_dim;
6946
  bool scalar_mask = false;
6947
 
6948
  /* The rank of the result will be determined later.  */
6949
  arg1 = expr->value.function.actual;
6950
  arg2 = arg1->next;
6951
  arg3 = arg2->next;
6952
  gcc_assert (arg3 != NULL);
6953
 
6954
  if (expr->rank == 0)
6955
    return ss;
6956
 
6957
  tmp_ss = gfc_ss_terminator;
6958
 
6959
  if (arg3->expr)
6960
    {
6961
      gfc_ss *mask_ss;
6962
 
6963
      mask_ss = gfc_walk_subexpr (tmp_ss, arg3->expr);
6964
      if (mask_ss == tmp_ss)
6965
        scalar_mask = 1;
6966
 
6967
      tmp_ss = mask_ss;
6968
    }
6969
 
6970
  array_ss = gfc_walk_subexpr (tmp_ss, arg1->expr);
6971
  gcc_assert (array_ss != tmp_ss);
6972
 
6973
  /* Odd thing: If the mask is scalar, it is used by the frontend after
6974
     the array (to make an if around the nested loop). Thus it shall
6975
     be after array_ss once the gfc_ss list is reversed.  */
6976
  if (scalar_mask)
6977
    tmp_ss = gfc_get_scalar_ss (array_ss, arg3->expr);
6978
  else
6979
    tmp_ss = array_ss;
6980
 
6981
  /* "Hide" the dimension on which we will sum in the first arg's scalarization
6982
     chain.  */
6983
  sum_dim = mpz_get_si (arg2->expr->value.integer) - 1;
6984
  tail = nest_loop_dimension (tmp_ss, sum_dim);
6985
  tail->next = ss;
6986
 
6987
  return tmp_ss;
6988
}
6989
 
6990
 
6991
static gfc_ss *
6992
walk_inline_intrinsic_function (gfc_ss * ss, gfc_expr * expr)
6993
{
6994
 
6995
  switch (expr->value.function.isym->id)
6996
    {
6997
      case GFC_ISYM_PRODUCT:
6998
      case GFC_ISYM_SUM:
6999
        return walk_inline_intrinsic_arith (ss, expr);
7000
 
7001
      case GFC_ISYM_TRANSPOSE:
7002
        return walk_inline_intrinsic_transpose (ss, expr);
7003
 
7004
      default:
7005
        gcc_unreachable ();
7006
    }
7007
  gcc_unreachable ();
7008
}
7009
 
7010
 
7011
/* This generates code to execute before entering the scalarization loop.
7012
   Currently does nothing.  */
7013
 
7014
void
7015
gfc_add_intrinsic_ss_code (gfc_loopinfo * loop ATTRIBUTE_UNUSED, gfc_ss * ss)
7016
{
7017
  switch (ss->info->expr->value.function.isym->id)
7018
    {
7019
    case GFC_ISYM_UBOUND:
7020
    case GFC_ISYM_LBOUND:
7021
    case GFC_ISYM_UCOBOUND:
7022
    case GFC_ISYM_LCOBOUND:
7023
    case GFC_ISYM_THIS_IMAGE:
7024
      break;
7025
 
7026
    default:
7027
      gcc_unreachable ();
7028
    }
7029
}
7030
 
7031
 
7032
/* The LBOUND, LCOBOUND, UBOUND and UCOBOUND intrinsics with one parameter
7033
   are expanded into code inside the scalarization loop.  */
7034
 
7035
static gfc_ss *
7036
gfc_walk_intrinsic_bound (gfc_ss * ss, gfc_expr * expr)
7037
{
7038
  if (expr->value.function.actual->expr->ts.type == BT_CLASS)
7039
    gfc_add_class_array_ref (expr->value.function.actual->expr);
7040
 
7041
  /* The two argument version returns a scalar.  */
7042
  if (expr->value.function.actual->next->expr)
7043
    return ss;
7044
 
7045
  return gfc_get_array_ss (ss, expr, 1, GFC_SS_INTRINSIC);
7046
}
7047
 
7048
 
7049
/* Walk an intrinsic array libcall.  */
7050
 
7051
static gfc_ss *
7052
gfc_walk_intrinsic_libfunc (gfc_ss * ss, gfc_expr * expr)
7053
{
7054
  gcc_assert (expr->rank > 0);
7055
  return gfc_get_array_ss (ss, expr, expr->rank, GFC_SS_FUNCTION);
7056
}
7057
 
7058
 
7059
/* Return whether the function call expression EXPR will be expanded
7060
   inline by gfc_conv_intrinsic_function.  */
7061
 
7062
bool
7063
gfc_inline_intrinsic_function_p (gfc_expr *expr)
7064
{
7065
  gfc_actual_arglist *args;
7066
 
7067
  if (!expr->value.function.isym)
7068
    return false;
7069
 
7070
  switch (expr->value.function.isym->id)
7071
    {
7072
    case GFC_ISYM_PRODUCT:
7073
    case GFC_ISYM_SUM:
7074
      /* Disable inline expansion if code size matters.  */
7075
      if (optimize_size)
7076
        return false;
7077
 
7078
      args = expr->value.function.actual;
7079
      /* We need to be able to subset the SUM argument at compile-time.  */
7080
      if (args->next->expr && args->next->expr->expr_type != EXPR_CONSTANT)
7081
        return false;
7082
 
7083
      return true;
7084
 
7085
    case GFC_ISYM_TRANSPOSE:
7086
      return true;
7087
 
7088
    default:
7089
      return false;
7090
    }
7091
}
7092
 
7093
 
7094
/* Returns nonzero if the specified intrinsic function call maps directly to
7095
   an external library call.  Should only be used for functions that return
7096
   arrays.  */
7097
 
7098
int
7099
gfc_is_intrinsic_libcall (gfc_expr * expr)
7100
{
7101
  gcc_assert (expr->expr_type == EXPR_FUNCTION && expr->value.function.isym);
7102
  gcc_assert (expr->rank > 0);
7103
 
7104
  if (gfc_inline_intrinsic_function_p (expr))
7105
    return 0;
7106
 
7107
  switch (expr->value.function.isym->id)
7108
    {
7109
    case GFC_ISYM_ALL:
7110
    case GFC_ISYM_ANY:
7111
    case GFC_ISYM_COUNT:
7112
    case GFC_ISYM_JN2:
7113
    case GFC_ISYM_IANY:
7114
    case GFC_ISYM_IALL:
7115
    case GFC_ISYM_IPARITY:
7116
    case GFC_ISYM_MATMUL:
7117
    case GFC_ISYM_MAXLOC:
7118
    case GFC_ISYM_MAXVAL:
7119
    case GFC_ISYM_MINLOC:
7120
    case GFC_ISYM_MINVAL:
7121
    case GFC_ISYM_NORM2:
7122
    case GFC_ISYM_PARITY:
7123
    case GFC_ISYM_PRODUCT:
7124
    case GFC_ISYM_SUM:
7125
    case GFC_ISYM_SHAPE:
7126
    case GFC_ISYM_SPREAD:
7127
    case GFC_ISYM_YN2:
7128
      /* Ignore absent optional parameters.  */
7129
      return 1;
7130
 
7131
    case GFC_ISYM_RESHAPE:
7132
    case GFC_ISYM_CSHIFT:
7133
    case GFC_ISYM_EOSHIFT:
7134
    case GFC_ISYM_PACK:
7135
    case GFC_ISYM_UNPACK:
7136
      /* Pass absent optional parameters.  */
7137
      return 2;
7138
 
7139
    default:
7140
      return 0;
7141
    }
7142
}
7143
 
7144
/* Walk an intrinsic function.  */
7145
gfc_ss *
7146
gfc_walk_intrinsic_function (gfc_ss * ss, gfc_expr * expr,
7147
                             gfc_intrinsic_sym * isym)
7148
{
7149
  gcc_assert (isym);
7150
 
7151
  if (isym->elemental)
7152
    return gfc_walk_elemental_function_args (ss, expr->value.function.actual,
7153
                                             NULL, GFC_SS_SCALAR);
7154
 
7155
  if (expr->rank == 0)
7156
    return ss;
7157
 
7158
  if (gfc_inline_intrinsic_function_p (expr))
7159
    return walk_inline_intrinsic_function (ss, expr);
7160
 
7161
  if (gfc_is_intrinsic_libcall (expr))
7162
    return gfc_walk_intrinsic_libfunc (ss, expr);
7163
 
7164
  /* Special cases.  */
7165
  switch (isym->id)
7166
    {
7167
    case GFC_ISYM_LBOUND:
7168
    case GFC_ISYM_LCOBOUND:
7169
    case GFC_ISYM_UBOUND:
7170
    case GFC_ISYM_UCOBOUND:
7171
    case GFC_ISYM_THIS_IMAGE:
7172
      return gfc_walk_intrinsic_bound (ss, expr);
7173
 
7174
    case GFC_ISYM_TRANSFER:
7175
      return gfc_walk_intrinsic_libfunc (ss, expr);
7176
 
7177
    default:
7178
      /* This probably meant someone forgot to add an intrinsic to the above
7179
         list(s) when they implemented it, or something's gone horribly
7180
         wrong.  */
7181
      gcc_unreachable ();
7182
    }
7183
}
7184
 
7185
 
7186
static tree
7187
conv_intrinsic_atomic_def (gfc_code *code)
7188
{
7189
  gfc_se atom, value;
7190
  stmtblock_t block;
7191
 
7192
  gfc_init_se (&atom, NULL);
7193
  gfc_init_se (&value, NULL);
7194
  gfc_conv_expr (&atom, code->ext.actual->expr);
7195
  gfc_conv_expr (&value, code->ext.actual->next->expr);
7196
 
7197
  gfc_init_block (&block);
7198
  gfc_add_modify (&block, atom.expr,
7199
                  fold_convert (TREE_TYPE (atom.expr), value.expr));
7200
  return gfc_finish_block (&block);
7201
}
7202
 
7203
 
7204
static tree
7205
conv_intrinsic_atomic_ref (gfc_code *code)
7206
{
7207
  gfc_se atom, value;
7208
  stmtblock_t block;
7209
 
7210
  gfc_init_se (&atom, NULL);
7211
  gfc_init_se (&value, NULL);
7212
  gfc_conv_expr (&value, code->ext.actual->expr);
7213
  gfc_conv_expr (&atom, code->ext.actual->next->expr);
7214
 
7215
  gfc_init_block (&block);
7216
  gfc_add_modify (&block, value.expr,
7217
                  fold_convert (TREE_TYPE (value.expr), atom.expr));
7218
  return gfc_finish_block (&block);
7219
}
7220
 
7221
 
7222
static tree
7223
conv_intrinsic_move_alloc (gfc_code *code)
7224
{
7225
  stmtblock_t block;
7226
  gfc_expr *from_expr, *to_expr;
7227
  gfc_expr *to_expr2, *from_expr2 = NULL;
7228
  gfc_se from_se, to_se;
7229
  gfc_ss *from_ss, *to_ss;
7230
  tree tmp;
7231
 
7232
  gfc_start_block (&block);
7233
 
7234
  from_expr = code->ext.actual->expr;
7235
  to_expr = code->ext.actual->next->expr;
7236
 
7237
  gfc_init_se (&from_se, NULL);
7238
  gfc_init_se (&to_se, NULL);
7239
 
7240
  gcc_assert (from_expr->ts.type != BT_CLASS
7241
              || to_expr->ts.type == BT_CLASS);
7242
 
7243
  if (from_expr->rank == 0)
7244
    {
7245
      if (from_expr->ts.type != BT_CLASS)
7246
        from_expr2 = from_expr;
7247
      else
7248
        {
7249
          from_expr2 = gfc_copy_expr (from_expr);
7250
          gfc_add_data_component (from_expr2);
7251
        }
7252
 
7253
      if (to_expr->ts.type != BT_CLASS)
7254
        to_expr2 = to_expr;
7255
      else
7256
        {
7257
          to_expr2 = gfc_copy_expr (to_expr);
7258
          gfc_add_data_component (to_expr2);
7259
        }
7260
 
7261
      from_se.want_pointer = 1;
7262
      to_se.want_pointer = 1;
7263
      gfc_conv_expr (&from_se, from_expr2);
7264
      gfc_conv_expr (&to_se, to_expr2);
7265
      gfc_add_block_to_block (&block, &from_se.pre);
7266
      gfc_add_block_to_block (&block, &to_se.pre);
7267
 
7268
      /* Deallocate "to".  */
7269
      tmp = gfc_deallocate_scalar_with_status (to_se.expr, NULL_TREE, true,
7270
                                               to_expr2, to_expr->ts);
7271
      gfc_add_expr_to_block (&block, tmp);
7272
 
7273
      /* Assign (_data) pointers.  */
7274
      gfc_add_modify_loc (input_location, &block, to_se.expr,
7275
                          fold_convert (TREE_TYPE (to_se.expr), from_se.expr));
7276
 
7277
      /* Set "from" to NULL.  */
7278
      gfc_add_modify_loc (input_location, &block, from_se.expr,
7279
                          fold_convert (TREE_TYPE (from_se.expr), null_pointer_node));
7280
 
7281
      gfc_add_block_to_block (&block, &from_se.post);
7282
      gfc_add_block_to_block (&block, &to_se.post);
7283
 
7284
      /* Set _vptr.  */
7285
      if (to_expr->ts.type == BT_CLASS)
7286
        {
7287
          gfc_free_expr (to_expr2);
7288
          gfc_init_se (&to_se, NULL);
7289
          to_se.want_pointer = 1;
7290
          gfc_add_vptr_component (to_expr);
7291
          gfc_conv_expr (&to_se, to_expr);
7292
 
7293
          if (from_expr->ts.type == BT_CLASS)
7294
            {
7295
              gfc_free_expr (from_expr2);
7296
              gfc_init_se (&from_se, NULL);
7297
              from_se.want_pointer = 1;
7298
              gfc_add_vptr_component (from_expr);
7299
              gfc_conv_expr (&from_se, from_expr);
7300
              tmp = from_se.expr;
7301
            }
7302
          else
7303
            {
7304
              gfc_symbol *vtab;
7305
              vtab = gfc_find_derived_vtab (from_expr->ts.u.derived);
7306
              gcc_assert (vtab);
7307
              tmp = gfc_build_addr_expr (NULL_TREE, gfc_get_symbol_decl (vtab));
7308
            }
7309
 
7310
          gfc_add_modify_loc (input_location, &block, to_se.expr,
7311
                              fold_convert (TREE_TYPE (to_se.expr), tmp));
7312
        }
7313
 
7314
      return gfc_finish_block (&block);
7315
    }
7316
 
7317
  /* Update _vptr component.  */
7318
  if (to_expr->ts.type == BT_CLASS)
7319
    {
7320
      to_se.want_pointer = 1;
7321
      to_expr2 = gfc_copy_expr (to_expr);
7322
      gfc_add_vptr_component (to_expr2);
7323
      gfc_conv_expr (&to_se, to_expr2);
7324
 
7325
      if (from_expr->ts.type == BT_CLASS)
7326
        {
7327
          from_se.want_pointer = 1;
7328
          from_expr2 = gfc_copy_expr (from_expr);
7329
          gfc_add_vptr_component (from_expr2);
7330
          gfc_conv_expr (&from_se, from_expr2);
7331
          tmp = from_se.expr;
7332
        }
7333
      else
7334
        {
7335
          gfc_symbol *vtab;
7336
          vtab = gfc_find_derived_vtab (from_expr->ts.u.derived);
7337
          gcc_assert (vtab);
7338
          tmp = gfc_build_addr_expr (NULL_TREE, gfc_get_symbol_decl (vtab));
7339
        }
7340
 
7341
      gfc_add_modify_loc (input_location, &block, to_se.expr,
7342
                          fold_convert (TREE_TYPE (to_se.expr), tmp));
7343
      gfc_free_expr (to_expr2);
7344
      gfc_init_se (&to_se, NULL);
7345
 
7346
      if (from_expr->ts.type == BT_CLASS)
7347
        {
7348
          gfc_free_expr (from_expr2);
7349
          gfc_init_se (&from_se, NULL);
7350
        }
7351
    }
7352
 
7353
  /* Deallocate "to".  */
7354
  to_ss = gfc_walk_expr (to_expr);
7355
  from_ss = gfc_walk_expr (from_expr);
7356
  gfc_conv_expr_descriptor (&to_se, to_expr, to_ss);
7357
  gfc_conv_expr_descriptor (&from_se, from_expr, from_ss);
7358
 
7359
  tmp = gfc_conv_descriptor_data_get (to_se.expr);
7360
  tmp = gfc_deallocate_with_status (tmp, NULL_TREE, NULL_TREE, NULL_TREE,
7361
                                    NULL_TREE, true, to_expr, false);
7362
  gfc_add_expr_to_block (&block, tmp);
7363
 
7364
  /* Move the pointer and update the array descriptor data.  */
7365
  gfc_add_modify_loc (input_location, &block, to_se.expr, from_se.expr);
7366
 
7367
  /* Set "to" to NULL.  */
7368
  tmp = gfc_conv_descriptor_data_get (from_se.expr);
7369
  gfc_add_modify_loc (input_location, &block, tmp,
7370
                      fold_convert (TREE_TYPE (tmp), null_pointer_node));
7371
 
7372
  return gfc_finish_block (&block);
7373
}
7374
 
7375
 
7376
tree
7377
gfc_conv_intrinsic_subroutine (gfc_code *code)
7378
{
7379
  tree res;
7380
 
7381
  gcc_assert (code->resolved_isym);
7382
 
7383
  switch (code->resolved_isym->id)
7384
    {
7385
    case GFC_ISYM_MOVE_ALLOC:
7386
      res = conv_intrinsic_move_alloc (code);
7387
      break;
7388
 
7389
    case GFC_ISYM_ATOMIC_DEF:
7390
      res = conv_intrinsic_atomic_def (code);
7391
      break;
7392
 
7393
    case GFC_ISYM_ATOMIC_REF:
7394
      res = conv_intrinsic_atomic_ref (code);
7395
      break;
7396
 
7397
    default:
7398
      res = NULL_TREE;
7399
      break;
7400
    }
7401
 
7402
  return res;
7403
}
7404
 
7405
#include "gt-fortran-trans-intrinsic.h"

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.