trans-array.c 160 KB
Newer Older
1
/* Array translation routines
2 3
   Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007
   Free Software Foundation, Inc.
4 5 6
   Contributed by Paul Brook <paul@nowt.org>
   and Steven Bosscher <s.bosscher@student.tudelft.nl>

7
This file is part of GCC.
8

9 10
GCC is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
11
Software Foundation; either version 3, or (at your option) any later
12
version.
13

14 15 16 17
GCC is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
for more details.
18 19

You should have received a copy of the GNU General Public License
20 21
along with GCC; see the file COPYING3.  If not see
<http://www.gnu.org/licenses/>.  */
22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62

/* trans-array.c-- Various array related code, including scalarization,
                   allocation, initialization and other support routines.  */

/* How the scalarizer works.
   In gfortran, array expressions use the same core routines as scalar
   expressions.
   First, a Scalarization State (SS) chain is built.  This is done by walking
   the expression tree, and building a linear list of the terms in the
   expression.  As the tree is walked, scalar subexpressions are translated.

   The scalarization parameters are stored in a gfc_loopinfo structure.
   First the start and stride of each term is calculated by
   gfc_conv_ss_startstride.  During this process the expressions for the array
   descriptors and data pointers are also translated.

   If the expression is an assignment, we must then resolve any dependencies.
   In fortran all the rhs values of an assignment must be evaluated before
   any assignments take place.  This can require a temporary array to store the
   values.  We also require a temporary when we are passing array expressions
   or vector subecripts as procedure parameters.

   Array sections are passed without copying to a temporary.  These use the
   scalarizer to determine the shape of the section.  The flag
   loop->array_parameter tells the scalarizer that the actual values and loop
   variables will not be required.

   The function gfc_conv_loop_setup generates the scalarization setup code.
   It determines the range of the scalarizing loop variables.  If a temporary
   is required, this is created and initialized.  Code for scalar expressions
   taken outside the loop is also generated at this time.  Next the offset and
   scaling required to translate from loop variables to array indices for each
   term is calculated.

   A call to gfc_start_scalarized_body marks the start of the scalarized
   expression.  This creates a scope and declares the loop variables.  Before
   calling this gfc_make_ss_chain_used must be used to indicate which terms
   will be used inside this loop.

   The scalar gfc_conv_* functions are then used to build the main body of the
   scalarization loop.  Scalarization loop variables and precalculated scalar
63
   values are automatically substituted.  Note that gfc_advance_se_ss_chain
64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82
   must be used, rather than changing the se->ss directly.

   For assignment expressions requiring a temporary two sub loops are
   generated.  The first stores the result of the expression in the temporary,
   the second copies it to the result.  A call to
   gfc_trans_scalarized_loop_boundary marks the end of the main loop code and
   the start of the copying loop.  The temporary may be less than full rank.

   Finally gfc_trans_scalarizing_loops is called to generate the implicit do
   loops.  The loops are added to the pre chain of the loopinfo.  The post
   chain may still contain cleanup code.

   After the loop code has been added into its parent scope gfc_cleanup_loop
   is called to free all the SS allocated by the scalarizer.  */

#include "config.h"
#include "system.h"
#include "coretypes.h"
#include "tree.h"
83
#include "tree-gimple.h"
84 85 86 87 88 89 90 91 92 93 94 95 96
#include "ggc.h"
#include "toplev.h"
#include "real.h"
#include "flags.h"
#include "gfortran.h"
#include "trans.h"
#include "trans-stmt.h"
#include "trans-types.h"
#include "trans-array.h"
#include "trans-const.h"
#include "dependency.h"

static gfc_ss *gfc_walk_subexpr (gfc_ss *, gfc_expr *);
97
static bool gfc_get_array_constructor_size (mpz_t *, gfc_constructor *);
98

99
/* The contents of this structure aren't actually used, just the address.  */
100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137
static gfc_ss gfc_ss_terminator_var;
gfc_ss * const gfc_ss_terminator = &gfc_ss_terminator_var;


static tree
gfc_array_dataptr_type (tree desc)
{
  return (GFC_TYPE_ARRAY_DATAPTR_TYPE (TREE_TYPE (desc)));
}


/* Build expressions to access the members of an array descriptor.
   It's surprisingly easy to mess up here, so never access
   an array descriptor by "brute force", always use these
   functions.  This also avoids problems if we change the format
   of an array descriptor.

   To understand these magic numbers, look at the comments
   before gfc_build_array_type() in trans-types.c.

   The code within these defines should be the only code which knows the format
   of an array descriptor.

   Any code just needing to read obtain the bounds of an array should use
   gfc_conv_array_* rather than the following functions as these will return
   know constant values, and work with arrays which do not have descriptors.

   Don't forget to #undef these!  */

#define DATA_FIELD 0
#define OFFSET_FIELD 1
#define DTYPE_FIELD 2
#define DIMENSION_FIELD 3

#define STRIDE_SUBFIELD 0
#define LBOUND_SUBFIELD 1
#define UBOUND_SUBFIELD 2

138 139 140
/* This provides READ-ONLY access to the data field.  The field itself
   doesn't have the proper type.  */

141
tree
142
gfc_conv_descriptor_data_get (tree desc)
143
{
144
  tree field, type, t;
145 146

  type = TREE_TYPE (desc);
147
  gcc_assert (GFC_DESCRIPTOR_TYPE_P (type));
148 149

  field = TYPE_FIELDS (type);
150
  gcc_assert (DATA_FIELD == 0);
151

152 153 154 155 156 157
  t = build3 (COMPONENT_REF, TREE_TYPE (field), desc, field, NULL_TREE);
  t = fold_convert (GFC_TYPE_ARRAY_DATAPTR_TYPE (type), t);

  return t;
}

158 159 160 161 162 163 164
/* This provides WRITE access to the data field.

   TUPLES_P is true if we are generating tuples.
   
   This function gets called through the following macros:
     gfc_conv_descriptor_data_set
     gfc_conv_descriptor_data_set_tuples.  */
165 166

void
167 168 169
gfc_conv_descriptor_data_set_internal (stmtblock_t *block,
				       tree desc, tree value,
				       bool tuples_p)
170 171 172 173 174 175 176 177 178 179
{
  tree field, type, t;

  type = TREE_TYPE (desc);
  gcc_assert (GFC_DESCRIPTOR_TYPE_P (type));

  field = TYPE_FIELDS (type);
  gcc_assert (DATA_FIELD == 0);

  t = build3 (COMPONENT_REF, TREE_TYPE (field), desc, field, NULL_TREE);
180
  gfc_add_modify (block, t, fold_convert (TREE_TYPE (field), value), tuples_p);
181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198
}


/* This provides address access to the data field.  This should only be
   used by array allocation, passing this on to the runtime.  */

tree
gfc_conv_descriptor_data_addr (tree desc)
{
  tree field, type, t;

  type = TREE_TYPE (desc);
  gcc_assert (GFC_DESCRIPTOR_TYPE_P (type));

  field = TYPE_FIELDS (type);
  gcc_assert (DATA_FIELD == 0);

  t = build3 (COMPONENT_REF, TREE_TYPE (field), desc, field, NULL_TREE);
199
  return build_fold_addr_expr (t);
200 201 202 203 204 205 206 207 208
}

tree
gfc_conv_descriptor_offset (tree desc)
{
  tree type;
  tree field;

  type = TREE_TYPE (desc);
209
  gcc_assert (GFC_DESCRIPTOR_TYPE_P (type));
210 211

  field = gfc_advance_chain (TYPE_FIELDS (type), OFFSET_FIELD);
212
  gcc_assert (field != NULL_TREE && TREE_TYPE (field) == gfc_array_index_type);
213

214
  return build3 (COMPONENT_REF, TREE_TYPE (field), desc, field, NULL_TREE);
215 216 217 218 219 220 221 222 223
}

tree
gfc_conv_descriptor_dtype (tree desc)
{
  tree field;
  tree type;

  type = TREE_TYPE (desc);
224
  gcc_assert (GFC_DESCRIPTOR_TYPE_P (type));
225 226

  field = gfc_advance_chain (TYPE_FIELDS (type), DTYPE_FIELD);
227
  gcc_assert (field != NULL_TREE && TREE_TYPE (field) == gfc_array_index_type);
228

229
  return build3 (COMPONENT_REF, TREE_TYPE (field), desc, field, NULL_TREE);
230 231 232 233 234 235 236 237 238 239
}

static tree
gfc_conv_descriptor_dimension (tree desc, tree dim)
{
  tree field;
  tree type;
  tree tmp;

  type = TREE_TYPE (desc);
240
  gcc_assert (GFC_DESCRIPTOR_TYPE_P (type));
241 242

  field = gfc_advance_chain (TYPE_FIELDS (type), DIMENSION_FIELD);
243
  gcc_assert (field != NULL_TREE
244 245 246
	  && TREE_CODE (TREE_TYPE (field)) == ARRAY_TYPE
	  && TREE_CODE (TREE_TYPE (TREE_TYPE (field))) == RECORD_TYPE);

247
  tmp = build3 (COMPONENT_REF, TREE_TYPE (field), desc, field, NULL_TREE);
248 249 250 251 252 253 254 255 256 257 258 259 260
  tmp = gfc_build_array_ref (tmp, dim);
  return tmp;
}

tree
gfc_conv_descriptor_stride (tree desc, tree dim)
{
  tree tmp;
  tree field;

  tmp = gfc_conv_descriptor_dimension (desc, dim);
  field = TYPE_FIELDS (TREE_TYPE (tmp));
  field = gfc_advance_chain (field, STRIDE_SUBFIELD);
261
  gcc_assert (field != NULL_TREE && TREE_TYPE (field) == gfc_array_index_type);
262

263
  tmp = build3 (COMPONENT_REF, TREE_TYPE (field), tmp, field, NULL_TREE);
264 265 266 267 268 269 270 271 272 273 274 275
  return tmp;
}

tree
gfc_conv_descriptor_lbound (tree desc, tree dim)
{
  tree tmp;
  tree field;

  tmp = gfc_conv_descriptor_dimension (desc, dim);
  field = TYPE_FIELDS (TREE_TYPE (tmp));
  field = gfc_advance_chain (field, LBOUND_SUBFIELD);
276
  gcc_assert (field != NULL_TREE && TREE_TYPE (field) == gfc_array_index_type);
277

278
  tmp = build3 (COMPONENT_REF, TREE_TYPE (field), tmp, field, NULL_TREE);
279 280 281 282 283 284 285 286 287 288 289 290
  return tmp;
}

tree
gfc_conv_descriptor_ubound (tree desc, tree dim)
{
  tree tmp;
  tree field;

  tmp = gfc_conv_descriptor_dimension (desc, dim);
  field = TYPE_FIELDS (TREE_TYPE (tmp));
  field = gfc_advance_chain (field, UBOUND_SUBFIELD);
291
  gcc_assert (field != NULL_TREE && TREE_TYPE (field) == gfc_array_index_type);
292

293
  tmp = build3 (COMPONENT_REF, TREE_TYPE (field), tmp, field, NULL_TREE);
294 295 296 297
  return tmp;
}


298
/* Build a null array descriptor constructor.  */
299

300 301
tree
gfc_build_null_descriptor (tree type)
302 303
{
  tree field;
304
  tree tmp;
305

306 307
  gcc_assert (GFC_DESCRIPTOR_TYPE_P (type));
  gcc_assert (DATA_FIELD == 0);
308 309
  field = TYPE_FIELDS (type);

310
  /* Set a NULL data pointer.  */
311
  tmp = build_constructor_single (type, field, null_pointer_node);
312 313
  TREE_CONSTANT (tmp) = 1;
  TREE_INVARIANT (tmp) = 1;
314 315 316
  /* All other fields are ignored.  */

  return tmp;
317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353
}


/* Cleanup those #defines.  */

#undef DATA_FIELD
#undef OFFSET_FIELD
#undef DTYPE_FIELD
#undef DIMENSION_FIELD
#undef STRIDE_SUBFIELD
#undef LBOUND_SUBFIELD
#undef UBOUND_SUBFIELD


/* Mark a SS chain as used.  Flags specifies in which loops the SS is used.
   flags & 1 = Main loop body.
   flags & 2 = temp copy loop.  */

void
gfc_mark_ss_chain_used (gfc_ss * ss, unsigned flags)
{
  for (; ss != gfc_ss_terminator; ss = ss->next)
    ss->useflags = flags;
}

static void gfc_free_ss (gfc_ss *);


/* Free a gfc_ss chain.  */

static void
gfc_free_ss_chain (gfc_ss * ss)
{
  gfc_ss *next;

  while (ss != gfc_ss_terminator)
    {
354
      gcc_assert (ss != NULL);
355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397
      next = ss->next;
      gfc_free_ss (ss);
      ss = next;
    }
}


/* Free a SS.  */

static void
gfc_free_ss (gfc_ss * ss)
{
  int n;

  switch (ss->type)
    {
    case GFC_SS_SECTION:
      for (n = 0; n < GFC_MAX_DIMENSIONS; n++)
	{
	  if (ss->data.info.subscript[n])
	    gfc_free_ss_chain (ss->data.info.subscript[n]);
	}
      break;

    default:
      break;
    }

  gfc_free (ss);
}


/* Free all the SS associated with a loop.  */

void
gfc_cleanup_loop (gfc_loopinfo * loop)
{
  gfc_ss *ss;
  gfc_ss *next;

  ss = loop->ss;
  while (ss != gfc_ss_terminator)
    {
398
      gcc_assert (ss != NULL);
399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423
      next = ss->loop_chain;
      gfc_free_ss (ss);
      ss = next;
    }
}


/* Associate a SS chain with a loop.  */

void
gfc_add_ss_to_loop (gfc_loopinfo * loop, gfc_ss * head)
{
  gfc_ss *ss;

  if (head == gfc_ss_terminator)
    return;

  ss = head;
  for (; ss && ss != gfc_ss_terminator; ss = ss->next)
    {
      if (ss->next == gfc_ss_terminator)
	ss->loop_chain = loop->ss;
      else
	ss->loop_chain = ss->next;
    }
424
  gcc_assert (ss == gfc_ss_terminator);
425 426 427 428
  loop->ss = head;
}


429 430 431 432 433 434 435
/* Generate an initializer for a static pointer or allocatable array.  */

void
gfc_trans_static_array_pointer (gfc_symbol * sym)
{
  tree type;

436
  gcc_assert (TREE_STATIC (sym->backend_decl));
437 438
  /* Just zero the data member.  */
  type = TREE_TYPE (sym->backend_decl);
439
  DECL_INITIAL (sym->backend_decl) = gfc_build_null_descriptor (type);
440 441 442
}


443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487
/* If the bounds of SE's loop have not yet been set, see if they can be
   determined from array spec AS, which is the array spec of a called
   function.  MAPPING maps the callee's dummy arguments to the values
   that the caller is passing.  Add any initialization and finalization
   code to SE.  */

void
gfc_set_loop_bounds_from_array_spec (gfc_interface_mapping * mapping,
				     gfc_se * se, gfc_array_spec * as)
{
  int n, dim;
  gfc_se tmpse;
  tree lower;
  tree upper;
  tree tmp;

  if (as && as->type == AS_EXPLICIT)
    for (dim = 0; dim < se->loop->dimen; dim++)
      {
	n = se->loop->order[dim];
	if (se->loop->to[n] == NULL_TREE)
	  {
	    /* Evaluate the lower bound.  */
	    gfc_init_se (&tmpse, NULL);
	    gfc_apply_interface_mapping (mapping, &tmpse, as->lower[dim]);
	    gfc_add_block_to_block (&se->pre, &tmpse.pre);
	    gfc_add_block_to_block (&se->post, &tmpse.post);
	    lower = tmpse.expr;

	    /* ...and the upper bound.  */
	    gfc_init_se (&tmpse, NULL);
	    gfc_apply_interface_mapping (mapping, &tmpse, as->upper[dim]);
	    gfc_add_block_to_block (&se->pre, &tmpse.pre);
	    gfc_add_block_to_block (&se->post, &tmpse.post);
	    upper = tmpse.expr;

	    /* Set the upper bound of the loop to UPPER - LOWER.  */
	    tmp = fold_build2 (MINUS_EXPR, gfc_array_index_type, upper, lower);
	    tmp = gfc_evaluate_now (tmp, &se->pre);
	    se->loop->to[n] = tmp;
	  }
      }
}


488
/* Generate code to allocate an array temporary, or create a variable to
489 490 491
   hold the data.  If size is NULL, zero the descriptor so that the
   callee will allocate the array.  If DEALLOC is true, also generate code to
   free the array afterwards.
492

493
   Initialization code is added to PRE and finalization code to POST.
494 495
   DYNAMIC is true if the caller may want to extend the array later
   using realloc.  This prevents us from putting the array on the stack.  */
496 497

static void
498
gfc_trans_allocate_array_storage (stmtblock_t * pre, stmtblock_t * post,
499 500
                                  gfc_ss_info * info, tree size, tree nelem,
                                  bool dynamic, bool dealloc)
501 502 503 504 505 506
{
  tree tmp;
  tree desc;
  bool onstack;

  desc = info->descriptor;
507
  info->offset = gfc_index_zero_node;
508
  if (size == NULL_TREE || integer_zerop (size))
509
    {
510
      /* A callee allocated array.  */
511
      gfc_conv_descriptor_data_set (pre, desc, null_pointer_node);
512
      onstack = FALSE;
513 514 515
    }
  else
    {
516
      /* Allocate the temporary.  */
517
      onstack = !dynamic && gfc_can_put_var_on_stack (size);
518 519 520 521

      if (onstack)
	{
	  /* Make a temporary variable to hold the data.  */
522
	  tmp = fold_build2 (MINUS_EXPR, TREE_TYPE (nelem), nelem,
523
			     gfc_index_one_node);
524 525 526 527 528
	  tmp = build_range_type (gfc_array_index_type, gfc_index_zero_node,
				  tmp);
	  tmp = build_array_type (gfc_get_element_type (TREE_TYPE (desc)),
				  tmp);
	  tmp = gfc_create_var (tmp, "A");
529
	  tmp = build_fold_addr_expr (tmp);
530
	  gfc_conv_descriptor_data_set (pre, desc, tmp);
531
	}
532
      else
533 534
	{
	  /* Allocate memory to hold the data.  */
535
	  tmp = gfc_call_malloc (pre, NULL, size);
536 537
	  tmp = gfc_evaluate_now (tmp, pre);
	  gfc_conv_descriptor_data_set (pre, desc, tmp);
538
	}
539
    }
540
  info->data = gfc_conv_descriptor_data_get (desc);
541 542 543 544

  /* The offset is zero because we create temporaries with a zero
     lower bound.  */
  tmp = gfc_conv_descriptor_offset (desc);
545
  gfc_add_modify_expr (pre, tmp, gfc_index_zero_node);
546

547
  if (dealloc && !onstack)
548 549
    {
      /* Free the temporary.  */
550
      tmp = gfc_conv_descriptor_data_get (desc);
551
      tmp = gfc_call_free (fold_convert (pvoid_type_node, tmp));
552
      gfc_add_expr_to_block (post, tmp);
553 554 555 556
    }
}


557
/* Generate code to create and initialize the descriptor for a temporary
558
   array.  This is used for both temporaries needed by the scalarizer, and
559 560 561 562 563 564 565
   functions returning arrays.  Adjusts the loop variables to be
   zero-based, and calculates the loop bounds for callee allocated arrays.
   Allocate the array unless it's callee allocated (we have a callee
   allocated array if 'callee_alloc' is true, or if loop->to[n] is
   NULL_TREE for any n).  Also fills in the descriptor, data and offset
   fields of info if known.  Returns the size of the array, or NULL for a
   callee allocated array.
566

567 568
   PRE, POST, DYNAMIC and DEALLOC are as for gfc_trans_allocate_array_storage.
 */
569 570

tree
571 572 573
gfc_trans_create_temp_array (stmtblock_t * pre, stmtblock_t * post,
			     gfc_loopinfo * loop, gfc_ss_info * info,
			     tree eltype, bool dynamic, bool dealloc,
574
			     bool callee_alloc)
575 576 577 578 579 580
{
  tree type;
  tree desc;
  tree tmp;
  tree size;
  tree nelem;
581 582
  tree cond;
  tree or_expr;
583 584 585
  int n;
  int dim;

586
  gcc_assert (info->dimen > 0);
587 588 589 590 591
  /* Set the lower bound to zero.  */
  for (dim = 0; dim < info->dimen; dim++)
    {
      n = loop->order[dim];
      if (n < loop->temp_dim)
592
	gcc_assert (integer_zerop (loop->from[n]));
593 594
      else
	{
595 596
	  /* Callee allocated arrays may not have a known bound yet.  */
          if (loop->to[n])
597 598
              loop->to[n] = fold_build2 (MINUS_EXPR, gfc_array_index_type,
					 loop->to[n], loop->from[n]);
599
	  loop->from[n] = gfc_index_zero_node;
600 601
	}

602 603
      info->delta[dim] = gfc_index_zero_node;
      info->start[dim] = gfc_index_zero_node;
604
      info->end[dim] = gfc_index_zero_node;
605
      info->stride[dim] = gfc_index_one_node;
606 607 608
      info->dim[dim] = dim;
    }

609
  /* Initialize the descriptor.  */
610 611 612 613 614 615
  type =
    gfc_get_array_type_bounds (eltype, info->dimen, loop->from, loop->to, 1);
  desc = gfc_create_var (type, "atmp");
  GFC_DECL_PACKED_ARRAY (desc) = 1;

  info->descriptor = desc;
616
  size = gfc_index_one_node;
617 618 619

  /* Fill in the array dtype.  */
  tmp = gfc_conv_descriptor_dtype (desc);
620
  gfc_add_modify_expr (pre, tmp, gfc_get_dtype (TREE_TYPE (desc)));
621

622 623 624
  /*
     Fill in the bounds and stride.  This is a packed array, so:

625 626
     size = 1;
     for (n = 0; n < rank; n++)
627 628 629 630 631 632 633 634
       {
	 stride[n] = size
	 delta = ubound[n] + 1 - lbound[n];
         size = size * delta;
       }
     size = size * sizeof(element);
  */

635 636
  or_expr = NULL_TREE;

637 638
  for (n = 0; n < info->dimen; n++)
    {
639 640 641 642
      if (loop->to[n] == NULL_TREE)
        {
	  /* For a callee allocated array express the loop bounds in terms
	     of the descriptor fields.  */
643 644 645
          tmp = build2 (MINUS_EXPR, gfc_array_index_type,
			gfc_conv_descriptor_ubound (desc, gfc_rank_cst[n]),
			gfc_conv_descriptor_lbound (desc, gfc_rank_cst[n]));
646 647 648 649 650
          loop->to[n] = tmp;
          size = NULL_TREE;
          continue;
        }
        
651 652
      /* Store the stride and bound components in the descriptor.  */
      tmp = gfc_conv_descriptor_stride (desc, gfc_rank_cst[n]);
653
      gfc_add_modify_expr (pre, tmp, size);
654 655

      tmp = gfc_conv_descriptor_lbound (desc, gfc_rank_cst[n]);
656
      gfc_add_modify_expr (pre, tmp, gfc_index_zero_node);
657 658

      tmp = gfc_conv_descriptor_ubound (desc, gfc_rank_cst[n]);
659
      gfc_add_modify_expr (pre, tmp, loop->to[n]);
660

661 662
      tmp = fold_build2 (PLUS_EXPR, gfc_array_index_type,
			 loop->to[n], gfc_index_one_node);
663

664 665
      /* Check whether the size for this dimension is negative.  */
      cond = fold_build2 (LE_EXPR, boolean_type_node, tmp,
666
			  gfc_index_zero_node);
667
      cond = gfc_evaluate_now (cond, pre);
668

669 670 671 672
      if (n == 0)
	or_expr = cond;
      else
	or_expr = fold_build2 (TRUTH_OR_EXPR, boolean_type_node, or_expr, cond);
673

674
      size = fold_build2 (MULT_EXPR, gfc_array_index_type, size, tmp);
675
      size = gfc_evaluate_now (size, pre);
676 677 678
    }

  /* Get the size of the array.  */
679

680
  if (size && !callee_alloc)
681
    {
682 683 684 685
      /* If or_expr is true, then the extent in at least one
	 dimension is zero and the size is set to zero.  */
      size = fold_build3 (COND_EXPR, gfc_array_index_type,
			  or_expr, gfc_index_zero_node, size);
686

687
      nelem = size;
688
      size = fold_build2 (MULT_EXPR, gfc_array_index_type, size,
689 690
		fold_convert (gfc_array_index_type,
			      TYPE_SIZE_UNIT (gfc_get_element_type (type))));
691
    }
692
  else
693 694 695 696
    {
      nelem = size;
      size = NULL_TREE;
    }
697

698
  gfc_trans_allocate_array_storage (pre, post, info, size, nelem, dynamic,
699
			            dealloc);
700 701 702 703 704 705 706 707

  if (info->dimen > loop->temp_dim)
    loop->temp_dim = info->dimen;

  return size;
}


708
/* Generate code to transpose array EXPR by creating a new descriptor
709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727
   in which the dimension specifications have been reversed.  */

void
gfc_conv_array_transpose (gfc_se * se, gfc_expr * expr)
{
  tree dest, src, dest_index, src_index;
  gfc_loopinfo *loop;
  gfc_ss_info *dest_info, *src_info;
  gfc_ss *dest_ss, *src_ss;
  gfc_se src_se;
  int n;

  loop = se->loop;

  src_ss = gfc_walk_expr (expr);
  dest_ss = se->ss;

  src_info = &src_ss->data.info;
  dest_info = &dest_ss->data.info;
728 729
  gcc_assert (dest_info->dimen == 2);
  gcc_assert (src_info->dimen == 2);
730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751

  /* Get a descriptor for EXPR.  */
  gfc_init_se (&src_se, NULL);
  gfc_conv_expr_descriptor (&src_se, expr, src_ss);
  gfc_add_block_to_block (&se->pre, &src_se.pre);
  gfc_add_block_to_block (&se->post, &src_se.post);
  src = src_se.expr;

  /* Allocate a new descriptor for the return value.  */
  dest = gfc_create_var (TREE_TYPE (src), "atmp");
  dest_info->descriptor = dest;
  se->expr = dest;

  /* Copy across the dtype field.  */
  gfc_add_modify_expr (&se->pre,
		       gfc_conv_descriptor_dtype (dest),
		       gfc_conv_descriptor_dtype (src));

  /* Copy the dimension information, renumbering dimension 1 to 0 and
     0 to 1.  */
  for (n = 0; n < 2; n++)
    {
752 753
      dest_info->delta[n] = gfc_index_zero_node;
      dest_info->start[n] = gfc_index_zero_node;
754
      dest_info->end[n] = gfc_index_zero_node;
755
      dest_info->stride[n] = gfc_index_one_node;
756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785
      dest_info->dim[n] = n;

      dest_index = gfc_rank_cst[n];
      src_index = gfc_rank_cst[1 - n];

      gfc_add_modify_expr (&se->pre,
			   gfc_conv_descriptor_stride (dest, dest_index),
			   gfc_conv_descriptor_stride (src, src_index));

      gfc_add_modify_expr (&se->pre,
			   gfc_conv_descriptor_lbound (dest, dest_index),
			   gfc_conv_descriptor_lbound (src, src_index));

      gfc_add_modify_expr (&se->pre,
			   gfc_conv_descriptor_ubound (dest, dest_index),
			   gfc_conv_descriptor_ubound (src, src_index));

      if (!loop->to[n])
        {
	  gcc_assert (integer_zerop (loop->from[n]));
	  loop->to[n] = build2 (MINUS_EXPR, gfc_array_index_type,
				gfc_conv_descriptor_ubound (dest, dest_index),
				gfc_conv_descriptor_lbound (dest, dest_index));
        }
    }

  /* Copy the data pointer.  */
  dest_info->data = gfc_conv_descriptor_data_get (src);
  gfc_conv_descriptor_data_set (&se->pre, dest, dest_info->data);

786 787 788 789 790 791 792 793
  /* Copy the offset.  This is not changed by transposition; the top-left
     element is still at the same offset as before, except where the loop
     starts at zero.  */
  if (!integer_zerop (loop->from[0]))
    dest_info->offset = gfc_conv_descriptor_offset (src);
  else
    dest_info->offset = gfc_index_zero_node;

794 795 796
  gfc_add_modify_expr (&se->pre,
		       gfc_conv_descriptor_offset (dest),
		       dest_info->offset);
797
	  
798 799 800 801 802
  if (dest_info->dimen > loop->temp_dim)
    loop->temp_dim = dest_info->dimen;
}


803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825
/* Return the number of iterations in a loop that starts at START,
   ends at END, and has step STEP.  */

static tree
gfc_get_iteration_count (tree start, tree end, tree step)
{
  tree tmp;
  tree type;

  type = TREE_TYPE (step);
  tmp = fold_build2 (MINUS_EXPR, type, end, start);
  tmp = fold_build2 (FLOOR_DIV_EXPR, type, tmp, step);
  tmp = fold_build2 (PLUS_EXPR, type, tmp, build_int_cst (type, 1));
  tmp = fold_build2 (MAX_EXPR, type, tmp, build_int_cst (type, 0));
  return fold_convert (gfc_array_index_type, tmp);
}


/* Extend the data in array DESC by EXTRA elements.  */

static void
gfc_grow_array (stmtblock_t * pblock, tree desc, tree extra)
{
826
  tree arg0, arg1;
827 828 829 830 831 832 833 834 835 836 837 838 839 840
  tree tmp;
  tree size;
  tree ubound;

  if (integer_zerop (extra))
    return;

  ubound = gfc_conv_descriptor_ubound (desc, gfc_rank_cst[0]);

  /* Add EXTRA to the upper bound.  */
  tmp = build2 (PLUS_EXPR, gfc_array_index_type, ubound, extra);
  gfc_add_modify_expr (pblock, ubound, tmp);

  /* Get the value of the current data pointer.  */
841
  arg0 = gfc_conv_descriptor_data_get (desc);
842 843 844 845

  /* Calculate the new array size.  */
  size = TYPE_SIZE_UNIT (gfc_get_element_type (TREE_TYPE (desc)));
  tmp = build2 (PLUS_EXPR, gfc_array_index_type, ubound, gfc_index_one_node);
846 847
  arg1 = build2 (MULT_EXPR, size_type_node, fold_convert (size_type_node, tmp),
		 fold_convert (size_type_node, size));
848

849 850
  /* Call the realloc() function.  */
  tmp = gfc_call_realloc (pblock, arg0, arg1);
851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936
  gfc_conv_descriptor_data_set (pblock, desc, tmp);
}


/* Return true if the bounds of iterator I can only be determined
   at run time.  */

static inline bool
gfc_iterator_has_dynamic_bounds (gfc_iterator * i)
{
  return (i->start->expr_type != EXPR_CONSTANT
	  || i->end->expr_type != EXPR_CONSTANT
	  || i->step->expr_type != EXPR_CONSTANT);
}


/* Split the size of constructor element EXPR into the sum of two terms,
   one of which can be determined at compile time and one of which must
   be calculated at run time.  Set *SIZE to the former and return true
   if the latter might be nonzero.  */

static bool
gfc_get_array_constructor_element_size (mpz_t * size, gfc_expr * expr)
{
  if (expr->expr_type == EXPR_ARRAY)
    return gfc_get_array_constructor_size (size, expr->value.constructor);
  else if (expr->rank > 0)
    {
      /* Calculate everything at run time.  */
      mpz_set_ui (*size, 0);
      return true;
    }
  else
    {
      /* A single element.  */
      mpz_set_ui (*size, 1);
      return false;
    }
}


/* Like gfc_get_array_constructor_element_size, but applied to the whole
   of array constructor C.  */

static bool
gfc_get_array_constructor_size (mpz_t * size, gfc_constructor * c)
{
  gfc_iterator *i;
  mpz_t val;
  mpz_t len;
  bool dynamic;

  mpz_set_ui (*size, 0);
  mpz_init (len);
  mpz_init (val);

  dynamic = false;
  for (; c; c = c->next)
    {
      i = c->iterator;
      if (i && gfc_iterator_has_dynamic_bounds (i))
	dynamic = true;
      else
	{
	  dynamic |= gfc_get_array_constructor_element_size (&len, c->expr);
	  if (i)
	    {
	      /* Multiply the static part of the element size by the
		 number of iterations.  */
	      mpz_sub (val, i->end->value.integer, i->start->value.integer);
	      mpz_fdiv_q (val, val, i->step->value.integer);
	      mpz_add_ui (val, val, 1);
	      if (mpz_sgn (val) > 0)
		mpz_mul (len, len, val);
	      else
		mpz_set_ui (len, 0);
	    }
	  mpz_add (*size, *size, len);
	}
    }
  mpz_clear (len);
  mpz_clear (val);
  return dynamic;
}


937 938 939 940 941 942 943
/* Make sure offset is a variable.  */

static void
gfc_put_offset_into_var (stmtblock_t * pblock, tree * poffset,
			 tree * offsetvar)
{
  /* We should have already created the offset variable.  We cannot
944
     create it here because we may be in an inner scope.  */
945
  gcc_assert (*offsetvar != NULL_TREE);
946 947 948 949 950 951
  gfc_add_modify_expr (pblock, *offsetvar, *poffset);
  *poffset = *offsetvar;
  TREE_USED (*offsetvar) = 1;
}


952 953 954
/* Assign an element of an array constructor.  */

static void
955
gfc_trans_array_ctor_element (stmtblock_t * pblock, tree desc,
956 957 958 959 960 961 962
			      tree offset, gfc_se * se, gfc_expr * expr)
{
  tree tmp;

  gfc_conv_expr (se, expr);

  /* Store the value.  */
963
  tmp = build_fold_indirect_ref (gfc_conv_descriptor_data_get (desc));
964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979
  tmp = gfc_build_array_ref (tmp, offset);
  if (expr->ts.type == BT_CHARACTER)
    {
      gfc_conv_string_parameter (se);
      if (POINTER_TYPE_P (TREE_TYPE (tmp)))
	{
	  /* The temporary is an array of pointers.  */
	  se->expr = fold_convert (TREE_TYPE (tmp), se->expr);
	  gfc_add_modify_expr (&se->pre, tmp, se->expr);
	}
      else
	{
	  /* The temporary is an array of string values.  */
	  tmp = gfc_build_addr_expr (pchar_type_node, tmp);
	  /* We know the temporary and the value will be the same length,
	     so can use memcpy.  */
980 981
	  tmp = build_call_expr (built_in_decls[BUILT_IN_MEMCPY], 3,
				 tmp, se->expr, se->string_length);
982 983 984 985 986 987 988 989 990 991 992 993 994 995 996
	  gfc_add_expr_to_block (&se->pre, tmp);
	}
    }
  else
    {
      /* TODO: Should the frontend already have done this conversion?  */
      se->expr = fold_convert (TREE_TYPE (tmp), se->expr);
      gfc_add_modify_expr (&se->pre, tmp, se->expr);
    }

  gfc_add_block_to_block (pblock, &se->pre);
  gfc_add_block_to_block (pblock, &se->post);
}


997 998
/* Add the contents of an array to the constructor.  DYNAMIC is as for
   gfc_trans_array_constructor_value.  */
999 1000 1001 1002

static void
gfc_trans_array_constructor_subarray (stmtblock_t * pblock,
				      tree type ATTRIBUTE_UNUSED,
1003 1004 1005
				      tree desc, gfc_expr * expr,
				      tree * poffset, tree * offsetvar,
				      bool dynamic)
1006 1007 1008 1009 1010 1011
{
  gfc_se se;
  gfc_ss *ss;
  gfc_loopinfo loop;
  stmtblock_t body;
  tree tmp;
1012 1013
  tree size;
  int n;
1014 1015 1016 1017 1018 1019 1020 1021

  /* We need this to be a variable so we can increment it.  */
  gfc_put_offset_into_var (pblock, poffset, offsetvar);

  gfc_init_se (&se, NULL);

  /* Walk the array expression.  */
  ss = gfc_walk_expr (expr);
1022
  gcc_assert (ss != gfc_ss_terminator);
1023 1024 1025 1026 1027 1028 1029 1030 1031

  /* Initialize the scalarizer.  */
  gfc_init_loopinfo (&loop);
  gfc_add_ss_to_loop (&loop, ss);

  /* Initialize the loop.  */
  gfc_conv_ss_startstride (&loop);
  gfc_conv_loop_setup (&loop);

1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047
  /* Make sure the constructed array has room for the new data.  */
  if (dynamic)
    {
      /* Set SIZE to the total number of elements in the subarray.  */
      size = gfc_index_one_node;
      for (n = 0; n < loop.dimen; n++)
	{
	  tmp = gfc_get_iteration_count (loop.from[n], loop.to[n],
					 gfc_index_one_node);
	  size = fold_build2 (MULT_EXPR, gfc_array_index_type, size, tmp);
	}

      /* Grow the constructed array by SIZE elements.  */
      gfc_grow_array (&loop.pre, desc, size);
    }

1048 1049 1050 1051 1052 1053
  /* Make the loop body.  */
  gfc_mark_ss_chain_used (ss, 1);
  gfc_start_scalarized_body (&loop, &body);
  gfc_copy_loopinfo_to_se (&se, &loop);
  se.ss = ss;

1054
  gfc_trans_array_ctor_element (&body, desc, *poffset, &se, expr);
1055
  gcc_assert (se.ss == gfc_ss_terminator);
1056 1057

  /* Increment the offset.  */
1058
  tmp = build2 (PLUS_EXPR, gfc_array_index_type, *poffset, gfc_index_one_node);
1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070
  gfc_add_modify_expr (&body, *poffset, tmp);

  /* Finish the loop.  */
  gfc_trans_scalarizing_loops (&loop, &body);
  gfc_add_block_to_block (&loop.pre, &loop.post);
  tmp = gfc_finish_block (&loop.pre);
  gfc_add_expr_to_block (pblock, tmp);

  gfc_cleanup_loop (&loop);
}


1071 1072 1073 1074
/* Assign the values to the elements of an array constructor.  DYNAMIC
   is true if descriptor DESC only contains enough data for the static
   size calculated by gfc_get_array_constructor_size.  When true, memory
   for the dynamic parts must be allocated using realloc.  */
1075 1076 1077

static void
gfc_trans_array_constructor_value (stmtblock_t * pblock, tree type,
1078 1079 1080
				   tree desc, gfc_constructor * c,
				   tree * poffset, tree * offsetvar,
				   bool dynamic)
1081 1082 1083 1084
{
  tree tmp;
  stmtblock_t body;
  gfc_se se;
1085
  mpz_t size;
1086

1087
  mpz_init (size);
1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098
  for (; c; c = c->next)
    {
      /* If this is an iterator or an array, the offset must be a variable.  */
      if ((c->iterator || c->expr->rank > 0) && INTEGER_CST_P (*poffset))
	gfc_put_offset_into_var (pblock, poffset, offsetvar);

      gfc_start_block (&body);

      if (c->expr->expr_type == EXPR_ARRAY)
	{
	  /* Array constructors can be nested.  */
1099
	  gfc_trans_array_constructor_value (&body, type, desc,
1100
					     c->expr->value.constructor,
1101
					     poffset, offsetvar, dynamic);
1102 1103 1104
	}
      else if (c->expr->rank > 0)
	{
1105 1106
	  gfc_trans_array_constructor_subarray (&body, type, desc, c->expr,
						poffset, offsetvar, dynamic);
1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125
	}
      else
	{
	  /* This code really upsets the gimplifier so don't bother for now.  */
	  gfc_constructor *p;
	  HOST_WIDE_INT n;
	  HOST_WIDE_INT size;

	  p = c;
	  n = 0;
	  while (p && !(p->iterator || p->expr->expr_type != EXPR_CONSTANT))
	    {
	      p = p->next;
	      n++;
	    }
	  if (n < 4)
	    {
	      /* Scalar values.  */
	      gfc_init_se (&se, NULL);
1126 1127
	      gfc_trans_array_ctor_element (&body, desc, *poffset,
					    &se, c->expr);
1128

1129 1130
	      *poffset = fold_build2 (PLUS_EXPR, gfc_array_index_type,
				      *poffset, gfc_index_one_node);
1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147
	    }
	  else
	    {
	      /* Collect multiple scalar constants into a constructor.  */
	      tree list;
	      tree init;
	      tree bound;
	      tree tmptype;

	      p = c;
	      list = NULL_TREE;
              /* Count the number of consecutive scalar constants.  */
	      while (p && !(p->iterator
			    || p->expr->expr_type != EXPR_CONSTANT))
		{
		  gfc_init_se (&se, NULL);
		  gfc_conv_constant (&se, p->expr);
1148
		  if (p->expr->ts.type == BT_CHARACTER
1149
		      && POINTER_TYPE_P (type))
1150 1151 1152 1153
		    {
		      /* For constant character array constructors we build
			 an array of pointers.  */
		      se.expr = gfc_build_addr_expr (pchar_type_node,
1154
						     se.expr);
1155 1156
		    }
		    
1157 1158 1159 1160 1161
		  list = tree_cons (NULL_TREE, se.expr, list);
		  c = p;
		  p = p->next;
		}

1162
	      bound = build_int_cst (NULL_TREE, n - 1);
1163 1164
              /* Create an array type to hold them.  */
	      tmptype = build_range_type (gfc_array_index_type,
1165
					  gfc_index_zero_node, bound);
1166 1167
	      tmptype = build_array_type (type, tmptype);

1168
	      init = build_constructor_from_list (tmptype, nreverse (list));
1169 1170 1171 1172 1173 1174 1175 1176
	      TREE_CONSTANT (init) = 1;
	      TREE_INVARIANT (init) = 1;
	      TREE_STATIC (init) = 1;
	      /* Create a static variable to hold the data.  */
	      tmp = gfc_create_var (tmptype, "data");
	      TREE_STATIC (tmp) = 1;
	      TREE_CONSTANT (tmp) = 1;
	      TREE_INVARIANT (tmp) = 1;
1177
	      TREE_READONLY (tmp) = 1;
1178 1179 1180 1181
	      DECL_INITIAL (tmp) = init;
	      init = tmp;

	      /* Use BUILTIN_MEMCPY to assign the values.  */
1182
	      tmp = gfc_conv_descriptor_data_get (desc);
1183
	      tmp = build_fold_indirect_ref (tmp);
1184
	      tmp = gfc_build_array_ref (tmp, *poffset);
1185 1186
	      tmp = build_fold_addr_expr (tmp);
	      init = build_fold_addr_expr (init);
1187 1188

	      size = TREE_INT_CST_LOW (TYPE_SIZE_UNIT (type));
1189
	      bound = build_int_cst (NULL_TREE, n * size);
1190 1191
	      tmp = build_call_expr (built_in_decls[BUILT_IN_MEMCPY], 3,
				     tmp, init, bound);
1192 1193
	      gfc_add_expr_to_block (&body, tmp);

1194
	      *poffset = fold_build2 (PLUS_EXPR, gfc_array_index_type,
1195 1196
				      *poffset,
				      build_int_cst (gfc_array_index_type, n));
1197 1198 1199 1200 1201 1202 1203 1204
	    }
	  if (!INTEGER_CST_P (*poffset))
            {
              gfc_add_modify_expr (&body, *offsetvar, *poffset);
              *poffset = *offsetvar;
            }
	}

1205 1206 1207
      /* The frontend should already have done any expansions possible
	 at compile-time.  */
      if (!c->iterator)
1208
	{
1209 1210 1211 1212 1213 1214 1215 1216
	  /* Pass the code as is.  */
	  tmp = gfc_finish_block (&body);
	  gfc_add_expr_to_block (pblock, tmp);
	}
      else
	{
	  /* Build the implied do-loop.  */
	  tree cond;
1217 1218 1219 1220
	  tree end;
	  tree step;
	  tree loopvar;
	  tree exit_label;
1221
	  tree loopbody;
1222
	  tree tmp2;
1223
	  tree tmp_loopvar;
1224 1225 1226 1227 1228 1229 1230 1231

	  loopbody = gfc_finish_block (&body);

	  gfc_init_se (&se, NULL);
	  gfc_conv_expr (&se, c->iterator->var);
	  gfc_add_block_to_block (pblock, &se.pre);
	  loopvar = se.expr;

1232 1233 1234 1235 1236
	  /* Make a temporary, store the current value in that
	     and return it, once the loop is done.  */
	  tmp_loopvar = gfc_create_var (TREE_TYPE (loopvar), "loopvar");
	  gfc_add_modify_expr (pblock, tmp_loopvar, loopvar);

1237
	  /* Initialize the loop.  */
1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252
	  gfc_init_se (&se, NULL);
	  gfc_conv_expr_val (&se, c->iterator->start);
	  gfc_add_block_to_block (pblock, &se.pre);
	  gfc_add_modify_expr (pblock, loopvar, se.expr);

	  gfc_init_se (&se, NULL);
	  gfc_conv_expr_val (&se, c->iterator->end);
	  gfc_add_block_to_block (pblock, &se.pre);
	  end = gfc_evaluate_now (se.expr, pblock);

	  gfc_init_se (&se, NULL);
	  gfc_conv_expr_val (&se, c->iterator->step);
	  gfc_add_block_to_block (pblock, &se.pre);
	  step = gfc_evaluate_now (se.expr, pblock);

1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269
	  /* If this array expands dynamically, and the number of iterations
	     is not constant, we won't have allocated space for the static
	     part of C->EXPR's size.  Do that now.  */
	  if (dynamic && gfc_iterator_has_dynamic_bounds (c->iterator))
	    {
	      /* Get the number of iterations.  */
	      tmp = gfc_get_iteration_count (loopvar, end, step);

	      /* Get the static part of C->EXPR's size.  */
	      gfc_get_array_constructor_element_size (&size, c->expr);
	      tmp2 = gfc_conv_mpz_to_tree (size, gfc_index_integer_kind);

	      /* Grow the array by TMP * TMP2 elements.  */
	      tmp = fold_build2 (MULT_EXPR, gfc_array_index_type, tmp, tmp2);
	      gfc_grow_array (pblock, desc, tmp);
	    }

1270 1271 1272 1273
	  /* Generate the loop body.  */
	  exit_label = gfc_build_label_decl (NULL_TREE);
	  gfc_start_block (&body);

1274 1275 1276 1277 1278 1279 1280 1281 1282 1283
	  /* Generate the exit condition.  Depending on the sign of
	     the step variable we have to generate the correct
	     comparison.  */
	  tmp = fold_build2 (GT_EXPR, boolean_type_node, step, 
			     build_int_cst (TREE_TYPE (step), 0));
	  cond = fold_build3 (COND_EXPR, boolean_type_node, tmp,
			      build2 (GT_EXPR, boolean_type_node,
				      loopvar, end),
			      build2 (LT_EXPR, boolean_type_node,
				      loopvar, end));
1284 1285
	  tmp = build1_v (GOTO_EXPR, exit_label);
	  TREE_USED (exit_label) = 1;
1286
	  tmp = build3_v (COND_EXPR, cond, tmp, build_empty_stmt ());
1287 1288 1289 1290 1291
	  gfc_add_expr_to_block (&body, tmp);

	  /* The main loop body.  */
	  gfc_add_expr_to_block (&body, loopbody);

1292
	  /* Increase loop variable by step.  */
1293
	  tmp = build2 (PLUS_EXPR, TREE_TYPE (loopvar), loopvar, step);
1294 1295 1296 1297
	  gfc_add_modify_expr (&body, loopvar, tmp);

	  /* Finish the loop.  */
	  tmp = gfc_finish_block (&body);
1298
	  tmp = build1_v (LOOP_EXPR, tmp);
1299 1300 1301 1302 1303
	  gfc_add_expr_to_block (pblock, tmp);

	  /* Add the exit label.  */
	  tmp = build1_v (LABEL_EXPR, exit_label);
	  gfc_add_expr_to_block (pblock, tmp);
1304 1305 1306

	  /* Restore the original value of the loop counter.  */
	  gfc_add_modify_expr (pblock, loopvar, tmp_loopvar);
1307 1308
	}
    }
1309
  mpz_clear (size);
1310 1311 1312
}


1313 1314 1315 1316 1317 1318 1319 1320
/* Figure out the string length of a variable reference expression.
   Used by get_array_ctor_strlen.  */

static void
get_array_ctor_var_strlen (gfc_expr * expr, tree * len)
{
  gfc_ref *ref;
  gfc_typespec *ts;
1321
  mpz_t char_len;
1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332

  /* Don't bother if we already know the length is a constant.  */
  if (*len && INTEGER_CST_P (*len))
    return;

  ts = &expr->symtree->n.sym->ts;
  for (ref = expr->ref; ref; ref = ref->next)
    {
      switch (ref->type)
	{
	case REF_ARRAY:
1333
	  /* Array references don't change the string length.  */
1334 1335
	  break;

1336
	case REF_COMPONENT:
1337
	  /* Use the length of the component.  */
1338 1339 1340
	  ts = &ref->u.c.component->ts;
	  break;

1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353
	case REF_SUBSTRING:
	  if (ref->u.ss.start->expr_type != EXPR_CONSTANT
		|| ref->u.ss.start->expr_type != EXPR_CONSTANT)
	    break;
	  mpz_init_set_ui (char_len, 1);
	  mpz_add (char_len, char_len, ref->u.ss.end->value.integer);
	  mpz_sub (char_len, char_len, ref->u.ss.start->value.integer);
	  *len = gfc_conv_mpz_to_tree (char_len,
				       gfc_default_character_kind);
	  *len = convert (gfc_charlen_type_node, *len);
	  mpz_clear (char_len);
	  return;

1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365
	default:
	  /* TODO: Substrings are tricky because we can't evaluate the
	     expression more than once.  For now we just give up, and hope
	     we can figure it out elsewhere.  */
	  return;
	}
    }

  *len = ts->cl->backend_decl;
}


1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377
/* A catch-all to obtain the string length for anything that is not a
   constant, array or variable.  */
static void
get_array_ctor_all_strlen (stmtblock_t *block, gfc_expr *e, tree *len)
{
  gfc_se se;
  gfc_ss *ss;

  /* Don't bother if we already know the length is a constant.  */
  if (*len && INTEGER_CST_P (*len))
    return;

1378
  if (!e->ref && e->ts.cl && e->ts.cl->length
1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408
	&& e->ts.cl->length->expr_type == EXPR_CONSTANT)
    {
      /* This is easy.  */
      gfc_conv_const_charlen (e->ts.cl);
      *len = e->ts.cl->backend_decl;
    }
  else
    {
      /* Otherwise, be brutal even if inefficient.  */
      ss = gfc_walk_expr (e);
      gfc_init_se (&se, NULL);

      /* No function call, in case of side effects.  */
      se.no_function_call = 1;
      if (ss == gfc_ss_terminator)
	gfc_conv_expr (&se, e);
      else
	gfc_conv_expr_descriptor (&se, e, ss);

      /* Fix the value.  */
      *len = gfc_evaluate_now (se.string_length, &se.pre);

      gfc_add_block_to_block (block, &se.pre);
      gfc_add_block_to_block (block, &se.post);

      e->ts.cl->backend_decl = *len;
    }
}


1409 1410 1411
/* Figure out the string length of a character array constructor.
   Returns TRUE if all elements are character constants.  */

1412
bool
1413
get_array_ctor_strlen (stmtblock_t *block, gfc_constructor * c, tree * len)
1414 1415 1416 1417
{
  bool is_const;
  
  is_const = TRUE;
1418 1419 1420 1421 1422 1423 1424

  if (c == NULL)
    {
      *len = build_int_cstu (gfc_charlen_type_node, 0);
      return is_const;
    }

1425 1426 1427 1428 1429 1430
  for (; c; c = c->next)
    {
      switch (c->expr->expr_type)
	{
	case EXPR_CONSTANT:
	  if (!(*len && INTEGER_CST_P (*len)))
1431
	    *len = build_int_cstu (gfc_charlen_type_node,
1432 1433 1434 1435
				   c->expr->value.character.length);
	  break;

	case EXPR_ARRAY:
1436
	  if (!get_array_ctor_strlen (block, c->expr->value.constructor, len))
1437
	    is_const = false;
1438 1439 1440 1441 1442 1443 1444 1445
	  break;

	case EXPR_VARIABLE:
	  is_const = false;
	  get_array_ctor_var_strlen (c->expr, len);
	  break;

	default:
1446
	  is_const = false;
1447
	  get_array_ctor_all_strlen (block, c->expr, len);
1448 1449 1450 1451 1452 1453 1454
	  break;
	}
    }

  return is_const;
}

1455 1456 1457 1458
/* Check whether the array constructor C consists entirely of constant
   elements, and if so returns the number of those elements, otherwise
   return zero.  Note, an empty or NULL array constructor returns zero.  */

1459 1460
unsigned HOST_WIDE_INT
gfc_constant_array_constructor_p (gfc_constructor * c)
1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480
{
  unsigned HOST_WIDE_INT nelem = 0;

  while (c)
    {
      if (c->iterator
	  || c->expr->rank > 0
	  || c->expr->expr_type != EXPR_CONSTANT)
	return 0;
      c = c->next;
      nelem++;
    }
  return nelem;
}


/* Given EXPR, the constant array constructor specified by an EXPR_ARRAY,
   and the tree type of it's elements, TYPE, return a static constant
   variable that is compile-time initialized.  */

1481
tree
1482 1483 1484 1485 1486 1487 1488
gfc_build_constant_array_constructor (gfc_expr * expr, tree type)
{
  tree tmptype, list, init, tmp;
  HOST_WIDE_INT nelem;
  gfc_constructor *c;
  gfc_array_spec as;
  gfc_se se;
1489
  int i;
1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507

  /* First traverse the constructor list, converting the constants
     to tree to build an initializer.  */
  nelem = 0;
  list = NULL_TREE;
  c = expr->value.constructor;
  while (c)
    {
      gfc_init_se (&se, NULL);
      gfc_conv_constant (&se, c->expr);
      if (c->expr->ts.type == BT_CHARACTER
	  && POINTER_TYPE_P (type))
	se.expr = gfc_build_addr_expr (pchar_type_node, se.expr);
      list = tree_cons (NULL_TREE, se.expr, list);
      c = c->next;
      nelem++;
    }

1508
  /* Next determine the tree type for the array.  We use the gfortran
1509 1510 1511 1512 1513
     front-end's gfc_get_nodesc_array_type in order to create a suitable
     GFC_ARRAY_TYPE_P that may be used by the scalarizer.  */

  memset (&as, 0, sizeof (gfc_array_spec));

1514
  as.rank = expr->rank;
1515
  as.type = AS_EXPLICIT;
1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528
  if (!expr->shape)
    {
      as.lower[0] = gfc_int_expr (0);
      as.upper[0] = gfc_int_expr (nelem - 1);
    }
  else
    for (i = 0; i < expr->rank; i++)
      {
	int tmp = (int) mpz_get_si (expr->shape[i]);
	as.lower[i] = gfc_int_expr (0);
	as.upper[i] = gfc_int_expr (tmp - 1);
      }

1529
  tmptype = gfc_get_nodesc_array_type (type, &as, PACKED_STATIC);
1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558

  init = build_constructor_from_list (tmptype, nreverse (list));

  TREE_CONSTANT (init) = 1;
  TREE_INVARIANT (init) = 1;
  TREE_STATIC (init) = 1;

  tmp = gfc_create_var (tmptype, "A");
  TREE_STATIC (tmp) = 1;
  TREE_CONSTANT (tmp) = 1;
  TREE_INVARIANT (tmp) = 1;
  TREE_READONLY (tmp) = 1;
  DECL_INITIAL (tmp) = init;

  return tmp;
}


/* Translate a constant EXPR_ARRAY array constructor for the scalarizer.
   This mostly initializes the scalarizer state info structure with the
   appropriate values to directly use the array created by the function
   gfc_build_constant_array_constructor.  */

static void
gfc_trans_constant_array_constructor (gfc_loopinfo * loop,
				      gfc_ss * ss, tree type)
{
  gfc_ss_info *info;
  tree tmp;
1559
  int i;
1560 1561 1562 1563 1564 1565 1566 1567 1568 1569

  tmp = gfc_build_constant_array_constructor (ss->expr, type);

  info = &ss->data.info;

  info->descriptor = tmp;
  info->data = build_fold_addr_expr (tmp);
  info->offset = fold_build1 (NEGATE_EXPR, gfc_array_index_type,
			      loop->from[0]);

1570 1571 1572 1573 1574 1575 1576 1577
  for (i = 0; i < info->dimen; i++)
    {
      info->delta[i] = gfc_index_zero_node;
      info->start[i] = gfc_index_zero_node;
      info->end[i] = gfc_index_zero_node;
      info->stride[i] = gfc_index_one_node;
      info->dim[i] = i;
    }
1578 1579 1580 1581 1582

  if (info->dimen > loop->temp_dim)
    loop->temp_dim = info->dimen;
}

1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601
/* Helper routine of gfc_trans_array_constructor to determine if the
   bounds of the loop specified by LOOP are constant and simple enough
   to use with gfc_trans_constant_array_constructor.  Returns the
   the iteration count of the loop if suitable, and NULL_TREE otherwise.  */

static tree
constant_array_constructor_loop_size (gfc_loopinfo * loop)
{
  tree size = gfc_index_one_node;
  tree tmp;
  int i;

  for (i = 0; i < loop->dimen; i++)
    {
      /* If the bounds aren't constant, return NULL_TREE.  */
      if (!INTEGER_CST_P (loop->from[i]) || !INTEGER_CST_P (loop->to[i]))
	return NULL_TREE;
      if (!integer_zerop (loop->from[i]))
	{
1602
	  /* Only allow nonzero "from" in one-dimensional arrays.  */
1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617
	  if (loop->dimen != 1)
	    return NULL_TREE;
	  tmp = fold_build2 (MINUS_EXPR, gfc_array_index_type,
			     loop->to[i], loop->from[i]);
	}
      else
	tmp = loop->to[i];
      tmp = fold_build2 (PLUS_EXPR, gfc_array_index_type,
			 tmp, gfc_index_one_node);
      size = fold_build2 (MULT_EXPR, gfc_array_index_type, size, tmp);
    }

  return size;
}

1618

1619 1620 1621 1622 1623 1624 1625
/* Array constructors are handled by constructing a temporary, then using that
   within the scalarization loop.  This is not optimal, but seems by far the
   simplest method.  */

static void
gfc_trans_array_constructor (gfc_loopinfo * loop, gfc_ss * ss)
{
1626
  gfc_constructor *c;
1627 1628 1629 1630
  tree offset;
  tree offsetvar;
  tree desc;
  tree type;
1631
  bool dynamic;
1632 1633

  ss->data.info.dimen = loop->dimen;
1634

1635
  c = ss->expr->value.constructor;
1636 1637
  if (ss->expr->ts.type == BT_CHARACTER)
    {
1638
      bool const_string = get_array_ctor_strlen (&loop->pre, c, &ss->string_length);
1639 1640 1641
      if (!ss->string_length)
	gfc_todo_error ("complex character array constructors");

1642
      ss->expr->ts.cl->backend_decl = ss->string_length;
1643

1644 1645 1646 1647 1648
      type = gfc_get_character_type_len (ss->expr->ts.kind, ss->string_length);
      if (const_string)
	type = build_pointer_type (type);
    }
  else
1649
    type = gfc_typenode_for_spec (&ss->expr->ts);
1650

1651 1652
  /* See if the constructor determines the loop bounds.  */
  dynamic = false;
1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667

  if (ss->expr->shape && loop->dimen > 1 && loop->to[0] == NULL_TREE)
    {
      /* We have a multidimensional parameter.  */
      int n;
      for (n = 0; n < ss->expr->rank; n++)
      {
	loop->from[n] = gfc_index_zero_node;
	loop->to[n] = gfc_conv_mpz_to_tree (ss->expr->shape [n],
					    gfc_index_integer_kind);
	loop->to[n] = fold_build2 (MINUS_EXPR, gfc_array_index_type,
				   loop->to[n], gfc_index_one_node);
      }
    }

1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685
  if (loop->to[0] == NULL_TREE)
    {
      mpz_t size;

      /* We should have a 1-dimensional, zero-based loop.  */
      gcc_assert (loop->dimen == 1);
      gcc_assert (integer_zerop (loop->from[0]));

      /* Split the constructor size into a static part and a dynamic part.
	 Allocate the static size up-front and record whether the dynamic
	 size might be nonzero.  */
      mpz_init (size);
      dynamic = gfc_get_array_constructor_size (&size, c);
      mpz_sub_ui (size, size, 1);
      loop->to[0] = gfc_conv_mpz_to_tree (size, gfc_index_integer_kind);
      mpz_clear (size);
    }

1686
  /* Special case constant array constructors.  */
1687
  if (!dynamic)
1688
    {
1689
      unsigned HOST_WIDE_INT nelem = gfc_constant_array_constructor_p (c);
1690 1691
      if (nelem > 0)
	{
1692 1693
	  tree size = constant_array_constructor_loop_size (loop);
	  if (size && compare_tree_int (size, nelem) == 0)
1694 1695 1696 1697 1698 1699 1700
	    {
	      gfc_trans_constant_array_constructor (loop, ss, type);
	      return;
	    }
	}
    }

1701
  gfc_trans_create_temp_array (&loop->pre, &loop->post, loop, &ss->data.info,
1702
			       type, dynamic, true, false);
1703 1704

  desc = ss->data.info.descriptor;
1705
  offset = gfc_index_zero_node;
1706
  offsetvar = gfc_create_var_np (gfc_array_index_type, "offset");
1707
  TREE_NO_WARNING (offsetvar) = 1;
1708
  TREE_USED (offsetvar) = 0;
1709 1710 1711 1712 1713 1714 1715
  gfc_trans_array_constructor_value (&loop->pre, type, desc, c,
				     &offset, &offsetvar, dynamic);

  /* If the array grows dynamically, the upper bound of the loop variable
     is determined by the array's final upper bound.  */
  if (dynamic)
    loop->to[0] = gfc_conv_descriptor_ubound (desc, gfc_rank_cst[0]);
1716 1717 1718 1719

  if (TREE_USED (offsetvar))
    pushdecl (offsetvar);
  else
1720
    gcc_assert (INTEGER_CST_P (offset));
1721
#if 0
1722
  /* Disable bound checking for now because it's probably broken.  */
1723 1724
  if (flag_bounds_check)
    {
1725
      gcc_unreachable ();
1726 1727 1728 1729 1730
    }
#endif
}


1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771
/* INFO describes a GFC_SS_SECTION in loop LOOP, and this function is
   called after evaluating all of INFO's vector dimensions.  Go through
   each such vector dimension and see if we can now fill in any missing
   loop bounds.  */

static void
gfc_set_vector_loop_bounds (gfc_loopinfo * loop, gfc_ss_info * info)
{
  gfc_se se;
  tree tmp;
  tree desc;
  tree zero;
  int n;
  int dim;

  for (n = 0; n < loop->dimen; n++)
    {
      dim = info->dim[n];
      if (info->ref->u.ar.dimen_type[dim] == DIMEN_VECTOR
	  && loop->to[n] == NULL)
	{
	  /* Loop variable N indexes vector dimension DIM, and we don't
	     yet know the upper bound of loop variable N.  Set it to the
	     difference between the vector's upper and lower bounds.  */
	  gcc_assert (loop->from[n] == gfc_index_zero_node);
	  gcc_assert (info->subscript[dim]
		      && info->subscript[dim]->type == GFC_SS_VECTOR);

	  gfc_init_se (&se, NULL);
	  desc = info->subscript[dim]->data.info.descriptor;
	  zero = gfc_rank_cst[0];
	  tmp = fold_build2 (MINUS_EXPR, gfc_array_index_type,
			     gfc_conv_descriptor_ubound (desc, zero),
			     gfc_conv_descriptor_lbound (desc, zero));
	  tmp = gfc_evaluate_now (tmp, &loop->pre);
	  loop->to[n] = tmp;
	}
    }
}


1772 1773 1774 1775 1776 1777 1778 1779 1780 1781
/* Add the pre and post chains for all the scalar expressions in a SS chain
   to loop.  This is called after the loop parameters have been calculated,
   but before the actual scalarizing loops.  */

static void
gfc_add_loop_ss_code (gfc_loopinfo * loop, gfc_ss * ss, bool subscript)
{
  gfc_se se;
  int n;

1782 1783
  /* TODO: This can generate bad code if there are ordering dependencies.
     eg. a callee allocated function and an unknown size constructor.  */
1784
  gcc_assert (ss != NULL);
1785 1786 1787

  for (; ss != gfc_ss_terminator; ss = ss->loop_chain)
    {
1788
      gcc_assert (ss);
1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 1799 1800 1801 1802 1803 1804 1805 1806 1807 1808 1809 1810 1811

      switch (ss->type)
	{
	case GFC_SS_SCALAR:
	  /* Scalar expression.  Evaluate this now.  This includes elemental
	     dimension indices, but not array section bounds.  */
	  gfc_init_se (&se, NULL);
          gfc_conv_expr (&se, ss->expr);
          gfc_add_block_to_block (&loop->pre, &se.pre);

          if (ss->expr->ts.type != BT_CHARACTER)
            {
              /* Move the evaluation of scalar expressions outside the
                 scalarization loop.  */
              if (subscript)
                se.expr = convert(gfc_array_index_type, se.expr);
              se.expr = gfc_evaluate_now (se.expr, &loop->pre);
              gfc_add_block_to_block (&loop->pre, &se.post);
            }
          else
            gfc_add_block_to_block (&loop->post, &se.post);

	  ss->data.scalar.expr = se.expr;
1812
	  ss->string_length = se.string_length;
1813 1814 1815 1816 1817 1818 1819 1820 1821 1822
	  break;

	case GFC_SS_REFERENCE:
	  /* Scalar reference.  Evaluate this now.  */
	  gfc_init_se (&se, NULL);
	  gfc_conv_expr_reference (&se, ss->expr);
	  gfc_add_block_to_block (&loop->pre, &se.pre);
	  gfc_add_block_to_block (&loop->post, &se.post);

	  ss->data.scalar.expr = gfc_evaluate_now (se.expr, &loop->pre);
1823
	  ss->string_length = se.string_length;
1824 1825 1826
	  break;

	case GFC_SS_SECTION:
1827
	  /* Add the expressions for scalar and vector subscripts.  */
1828
	  for (n = 0; n < GFC_MAX_DIMENSIONS; n++)
1829 1830 1831 1832 1833 1834 1835 1836 1837 1838 1839 1840 1841
	    if (ss->data.info.subscript[n])
	      gfc_add_loop_ss_code (loop, ss->data.info.subscript[n], true);

	  gfc_set_vector_loop_bounds (loop, &ss->data.info);
	  break;

	case GFC_SS_VECTOR:
	  /* Get the vector's descriptor and store it in SS.  */
	  gfc_init_se (&se, NULL);
	  gfc_conv_expr_descriptor (&se, ss->expr, gfc_walk_expr (ss->expr));
	  gfc_add_block_to_block (&loop->pre, &se.pre);
	  gfc_add_block_to_block (&loop->post, &se.post);
	  ss->data.info.descriptor = se.expr;
1842 1843 1844 1845 1846 1847 1848 1849 1850 1851 1852 1853 1854 1855 1856
	  break;

	case GFC_SS_INTRINSIC:
	  gfc_add_intrinsic_ss_code (loop, ss);
	  break;

	case GFC_SS_FUNCTION:
	  /* Array function return value.  We call the function and save its
	     result in a temporary for use inside the loop.  */
	  gfc_init_se (&se, NULL);
	  se.loop = loop;
	  se.ss = ss;
	  gfc_conv_expr (&se, ss->expr);
	  gfc_add_block_to_block (&loop->pre, &se.pre);
	  gfc_add_block_to_block (&loop->post, &se.post);
1857
	  ss->string_length = se.string_length;
1858 1859 1860 1861 1862 1863
	  break;

	case GFC_SS_CONSTRUCTOR:
	  gfc_trans_array_constructor (loop, ss);
	  break;

1864
        case GFC_SS_TEMP:
1865 1866
	case GFC_SS_COMPONENT:
          /* Do nothing.  These are handled elsewhere.  */
1867 1868
          break;

1869
	default:
1870
	  gcc_unreachable ();
1871 1872 1873 1874 1875 1876 1877 1878 1879 1880 1881 1882 1883 1884 1885
	}
    }
}


/* Translate expressions for the descriptor and data pointer of a SS.  */
/*GCC ARRAYS*/

static void
gfc_conv_ss_descriptor (stmtblock_t * block, gfc_ss * ss, int base)
{
  gfc_se se;
  tree tmp;

  /* Get the descriptor for the array to be scalarized.  */
1886
  gcc_assert (ss->expr->expr_type == EXPR_VARIABLE);
1887 1888 1889 1890 1891
  gfc_init_se (&se, NULL);
  se.descriptor_only = 1;
  gfc_conv_expr_lhs (&se, ss->expr);
  gfc_add_block_to_block (block, &se.pre);
  ss->data.info.descriptor = se.expr;
1892
  ss->string_length = se.string_length;
1893 1894 1895 1896 1897 1898

  if (base)
    {
      /* Also the data pointer.  */
      tmp = gfc_conv_array_data (se.expr);
      /* If this is a variable or address of a variable we use it directly.
1899
         Otherwise we must evaluate it now to avoid breaking dependency
1900 1901 1902 1903 1904 1905 1906 1907 1908 1909 1910 1911 1912 1913
	 analysis by pulling the expressions for elemental array indices
	 inside the loop.  */
      if (!(DECL_P (tmp)
	    || (TREE_CODE (tmp) == ADDR_EXPR
		&& DECL_P (TREE_OPERAND (tmp, 0)))))
	tmp = gfc_evaluate_now (tmp, block);
      ss->data.info.data = tmp;

      tmp = gfc_conv_array_offset (se.expr);
      ss->data.info.offset = gfc_evaluate_now (tmp, block);
    }
}


1914
/* Initialize a gfc_loopinfo structure.  */
1915 1916 1917 1918 1919 1920 1921 1922 1923 1924

void
gfc_init_loopinfo (gfc_loopinfo * loop)
{
  int n;

  memset (loop, 0, sizeof (gfc_loopinfo));
  gfc_init_block (&loop->pre);
  gfc_init_block (&loop->post);

1925
  /* Initially scalarize in order.  */
1926 1927 1928 1929 1930 1931 1932
  for (n = 0; n < GFC_MAX_DIMENSIONS; n++)
    loop->order[n] = n;

  loop->ss = gfc_ss_terminator;
}


1933
/* Copies the loop variable info to a gfc_se structure. Does not copy the SS
1934 1935 1936 1937 1938 1939 1940 1941 1942 1943 1944 1945 1946 1947 1948 1949 1950 1951 1952 1953 1954 1955 1956
   chain.  */

void
gfc_copy_loopinfo_to_se (gfc_se * se, gfc_loopinfo * loop)
{
  se->loop = loop;
}


/* Return an expression for the data pointer of an array.  */

tree
gfc_conv_array_data (tree descriptor)
{
  tree type;

  type = TREE_TYPE (descriptor);
  if (GFC_ARRAY_TYPE_P (type))
    {
      if (TREE_CODE (type) == POINTER_TYPE)
        return descriptor;
      else
        {
1957
          /* Descriptorless arrays.  */
1958
	  return build_fold_addr_expr (descriptor);
1959 1960 1961
        }
    }
  else
1962
    return gfc_conv_descriptor_data_get (descriptor);
1963 1964 1965 1966 1967 1968 1969 1970 1971 1972 1973 1974 1975 1976 1977 1978 1979 1980 1981 1982 1983 1984 1985 1986 1987 1988 1989 1990 1991 1992 1993 1994 1995 1996 1997 1998 1999 2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 2010 2011 2012 2013 2014 2015 2016 2017 2018 2019 2020 2021 2022 2023 2024 2025 2026 2027 2028 2029 2030 2031 2032 2033 2034 2035 2036
}


/* Return an expression for the base offset of an array.  */

tree
gfc_conv_array_offset (tree descriptor)
{
  tree type;

  type = TREE_TYPE (descriptor);
  if (GFC_ARRAY_TYPE_P (type))
    return GFC_TYPE_ARRAY_OFFSET (type);
  else
    return gfc_conv_descriptor_offset (descriptor);
}


/* Get an expression for the array stride.  */

tree
gfc_conv_array_stride (tree descriptor, int dim)
{
  tree tmp;
  tree type;

  type = TREE_TYPE (descriptor);

  /* For descriptorless arrays use the array size.  */
  tmp = GFC_TYPE_ARRAY_STRIDE (type, dim);
  if (tmp != NULL_TREE)
    return tmp;

  tmp = gfc_conv_descriptor_stride (descriptor, gfc_rank_cst[dim]);
  return tmp;
}


/* Like gfc_conv_array_stride, but for the lower bound.  */

tree
gfc_conv_array_lbound (tree descriptor, int dim)
{
  tree tmp;
  tree type;

  type = TREE_TYPE (descriptor);

  tmp = GFC_TYPE_ARRAY_LBOUND (type, dim);
  if (tmp != NULL_TREE)
    return tmp;

  tmp = gfc_conv_descriptor_lbound (descriptor, gfc_rank_cst[dim]);
  return tmp;
}


/* Like gfc_conv_array_stride, but for the upper bound.  */

tree
gfc_conv_array_ubound (tree descriptor, int dim)
{
  tree tmp;
  tree type;

  type = TREE_TYPE (descriptor);

  tmp = GFC_TYPE_ARRAY_UBOUND (type, dim);
  if (tmp != NULL_TREE)
    return tmp;

  /* This should only ever happen when passing an assumed shape array
     as an actual parameter.  The value will never be used.  */
  if (GFC_ARRAY_TYPE_P (TREE_TYPE (descriptor)))
2037
    return gfc_index_zero_node;
2038 2039 2040 2041 2042 2043 2044 2045 2046

  tmp = gfc_conv_descriptor_ubound (descriptor, gfc_rank_cst[dim]);
  return tmp;
}


/* Generate code to perform an array index bound check.  */

static tree
2047
gfc_trans_array_bound_check (gfc_se * se, tree descriptor, tree index, int n,
2048
			     locus * where, bool check_upper)
2049 2050 2051
{
  tree fault;
  tree tmp;
2052
  char *msg;
2053
  const char * name = NULL;
2054 2055 2056 2057 2058

  if (!flag_bounds_check)
    return index;

  index = gfc_evaluate_now (index, &se->pre);
2059

2060 2061 2062 2063 2064 2065 2066 2067 2068 2069 2070 2071 2072 2073 2074 2075 2076 2077 2078 2079 2080 2081 2082 2083 2084 2085 2086 2087
  /* We find a name for the error message.  */
  if (se->ss)
    name = se->ss->expr->symtree->name;

  if (!name && se->loop && se->loop->ss && se->loop->ss->expr
      && se->loop->ss->expr->symtree)
    name = se->loop->ss->expr->symtree->name;

  if (!name && se->loop && se->loop->ss && se->loop->ss->loop_chain
      && se->loop->ss->loop_chain->expr
      && se->loop->ss->loop_chain->expr->symtree)
    name = se->loop->ss->loop_chain->expr->symtree->name;

  if (!name && se->loop && se->loop->ss && se->loop->ss->loop_chain
      && se->loop->ss->loop_chain->expr->symtree)
    name = se->loop->ss->loop_chain->expr->symtree->name;

  if (!name && se->loop && se->loop->ss && se->loop->ss->expr)
    {
      if (se->loop->ss->expr->expr_type == EXPR_FUNCTION
	  && se->loop->ss->expr->value.function.name)
	name = se->loop->ss->expr->value.function.name;
      else
	if (se->loop->ss->type == GFC_SS_CONSTRUCTOR
	    || se->loop->ss->type == GFC_SS_SCALAR)
	  name = "unnamed constant";
    }

2088 2089
  /* Check lower bound.  */
  tmp = gfc_conv_array_lbound (descriptor, n);
2090
  fault = fold_build2 (LT_EXPR, boolean_type_node, index, tmp);
2091
  if (name)
2092
    asprintf (&msg, "%s for array '%s', lower bound of dimension %d exceeded",
2093
	      gfc_msg_fault, name, n+1);
2094
  else
2095 2096 2097 2098 2099
    asprintf (&msg, "%s, lower bound of dimension %d exceeded, %%ld is "
	      "smaller than %%ld", gfc_msg_fault, n+1);
  gfc_trans_runtime_check (fault, &se->pre, where, msg,
			   fold_convert (long_integer_type_node, index),
			   fold_convert (long_integer_type_node, tmp));
2100 2101
  gfc_free (msg);

2102
  /* Check upper bound.  */
2103 2104 2105 2106 2107 2108 2109 2110
  if (check_upper)
    {
      tmp = gfc_conv_array_ubound (descriptor, n);
      fault = fold_build2 (GT_EXPR, boolean_type_node, index, tmp);
      if (name)
	asprintf (&msg, "%s for array '%s', upper bound of dimension %d "
			" exceeded", gfc_msg_fault, name, n+1);
      else
2111 2112 2113 2114 2115
	asprintf (&msg, "%s, upper bound of dimension %d exceeded, %%ld is "
		  "larger than %%ld", gfc_msg_fault, n+1);
      gfc_trans_runtime_check (fault, &se->pre, where, msg,
			       fold_convert (long_integer_type_node, index),
			       fold_convert (long_integer_type_node, tmp));
2116 2117
      gfc_free (msg);
    }
2118 2119 2120 2121 2122 2123

  return index;
}


/* Return the offset for an index.  Performs bound checking for elemental
2124
   dimensions.  Single element references are processed separately.  */
2125 2126 2127 2128 2129 2130

static tree
gfc_conv_array_index_offset (gfc_se * se, gfc_ss_info * info, int dim, int i,
			     gfc_array_ref * ar, tree stride)
{
  tree index;
2131 2132
  tree desc;
  tree data;
2133 2134 2135 2136

  /* Get the index into the array for this dimension.  */
  if (ar)
    {
2137
      gcc_assert (ar->type != AR_ELEMENT);
2138
      switch (ar->dimen_type[dim])
2139
	{
2140
	case DIMEN_ELEMENT:
2141
	  gcc_assert (i == -1);
2142
	  /* Elemental dimension.  */
2143
	  gcc_assert (info->subscript[dim]
2144
		      && info->subscript[dim]->type == GFC_SS_SCALAR);
2145 2146 2147
	  /* We've already translated this value outside the loop.  */
	  index = info->subscript[dim]->data.scalar.expr;

2148 2149 2150 2151
	  index = gfc_trans_array_bound_check (se, info->descriptor,
			index, dim, &ar->where,
			(ar->as->type != AS_ASSUMED_SIZE
			 && !ar->as->cp_was_assumed) || dim < ar->dimen - 1);
2152 2153 2154 2155 2156 2157 2158 2159 2160 2161 2162 2163 2164 2165 2166 2167 2168
	  break;

	case DIMEN_VECTOR:
	  gcc_assert (info && se->loop);
	  gcc_assert (info->subscript[dim]
		      && info->subscript[dim]->type == GFC_SS_VECTOR);
	  desc = info->subscript[dim]->data.info.descriptor;

	  /* Get a zero-based index into the vector.  */
	  index = fold_build2 (MINUS_EXPR, gfc_array_index_type,
			       se->loop->loopvar[i], se->loop->from[i]);

	  /* Multiply the index by the stride.  */
	  index = fold_build2 (MULT_EXPR, gfc_array_index_type,
			       index, gfc_conv_array_stride (desc, 0));

	  /* Read the vector to get an index into info->descriptor.  */
2169
	  data = build_fold_indirect_ref (gfc_conv_array_data (desc));
2170 2171 2172 2173
	  index = gfc_build_array_ref (data, index);
	  index = gfc_evaluate_now (index, &se->pre);

	  /* Do any bounds checking on the final info->descriptor index.  */
2174 2175 2176 2177
	  index = gfc_trans_array_bound_check (se, info->descriptor,
			index, dim, &ar->where,
			(ar->as->type != AS_ASSUMED_SIZE
			 && !ar->as->cp_was_assumed) || dim < ar->dimen - 1);
2178 2179 2180
	  break;

	case DIMEN_RANGE:
2181
	  /* Scalarized dimension.  */
2182
	  gcc_assert (info && se->loop);
2183

2184
          /* Multiply the loop variable by the stride and delta.  */
2185
	  index = se->loop->loopvar[i];
2186 2187 2188 2189 2190 2191
	  if (!integer_onep (info->stride[i]))
	    index = fold_build2 (MULT_EXPR, gfc_array_index_type, index,
				 info->stride[i]);
	  if (!integer_zerop (info->delta[i]))
	    index = fold_build2 (PLUS_EXPR, gfc_array_index_type, index,
				 info->delta[i]);
2192
	  break;
2193

2194 2195
	default:
	  gcc_unreachable ();
2196 2197 2198 2199
	}
    }
  else
    {
2200
      /* Temporary array or derived type component.  */
2201
      gcc_assert (se->loop);
2202
      index = se->loop->loopvar[se->loop->order[i]];
2203
      if (!integer_zerop (info->delta[i]))
2204 2205
	index = fold_build2 (PLUS_EXPR, gfc_array_index_type,
			     index, info->delta[i]);
2206 2207 2208
    }

  /* Multiply by the stride.  */
2209 2210
  if (!integer_onep (stride))
    index = fold_build2 (MULT_EXPR, gfc_array_index_type, index, stride);
2211 2212 2213 2214 2215 2216 2217 2218 2219 2220 2221 2222 2223 2224 2225 2226 2227 2228 2229 2230 2231 2232 2233 2234 2235

  return index;
}


/* Build a scalarized reference to an array.  */

static void
gfc_conv_scalarized_array_ref (gfc_se * se, gfc_array_ref * ar)
{
  gfc_ss_info *info;
  tree index;
  tree tmp;
  int n;

  info = &se->ss->data.info;
  if (ar)
    n = se->loop->order[0];
  else
    n = 0;

  index = gfc_conv_array_index_offset (se, info, info->dim[n], n, ar,
				       info->stride0);
  /* Add the offset for this dimension to the stored offset for all other
     dimensions.  */
2236 2237
  if (!integer_zerop (info->offset))
    index = fold_build2 (PLUS_EXPR, gfc_array_index_type, index, info->offset);
2238

2239
  tmp = build_fold_indirect_ref (info->data);
2240 2241 2242 2243 2244 2245 2246 2247 2248
  se->expr = gfc_build_array_ref (tmp, index);
}


/* Translate access of temporary array.  */

void
gfc_conv_tmp_array_ref (gfc_se * se)
{
2249
  se->string_length = se->ss->string_length;
2250 2251 2252 2253 2254 2255 2256 2257 2258 2259 2260
  gfc_conv_scalarized_array_ref (se, NULL);
}


/* Build an array reference.  se->expr already holds the array descriptor.
   This should be either a variable, indirect variable reference or component
   reference.  For arrays which do not have a descriptor, se->expr will be
   the data pointer.
   a(i, j, k) = base[offset + i * stride[0] + j * stride[1] + k * stride[2]]*/

void
2261 2262
gfc_conv_array_ref (gfc_se * se, gfc_array_ref * ar, gfc_symbol * sym,
		    locus * where)
2263 2264 2265 2266 2267 2268 2269
{
  int n;
  tree index;
  tree tmp;
  tree stride;
  gfc_se indexse;

2270
  /* Handle scalarized references separately.  */
2271 2272 2273
  if (ar->type != AR_ELEMENT)
    {
      gfc_conv_scalarized_array_ref (se, ar);
2274
      gfc_advance_se_ss_chain (se);
2275 2276 2277
      return;
    }

2278
  index = gfc_index_zero_node;
2279 2280 2281 2282

  /* Calculate the offsets from all the dimensions.  */
  for (n = 0; n < ar->dimen; n++)
    {
2283
      /* Calculate the index for this dimension.  */
2284
      gfc_init_se (&indexse, se);
2285 2286 2287
      gfc_conv_expr_type (&indexse, ar->start[n], gfc_array_index_type);
      gfc_add_block_to_block (&se->pre, &indexse.pre);

2288
      if (flag_bounds_check)
2289 2290 2291
	{
	  /* Check array bounds.  */
	  tree cond;
2292
	  char *msg;
2293

2294 2295 2296
	  /* Evaluate the indexse.expr only once.  */
	  indexse.expr = save_expr (indexse.expr);

2297
	  /* Lower bound.  */
2298
	  tmp = gfc_conv_array_lbound (se->expr, n);
2299 2300
	  cond = fold_build2 (LT_EXPR, boolean_type_node, 
			      indexse.expr, tmp);
2301
	  asprintf (&msg, "%s for array '%s', "
2302 2303 2304 2305 2306 2307
	            "lower bound of dimension %d exceeded, %%ld is smaller "
		    "than %%ld", gfc_msg_fault, sym->name, n+1);
	  gfc_trans_runtime_check (cond, &se->pre, where, msg,
				   fold_convert (long_integer_type_node,
						 indexse.expr),
				   fold_convert (long_integer_type_node, tmp));
2308
	  gfc_free (msg);
2309

2310 2311 2312 2313 2314 2315 2316 2317 2318
	  /* Upper bound, but not for the last dimension of assumed-size
	     arrays.  */
	  if (n < ar->dimen - 1
	      || (ar->as->type != AS_ASSUMED_SIZE && !ar->as->cp_was_assumed))
	    {
	      tmp = gfc_conv_array_ubound (se->expr, n);
	      cond = fold_build2 (GT_EXPR, boolean_type_node, 
				  indexse.expr, tmp);
	      asprintf (&msg, "%s for array '%s', "
2319 2320 2321 2322 2323 2324
			"upper bound of dimension %d exceeded, %%ld is "
			"greater than %%ld", gfc_msg_fault, sym->name, n+1);
	      gfc_trans_runtime_check (cond, &se->pre, where, msg,
				   fold_convert (long_integer_type_node,
						 indexse.expr),
				   fold_convert (long_integer_type_node, tmp));
2325 2326
	      gfc_free (msg);
	    }
2327 2328 2329 2330
	}

      /* Multiply the index by the stride.  */
      stride = gfc_conv_array_stride (se->expr, n);
2331 2332
      tmp = fold_build2 (MULT_EXPR, gfc_array_index_type, indexse.expr,
			 stride);
2333 2334

      /* And add it to the total.  */
2335
      index = fold_build2 (PLUS_EXPR, gfc_array_index_type, index, tmp);
2336 2337 2338 2339
    }

  tmp = gfc_conv_array_offset (se->expr);
  if (!integer_zerop (tmp))
2340
    index = fold_build2 (PLUS_EXPR, gfc_array_index_type, index, tmp);
2341 2342 2343
      
  /* Access the calculated element.  */
  tmp = gfc_conv_array_data (se->expr);
2344
  tmp = build_fold_indirect_ref (tmp);
2345 2346 2347 2348 2349 2350 2351 2352 2353 2354 2355 2356 2357 2358 2359 2360 2361 2362 2363 2364 2365 2366 2367 2368 2369 2370
  se->expr = gfc_build_array_ref (tmp, index);
}


/* Generate the code to be executed immediately before entering a
   scalarization loop.  */

static void
gfc_trans_preloop_setup (gfc_loopinfo * loop, int dim, int flag,
			 stmtblock_t * pblock)
{
  tree index;
  tree stride;
  gfc_ss_info *info;
  gfc_ss *ss;
  gfc_se se;
  int i;

  /* This code will be executed before entering the scalarization loop
     for this dimension.  */
  for (ss = loop->ss; ss != gfc_ss_terminator; ss = ss->loop_chain)
    {
      if ((ss->useflags & flag) == 0)
	continue;

      if (ss->type != GFC_SS_SECTION
2371 2372
	  && ss->type != GFC_SS_FUNCTION && ss->type != GFC_SS_CONSTRUCTOR
	  && ss->type != GFC_SS_COMPONENT)
2373 2374 2375 2376 2377 2378 2379 2380 2381 2382 2383 2384 2385 2386 2387 2388 2389 2390 2391 2392 2393 2394 2395 2396 2397 2398 2399 2400
	continue;

      info = &ss->data.info;

      if (dim >= info->dimen)
	continue;

      if (dim == info->dimen - 1)
	{
	  /* For the outermost loop calculate the offset due to any
	     elemental dimensions.  It will have been initialized with the
	     base offset of the array.  */
	  if (info->ref)
	    {
	      for (i = 0; i < info->ref->u.ar.dimen; i++)
		{
		  if (info->ref->u.ar.dimen_type[i] != DIMEN_ELEMENT)
		    continue;

		  gfc_init_se (&se, NULL);
		  se.loop = loop;
		  se.expr = info->descriptor;
		  stride = gfc_conv_array_stride (info->descriptor, i);
		  index = gfc_conv_array_index_offset (&se, info, i, -1,
						       &info->ref->u.ar,
						       stride);
		  gfc_add_block_to_block (pblock, &se.pre);

2401 2402
		  info->offset = fold_build2 (PLUS_EXPR, gfc_array_index_type,
					      info->offset, index);
2403 2404 2405 2406 2407 2408 2409 2410 2411 2412 2413 2414 2415 2416 2417 2418 2419 2420 2421 2422 2423 2424 2425 2426 2427 2428 2429 2430 2431 2432 2433 2434 2435 2436 2437 2438 2439
		  info->offset = gfc_evaluate_now (info->offset, pblock);
		}

	      i = loop->order[0];
	      stride = gfc_conv_array_stride (info->descriptor, info->dim[i]);
	    }
	  else
	    stride = gfc_conv_array_stride (info->descriptor, 0);

	  /* Calculate the stride of the innermost loop.  Hopefully this will
             allow the backend optimizers to do their stuff more effectively.
           */
	  info->stride0 = gfc_evaluate_now (stride, pblock);
	}
      else
	{
	  /* Add the offset for the previous loop dimension.  */
	  gfc_array_ref *ar;

	  if (info->ref)
	    {
	      ar = &info->ref->u.ar;
	      i = loop->order[dim + 1];
	    }
	  else
	    {
	      ar = NULL;
	      i = dim + 1;
	    }

	  gfc_init_se (&se, NULL);
	  se.loop = loop;
	  se.expr = info->descriptor;
	  stride = gfc_conv_array_stride (info->descriptor, info->dim[i]);
	  index = gfc_conv_array_index_offset (&se, info, info->dim[i], i,
					       ar, stride);
	  gfc_add_block_to_block (pblock, &se.pre);
2440 2441
	  info->offset = fold_build2 (PLUS_EXPR, gfc_array_index_type,
				      info->offset, index);
2442 2443 2444
	  info->offset = gfc_evaluate_now (info->offset, pblock);
	}

2445
      /* Remember this offset for the second loop.  */
2446 2447 2448 2449 2450 2451 2452 2453 2454 2455 2456 2457 2458 2459 2460 2461
      if (dim == loop->temp_dim - 1)
        info->saved_offset = info->offset;
    }
}


/* Start a scalarized expression.  Creates a scope and declares loop
   variables.  */

void
gfc_start_scalarized_body (gfc_loopinfo * loop, stmtblock_t * pbody)
{
  int dim;
  int n;
  int flags;

2462
  gcc_assert (!loop->array_parameter);
2463 2464 2465 2466 2467 2468 2469 2470 2471 2472 2473 2474 2475 2476 2477 2478 2479 2480 2481 2482 2483 2484 2485 2486 2487 2488 2489 2490 2491 2492 2493 2494 2495 2496 2497 2498 2499 2500 2501 2502 2503 2504 2505 2506

  for (dim = loop->dimen - 1; dim >= 0; dim--)
    {
      n = loop->order[dim];

      gfc_start_block (&loop->code[n]);

      /* Create the loop variable.  */
      loop->loopvar[n] = gfc_create_var (gfc_array_index_type, "S");

      if (dim < loop->temp_dim)
	flags = 3;
      else
	flags = 1;
      /* Calculate values that will be constant within this loop.  */
      gfc_trans_preloop_setup (loop, dim, flags, &loop->code[n]);
    }
  gfc_start_block (pbody);
}


/* Generates the actual loop code for a scalarization loop.  */

static void
gfc_trans_scalarized_loop_end (gfc_loopinfo * loop, int n,
			       stmtblock_t * pbody)
{
  stmtblock_t block;
  tree cond;
  tree tmp;
  tree loopbody;
  tree exit_label;

  loopbody = gfc_finish_block (pbody);

  /* Initialize the loopvar.  */
  gfc_add_modify_expr (&loop->code[n], loop->loopvar[n], loop->from[n]);

  exit_label = gfc_build_label_decl (NULL_TREE);

  /* Generate the loop body.  */
  gfc_init_block (&block);

  /* The exit condition.  */
2507
  cond = build2 (GT_EXPR, boolean_type_node, loop->loopvar[n], loop->to[n]);
2508 2509
  tmp = build1_v (GOTO_EXPR, exit_label);
  TREE_USED (exit_label) = 1;
2510
  tmp = build3_v (COND_EXPR, cond, tmp, build_empty_stmt ());
2511 2512 2513 2514 2515 2516
  gfc_add_expr_to_block (&block, tmp);

  /* The main body.  */
  gfc_add_expr_to_block (&block, loopbody);

  /* Increment the loopvar.  */
2517 2518
  tmp = build2 (PLUS_EXPR, gfc_array_index_type,
		loop->loopvar[n], gfc_index_one_node);
2519 2520 2521 2522
  gfc_add_modify_expr (&block, loop->loopvar[n], tmp);

  /* Build the loop.  */
  tmp = gfc_finish_block (&block);
2523
  tmp = build1_v (LOOP_EXPR, tmp);
2524 2525 2526 2527 2528 2529 2530 2531 2532 2533 2534 2535 2536 2537 2538 2539 2540 2541 2542 2543 2544 2545 2546 2547 2548 2549 2550 2551 2552 2553 2554 2555 2556 2557 2558 2559 2560 2561 2562 2563 2564 2565 2566 2567 2568 2569 2570 2571 2572 2573 2574 2575 2576 2577 2578 2579 2580 2581 2582 2583 2584 2585 2586 2587 2588 2589 2590 2591 2592 2593
  gfc_add_expr_to_block (&loop->code[n], tmp);

  /* Add the exit label.  */
  tmp = build1_v (LABEL_EXPR, exit_label);
  gfc_add_expr_to_block (&loop->code[n], tmp);
}


/* Finishes and generates the loops for a scalarized expression.  */

void
gfc_trans_scalarizing_loops (gfc_loopinfo * loop, stmtblock_t * body)
{
  int dim;
  int n;
  gfc_ss *ss;
  stmtblock_t *pblock;
  tree tmp;

  pblock = body;
  /* Generate the loops.  */
  for (dim = 0; dim < loop->dimen; dim++)
    {
      n = loop->order[dim];
      gfc_trans_scalarized_loop_end (loop, n, pblock);
      loop->loopvar[n] = NULL_TREE;
      pblock = &loop->code[n];
    }

  tmp = gfc_finish_block (pblock);
  gfc_add_expr_to_block (&loop->pre, tmp);

  /* Clear all the used flags.  */
  for (ss = loop->ss; ss; ss = ss->loop_chain)
    ss->useflags = 0;
}


/* Finish the main body of a scalarized expression, and start the secondary
   copying body.  */

void
gfc_trans_scalarized_loop_boundary (gfc_loopinfo * loop, stmtblock_t * body)
{
  int dim;
  int n;
  stmtblock_t *pblock;
  gfc_ss *ss;

  pblock = body;
  /* We finish as many loops as are used by the temporary.  */
  for (dim = 0; dim < loop->temp_dim - 1; dim++)
    {
      n = loop->order[dim];
      gfc_trans_scalarized_loop_end (loop, n, pblock);
      loop->loopvar[n] = NULL_TREE;
      pblock = &loop->code[n];
    }

  /* We don't want to finish the outermost loop entirely.  */
  n = loop->order[loop->temp_dim - 1];
  gfc_trans_scalarized_loop_end (loop, n, pblock);

  /* Restore the initial offsets.  */
  for (ss = loop->ss; ss != gfc_ss_terminator; ss = ss->loop_chain)
    {
      if ((ss->useflags & 2) == 0)
	continue;

      if (ss->type != GFC_SS_SECTION
2594 2595
	  && ss->type != GFC_SS_FUNCTION && ss->type != GFC_SS_CONSTRUCTOR
	  && ss->type != GFC_SS_COMPONENT)
2596 2597 2598 2599 2600 2601 2602 2603 2604 2605 2606 2607 2608 2609 2610 2611 2612 2613 2614 2615 2616 2617 2618 2619 2620 2621 2622 2623 2624 2625 2626 2627
	continue;

      ss->data.info.offset = ss->data.info.saved_offset;
    }

  /* Restart all the inner loops we just finished.  */
  for (dim = loop->temp_dim - 2; dim >= 0; dim--)
    {
      n = loop->order[dim];

      gfc_start_block (&loop->code[n]);

      loop->loopvar[n] = gfc_create_var (gfc_array_index_type, "Q");

      gfc_trans_preloop_setup (loop, dim, 2, &loop->code[n]);
    }

  /* Start a block for the secondary copying code.  */
  gfc_start_block (body);
}


/* Calculate the upper bound of an array section.  */

static tree
gfc_conv_section_upper_bound (gfc_ss * ss, int n, stmtblock_t * pblock)
{
  int dim;
  gfc_expr *end;
  tree desc;
  tree bound;
  gfc_se se;
2628
  gfc_ss_info *info;
2629

2630
  gcc_assert (ss->type == GFC_SS_SECTION);
2631

2632 2633
  info = &ss->data.info;
  dim = info->dim[n];
2634

2635 2636 2637 2638 2639 2640 2641 2642
  if (info->ref->u.ar.dimen_type[dim] == DIMEN_VECTOR)
    /* We'll calculate the upper bound once we have access to the
       vector's descriptor.  */
    return NULL;

  gcc_assert (info->ref->u.ar.dimen_type[dim] == DIMEN_RANGE);
  desc = info->descriptor;
  end = info->ref->u.ar.end[dim];
2643 2644 2645 2646 2647 2648 2649 2650 2651 2652 2653

  if (end)
    {
      /* The upper bound was specified.  */
      gfc_init_se (&se, NULL);
      gfc_conv_expr_type (&se, end, gfc_array_index_type);
      gfc_add_block_to_block (pblock, &se.pre);
      bound = se.expr;
    }
  else
    {
2654
      /* No upper bound was specified, so use the bound of the array.  */
2655 2656 2657 2658 2659 2660 2661 2662 2663 2664 2665 2666 2667
      bound = gfc_conv_array_ubound (desc, dim);
    }

  return bound;
}


/* Calculate the lower bound of an array section.  */

static void
gfc_conv_section_startstride (gfc_loopinfo * loop, gfc_ss * ss, int n)
{
  gfc_expr *start;
2668
  gfc_expr *end;
2669 2670 2671 2672 2673 2674
  gfc_expr *stride;
  tree desc;
  gfc_se se;
  gfc_ss_info *info;
  int dim;

2675
  gcc_assert (ss->type == GFC_SS_SECTION);
2676

2677
  info = &ss->data.info;
2678 2679
  dim = info->dim[n];

2680
  if (info->ref->u.ar.dimen_type[dim] == DIMEN_VECTOR)
2681
    {
2682 2683
      /* We use a zero-based index to access the vector.  */
      info->start[n] = gfc_index_zero_node;
2684
      info->end[n] = gfc_index_zero_node;
2685 2686
      info->stride[n] = gfc_index_one_node;
      return;
2687 2688
    }

2689 2690 2691
  gcc_assert (info->ref->u.ar.dimen_type[dim] == DIMEN_RANGE);
  desc = info->descriptor;
  start = info->ref->u.ar.start[dim];
2692
  end = info->ref->u.ar.end[dim];
2693
  stride = info->ref->u.ar.stride[dim];
2694 2695 2696 2697 2698 2699 2700 2701 2702 2703 2704 2705 2706 2707 2708 2709 2710 2711

  /* Calculate the start of the range.  For vector subscripts this will
     be the range of the vector.  */
  if (start)
    {
      /* Specified section start.  */
      gfc_init_se (&se, NULL);
      gfc_conv_expr_type (&se, start, gfc_array_index_type);
      gfc_add_block_to_block (&loop->pre, &se.pre);
      info->start[n] = se.expr;
    }
  else
    {
      /* No lower bound specified so use the bound of the array.  */
      info->start[n] = gfc_conv_array_lbound (desc, dim);
    }
  info->start[n] = gfc_evaluate_now (info->start[n], &loop->pre);

2712 2713 2714 2715 2716 2717 2718 2719 2720 2721 2722 2723 2724 2725 2726 2727 2728 2729
  /* Similarly calculate the end.  Although this is not used in the
     scalarizer, it is needed when checking bounds and where the end
     is an expression with side-effects.  */
  if (end)
    {
      /* Specified section start.  */
      gfc_init_se (&se, NULL);
      gfc_conv_expr_type (&se, end, gfc_array_index_type);
      gfc_add_block_to_block (&loop->pre, &se.pre);
      info->end[n] = se.expr;
    }
  else
    {
      /* No upper bound specified so use the bound of the array.  */
      info->end[n] = gfc_conv_array_ubound (desc, dim);
    }
  info->end[n] = gfc_evaluate_now (info->end[n], &loop->pre);

2730 2731
  /* Calculate the stride.  */
  if (stride == NULL)
2732
    info->stride[n] = gfc_index_one_node;
2733 2734 2735 2736 2737 2738 2739 2740 2741 2742 2743 2744 2745 2746 2747 2748 2749 2750 2751 2752 2753 2754 2755 2756 2757 2758 2759 2760 2761 2762 2763 2764
  else
    {
      gfc_init_se (&se, NULL);
      gfc_conv_expr_type (&se, stride, gfc_array_index_type);
      gfc_add_block_to_block (&loop->pre, &se.pre);
      info->stride[n] = gfc_evaluate_now (se.expr, &loop->pre);
    }
}


/* Calculates the range start and stride for a SS chain.  Also gets the
   descriptor and data pointer.  The range of vector subscripts is the size
   of the vector.  Array bounds are also checked.  */

void
gfc_conv_ss_startstride (gfc_loopinfo * loop)
{
  int n;
  tree tmp;
  gfc_ss *ss;
  tree desc;

  loop->dimen = 0;
  /* Determine the rank of the loop.  */
  for (ss = loop->ss;
       ss != gfc_ss_terminator && loop->dimen == 0; ss = ss->loop_chain)
    {
      switch (ss->type)
	{
	case GFC_SS_SECTION:
	case GFC_SS_CONSTRUCTOR:
	case GFC_SS_FUNCTION:
2765
	case GFC_SS_COMPONENT:
2766 2767 2768
	  loop->dimen = ss->data.info.dimen;
	  break;

2769 2770
	/* As usual, lbound and ubound are exceptions!.  */
	case GFC_SS_INTRINSIC:
2771
	  switch (ss->expr->value.function.isym->id)
2772 2773 2774 2775 2776 2777 2778 2779 2780
	    {
	    case GFC_ISYM_LBOUND:
	    case GFC_ISYM_UBOUND:
	      loop->dimen = ss->data.info.dimen;

	    default:
	      break;
	    }

2781 2782 2783 2784 2785 2786 2787 2788 2789
	default:
	  break;
	}
    }

  if (loop->dimen == 0)
    gfc_todo_error ("Unable to determine rank of expression");


2790
  /* Loop over all the SS in the chain.  */
2791 2792
  for (ss = loop->ss; ss != gfc_ss_terminator; ss = ss->loop_chain)
    {
2793 2794 2795
      if (ss->expr && ss->expr->shape && !ss->shape)
	ss->shape = ss->expr->shape;

2796 2797 2798 2799 2800 2801 2802 2803 2804 2805
      switch (ss->type)
	{
	case GFC_SS_SECTION:
	  /* Get the descriptor for the array.  */
	  gfc_conv_ss_descriptor (&loop->pre, ss, !loop->array_parameter);

	  for (n = 0; n < ss->data.info.dimen; n++)
	    gfc_conv_section_startstride (loop, ss, n);
	  break;

2806
	case GFC_SS_INTRINSIC:
2807
	  switch (ss->expr->value.function.isym->id)
2808 2809 2810 2811 2812 2813 2814 2815 2816
	    {
	    /* Fall through to supply start and stride.  */
	    case GFC_ISYM_LBOUND:
	    case GFC_ISYM_UBOUND:
	      break;
	    default:
	      continue;
	    }

2817 2818 2819 2820
	case GFC_SS_CONSTRUCTOR:
	case GFC_SS_FUNCTION:
	  for (n = 0; n < ss->data.info.dimen; n++)
	    {
2821
	      ss->data.info.start[n] = gfc_index_zero_node;
2822
	      ss->data.info.end[n] = gfc_index_zero_node;
2823
	      ss->data.info.stride[n] = gfc_index_one_node;
2824 2825 2826 2827 2828 2829 2830 2831 2832 2833 2834 2835
	    }
	  break;

	default:
	  break;
	}
    }

  /* The rest is just runtime bound checking.  */
  if (flag_bounds_check)
    {
      stmtblock_t block;
2836
      tree lbound, ubound;
2837 2838
      tree end;
      tree size[GFC_MAX_DIMENSIONS];
2839
      tree stride_pos, stride_neg, non_zerosized, tmp2;
2840
      gfc_ss_info *info;
2841
      char *msg;
2842 2843 2844 2845 2846 2847 2848 2849 2850 2851 2852 2853 2854 2855 2856
      int dim;

      gfc_start_block (&block);

      for (n = 0; n < loop->dimen; n++)
	size[n] = NULL_TREE;

      for (ss = loop->ss; ss != gfc_ss_terminator; ss = ss->loop_chain)
	{
	  if (ss->type != GFC_SS_SECTION)
	    continue;

	  /* TODO: range checking for mapped dimensions.  */
	  info = &ss->data.info;

2857 2858
	  /* This code only checks ranges.  Elemental and vector
	     dimensions are checked later.  */
2859 2860
	  for (n = 0; n < loop->dimen; n++)
	    {
2861 2862
	      bool check_upper;

2863
	      dim = info->dim[n];
2864 2865
	      if (info->ref->u.ar.dimen_type[dim] != DIMEN_RANGE)
		continue;
2866

2867 2868 2869
	      if (n == info->ref->u.ar.dimen - 1
		  && (info->ref->u.ar.as->type == AS_ASSUMED_SIZE
		      || info->ref->u.ar.as->cp_was_assumed))
2870 2871 2872
		check_upper = false;
	      else
		check_upper = true;
2873 2874 2875 2876 2877 2878 2879

	      /* Zero stride is not allowed.  */
	      tmp = fold_build2 (EQ_EXPR, boolean_type_node, info->stride[n],
				 gfc_index_zero_node);
	      asprintf (&msg, "Zero stride is not allowed, for dimension %d "
			"of array '%s'", info->dim[n]+1,
			ss->expr->symtree->name);
2880
	      gfc_trans_runtime_check (tmp, &block, &ss->expr->where, msg);
2881 2882
	      gfc_free (msg);

2883 2884 2885 2886 2887 2888 2889 2890 2891 2892 2893 2894
	      desc = ss->data.info.descriptor;

	      /* This is the run-time equivalent of resolve.c's
	         check_dimension().  The logical is more readable there
	         than it is here, with all the trees.  */
	      lbound = gfc_conv_array_lbound (desc, dim);
	      end = info->end[n];
	      if (check_upper)
		ubound = gfc_conv_array_ubound (desc, dim);
	      else
		ubound = NULL;

2895 2896 2897 2898 2899 2900 2901 2902 2903 2904 2905 2906 2907 2908 2909 2910 2911 2912 2913 2914 2915 2916 2917 2918
	      /* non_zerosized is true when the selected range is not
	         empty.  */
	      stride_pos = fold_build2 (GT_EXPR, boolean_type_node,
					info->stride[n], gfc_index_zero_node);
	      tmp = fold_build2 (LE_EXPR, boolean_type_node, info->start[n],
				 end);
	      stride_pos = fold_build2 (TRUTH_AND_EXPR, boolean_type_node,
					stride_pos, tmp);

	      stride_neg = fold_build2 (LT_EXPR, boolean_type_node,
					info->stride[n], gfc_index_zero_node);
	      tmp = fold_build2 (GE_EXPR, boolean_type_node, info->start[n],
				 end);
	      stride_neg = fold_build2 (TRUTH_AND_EXPR, boolean_type_node,
					stride_neg, tmp);
	      non_zerosized = fold_build2 (TRUTH_OR_EXPR, boolean_type_node,
					   stride_pos, stride_neg);

	      /* Check the start of the range against the lower and upper
		 bounds of the array, if the range is not empty.  */
	      tmp = fold_build2 (LT_EXPR, boolean_type_node, info->start[n],
				 lbound);
	      tmp = fold_build2 (TRUTH_AND_EXPR, boolean_type_node,
				 non_zerosized, tmp);
2919
	      asprintf (&msg, "%s, lower bound of dimension %d of array '%s'"
2920 2921 2922 2923 2924 2925 2926
			" exceeded, %%ld is smaller than %%ld", gfc_msg_fault,
			info->dim[n]+1, ss->expr->symtree->name);
	      gfc_trans_runtime_check (tmp, &block, &ss->expr->where, msg,
				       fold_convert (long_integer_type_node,
						     info->start[n]),
				       fold_convert (long_integer_type_node,
						     lbound));
2927
	      gfc_free (msg);
2928

2929 2930 2931 2932 2933 2934 2935
	      if (check_upper)
		{
		  tmp = fold_build2 (GT_EXPR, boolean_type_node,
				     info->start[n], ubound);
		  tmp = fold_build2 (TRUTH_AND_EXPR, boolean_type_node,
				     non_zerosized, tmp);
	          asprintf (&msg, "%s, upper bound of dimension %d of array "
2936 2937
			    "'%s' exceeded, %%ld is greater than %%ld",
			    gfc_msg_fault, info->dim[n]+1,
2938
			    ss->expr->symtree->name);
2939 2940 2941
		  gfc_trans_runtime_check (tmp, &block, &ss->expr->where, msg,
			fold_convert (long_integer_type_node, info->start[n]),
			fold_convert (long_integer_type_node, ubound));
2942 2943
		  gfc_free (msg);
		}
2944 2945 2946 2947 2948 2949 2950 2951 2952 2953 2954 2955 2956 2957 2958

	      /* Compute the last element of the range, which is not
		 necessarily "end" (think 0:5:3, which doesn't contain 5)
		 and check it against both lower and upper bounds.  */
	      tmp2 = fold_build2 (MINUS_EXPR, gfc_array_index_type, end,
				  info->start[n]);
	      tmp2 = fold_build2 (TRUNC_MOD_EXPR, gfc_array_index_type, tmp2,
				  info->stride[n]);
	      tmp2 = fold_build2 (MINUS_EXPR, gfc_array_index_type, end,
				  tmp2);

	      tmp = fold_build2 (LT_EXPR, boolean_type_node, tmp2, lbound);
	      tmp = fold_build2 (TRUTH_AND_EXPR, boolean_type_node,
				 non_zerosized, tmp);
	      asprintf (&msg, "%s, lower bound of dimension %d of array '%s'"
2959 2960 2961 2962 2963 2964 2965
			" exceeded, %%ld is smaller than %%ld", gfc_msg_fault,
			info->dim[n]+1, ss->expr->symtree->name);
	      gfc_trans_runtime_check (tmp, &block, &ss->expr->where, msg,
				       fold_convert (long_integer_type_node,
						     tmp2),
				       fold_convert (long_integer_type_node,
						     lbound));
2966 2967
	      gfc_free (msg);

2968 2969 2970 2971 2972 2973
	      if (check_upper)
		{
		  tmp = fold_build2 (GT_EXPR, boolean_type_node, tmp2, ubound);
		  tmp = fold_build2 (TRUTH_AND_EXPR, boolean_type_node,
				     non_zerosized, tmp);
		  asprintf (&msg, "%s, upper bound of dimension %d of array "
2974 2975
			    "'%s' exceeded, %%ld is greater than %%ld",
			    gfc_msg_fault, info->dim[n]+1,
2976
			    ss->expr->symtree->name);
2977 2978 2979
		  gfc_trans_runtime_check (tmp, &block, &ss->expr->where, msg,
			fold_convert (long_integer_type_node, tmp2),
			fold_convert (long_integer_type_node, ubound));
2980 2981
		  gfc_free (msg);
		}
2982 2983

	      /* Check the section sizes match.  */
2984 2985 2986 2987
	      tmp = fold_build2 (MINUS_EXPR, gfc_array_index_type, end,
				 info->start[n]);
	      tmp = fold_build2 (FLOOR_DIV_EXPR, gfc_array_index_type, tmp,
				 info->stride[n]);
2988 2989 2990 2991
	      /* We remember the size of the first section, and check all the
	         others against this.  */
	      if (size[n])
		{
2992 2993
		  tree tmp3
		    = fold_build2 (NE_EXPR, boolean_type_node, tmp, size[n]);
2994
		  asprintf (&msg, "%s, size mismatch for dimension %d "
2995 2996 2997 2998 2999
			    "of array '%s' (%%ld/%%ld)", gfc_msg_bounds,
			    info->dim[n]+1, ss->expr->symtree->name);
		  gfc_trans_runtime_check (tmp3, &block, &ss->expr->where, msg,
			fold_convert (long_integer_type_node, tmp),
			fold_convert (long_integer_type_node, size[n]));
3000
		  gfc_free (msg);
3001 3002 3003 3004 3005 3006 3007 3008 3009 3010 3011 3012
		}
	      else
		size[n] = gfc_evaluate_now (tmp, &block);
	    }
	}

      tmp = gfc_finish_block (&block);
      gfc_add_expr_to_block (&loop->pre, tmp);
    }
}


3013
/* Return true if the two SS could be aliased, i.e. both point to the same data
3014 3015 3016 3017 3018 3019 3020 3021 3022 3023 3024 3025 3026 3027 3028 3029 3030 3031 3032 3033
   object.  */
/* TODO: resolve aliases based on frontend expressions.  */

static int
gfc_could_be_alias (gfc_ss * lss, gfc_ss * rss)
{
  gfc_ref *lref;
  gfc_ref *rref;
  gfc_symbol *lsym;
  gfc_symbol *rsym;

  lsym = lss->expr->symtree->n.sym;
  rsym = rss->expr->symtree->n.sym;
  if (gfc_symbols_could_alias (lsym, rsym))
    return 1;

  if (rsym->ts.type != BT_DERIVED
      && lsym->ts.type != BT_DERIVED)
    return 0;

3034
  /* For derived types we must check all the component types.  We can ignore
3035 3036 3037 3038 3039 3040 3041 3042 3043 3044 3045 3046 3047 3048 3049 3050 3051 3052 3053 3054 3055 3056 3057 3058 3059 3060 3061 3062 3063 3064 3065 3066 3067 3068 3069 3070 3071 3072 3073 3074 3075 3076 3077 3078 3079 3080 3081 3082 3083 3084 3085 3086 3087 3088 3089 3090 3091 3092
     array references as these will have the same base type as the previous
     component ref.  */
  for (lref = lss->expr->ref; lref != lss->data.info.ref; lref = lref->next)
    {
      if (lref->type != REF_COMPONENT)
	continue;

      if (gfc_symbols_could_alias (lref->u.c.sym, rsym))
	return 1;

      for (rref = rss->expr->ref; rref != rss->data.info.ref;
	   rref = rref->next)
	{
	  if (rref->type != REF_COMPONENT)
	    continue;

	  if (gfc_symbols_could_alias (lref->u.c.sym, rref->u.c.sym))
	    return 1;
	}
    }

  for (rref = rss->expr->ref; rref != rss->data.info.ref; rref = rref->next)
    {
      if (rref->type != REF_COMPONENT)
	break;

      if (gfc_symbols_could_alias (rref->u.c.sym, lsym))
	return 1;
    }

  return 0;
}


/* Resolve array data dependencies.  Creates a temporary if required.  */
/* TODO: Calc dependencies with gfc_expr rather than gfc_ss, and move to
   dependency.c.  */

void
gfc_conv_resolve_dependencies (gfc_loopinfo * loop, gfc_ss * dest,
			       gfc_ss * rss)
{
  gfc_ss *ss;
  gfc_ref *lref;
  gfc_ref *rref;
  gfc_ref *aref;
  int nDepend = 0;
  int temp_dim = 0;

  loop->temp_ss = NULL;
  aref = dest->data.info.ref;
  temp_dim = 0;

  for (ss = rss; ss != gfc_ss_terminator; ss = ss->next)
    {
      if (ss->type != GFC_SS_SECTION)
	continue;

3093 3094
      if (gfc_could_be_alias (dest, ss)
	    || gfc_are_equivalenced_arrays (dest->expr, ss->expr))
3095 3096 3097 3098 3099 3100 3101 3102 3103 3104 3105
	{
	  nDepend = 1;
	  break;
	}

      if (dest->expr->symtree->n.sym == ss->expr->symtree->n.sym)
	{
	  lref = dest->expr->ref;
	  rref = ss->expr->ref;

	  nDepend = gfc_dep_resolver (lref, rref);
3106 3107
	  if (nDepend == 1)
	    break;
3108 3109 3110 3111 3112 3113 3114 3115 3116 3117 3118 3119 3120 3121 3122 3123
#if 0
	  /* TODO : loop shifting.  */
	  if (nDepend == 1)
	    {
	      /* Mark the dimensions for LOOP SHIFTING */
	      for (n = 0; n < loop->dimen; n++)
	        {
	          int dim = dest->data.info.dim[n];

		  if (lref->u.ar.dimen_type[dim] == DIMEN_VECTOR)
		    depends[n] = 2;
		  else if (! gfc_is_same_range (&lref->u.ar,
						&rref->u.ar, dim, 0))
		    depends[n] = 1;
	         }

3124
	      /* Put all the dimensions with dependencies in the
3125 3126 3127 3128
		 innermost loops.  */
	      dim = 0;
	      for (n = 0; n < loop->dimen; n++)
		{
3129
		  gcc_assert (loop->order[n] == n);
3130 3131 3132 3133 3134 3135 3136 3137 3138 3139
		  if (depends[n])
		  loop->order[dim++] = n;
		}
	      temp_dim = dim;
	      for (n = 0; n < loop->dimen; n++)
	        {
		  if (! depends[n])
		  loop->order[dim++] = n;
		}

3140
	      gcc_assert (dim == loop->dimen);
3141 3142 3143 3144 3145 3146 3147 3148
	      break;
	    }
#endif
	}
    }

  if (nDepend == 1)
    {
3149 3150 3151 3152
      tree base_type = gfc_typenode_for_spec (&dest->expr->ts);
      if (GFC_ARRAY_TYPE_P (base_type)
	  || GFC_DESCRIPTOR_TYPE_P (base_type))
	base_type = gfc_get_element_type (base_type);
3153 3154
      loop->temp_ss = gfc_get_ss ();
      loop->temp_ss->type = GFC_SS_TEMP;
3155
      loop->temp_ss->data.temp.type = base_type;
3156
      loop->temp_ss->string_length = dest->string_length;
3157 3158 3159 3160 3161 3162 3163 3164 3165
      loop->temp_ss->data.temp.dimen = loop->dimen;
      loop->temp_ss->next = gfc_ss_terminator;
      gfc_add_ss_to_loop (loop, loop->temp_ss);
    }
  else
    loop->temp_ss = NULL;
}


3166
/* Initialize the scalarization loop.  Creates the loop variables.  Determines
3167 3168 3169
   the range of the loop variables.  Creates a temporary if required.
   Calculates how to transform from loop variables to array indices for each
   expression.  Also generates code for scalar expressions which have been
3170
   moved outside the loop.  */
3171 3172 3173 3174 3175 3176 3177 3178 3179 3180 3181 3182

void
gfc_conv_loop_setup (gfc_loopinfo * loop)
{
  int n;
  int dim;
  gfc_ss_info *info;
  gfc_ss_info *specinfo;
  gfc_ss *ss;
  tree tmp;
  tree len;
  gfc_ss *loopspec[GFC_MAX_DIMENSIONS];
3183 3184
  bool dynamic[GFC_MAX_DIMENSIONS];
  gfc_constructor *c;
3185 3186 3187 3188 3189 3190 3191
  mpz_t *cshape;
  mpz_t i;

  mpz_init (i);
  for (n = 0; n < loop->dimen; n++)
    {
      loopspec[n] = NULL;
3192
      dynamic[n] = false;
3193 3194 3195 3196
      /* We use one SS term, and use that to determine the bounds of the
         loop for this dimension.  We try to pick the simplest term.  */
      for (ss = loop->ss; ss != gfc_ss_terminator; ss = ss->loop_chain)
	{
3197
	  if (ss->shape)
3198 3199 3200 3201 3202 3203 3204 3205
	    {
	      /* The frontend has worked out the size for us.  */
	      loopspec[n] = ss;
	      continue;
	    }

	  if (ss->type == GFC_SS_CONSTRUCTOR)
	    {
3206
	      /* An unknown size constructor will always be rank one.
3207
		 Higher rank constructors will either have known shape,
3208
		 or still be wrapped in a call to reshape.  */
3209
	      gcc_assert (loop->dimen == 1);
3210 3211 3212 3213 3214 3215 3216 3217 3218

	      /* Always prefer to use the constructor bounds if the size
		 can be determined at compile time.  Prefer not to otherwise,
		 since the general case involves realloc, and it's better to
		 avoid that overhead if possible.  */
	      c = ss->expr->value.constructor;
	      dynamic[n] = gfc_get_array_constructor_size (&i, c);
	      if (!dynamic[n] || !loopspec[n])
		loopspec[n] = ss;
3219 3220 3221
	      continue;
	    }

3222
	  /* TODO: Pick the best bound if we have a choice between a
3223
	     function and something else.  */
3224 3225 3226 3227 3228 3229
          if (ss->type == GFC_SS_FUNCTION)
            {
              loopspec[n] = ss;
              continue;
            }

3230 3231 3232 3233 3234 3235 3236 3237 3238
	  if (ss->type != GFC_SS_SECTION)
	    continue;

	  if (loopspec[n])
	    specinfo = &loopspec[n]->data.info;
	  else
	    specinfo = NULL;
	  info = &ss->data.info;

3239 3240
	  if (!specinfo)
	    loopspec[n] = ss;
3241
	  /* Criteria for choosing a loop specifier (most important first):
3242
	     doesn't need realloc
3243 3244 3245 3246 3247
	     stride of one
	     known stride
	     known lower bound
	     known upper bound
	   */
3248
	  else if (loopspec[n]->type == GFC_SS_CONSTRUCTOR && dynamic[n])
3249
	    loopspec[n] = ss;
3250 3251 3252 3253 3254 3255 3256 3257 3258 3259 3260 3261 3262
	  else if (integer_onep (info->stride[n])
		   && !integer_onep (specinfo->stride[n]))
	    loopspec[n] = ss;
	  else if (INTEGER_CST_P (info->stride[n])
		   && !INTEGER_CST_P (specinfo->stride[n]))
	    loopspec[n] = ss;
	  else if (INTEGER_CST_P (info->start[n])
		   && !INTEGER_CST_P (specinfo->start[n]))
	    loopspec[n] = ss;
	  /* We don't work out the upper bound.
	     else if (INTEGER_CST_P (info->finish[n])
	     && ! INTEGER_CST_P (specinfo->finish[n]))
	     loopspec[n] = ss; */
3263 3264 3265 3266 3267 3268 3269 3270
	}

      if (!loopspec[n])
	gfc_todo_error ("Unable to find scalarization loop specifier");

      info = &loopspec[n]->data.info;

      /* Set the extents of this range.  */
3271
      cshape = loopspec[n]->shape;
3272 3273 3274 3275 3276 3277 3278 3279 3280
      if (cshape && INTEGER_CST_P (info->start[n])
	  && INTEGER_CST_P (info->stride[n]))
	{
	  loop->from[n] = info->start[n];
	  mpz_set (i, cshape[n]);
	  mpz_sub_ui (i, i, 1);
	  /* To = from + (size - 1) * stride.  */
	  tmp = gfc_conv_mpz_to_tree (i, gfc_index_integer_kind);
	  if (!integer_onep (info->stride[n]))
3281 3282 3283 3284
	    tmp = fold_build2 (MULT_EXPR, gfc_array_index_type,
			       tmp, info->stride[n]);
	  loop->to[n] = fold_build2 (PLUS_EXPR, gfc_array_index_type,
				     loop->from[n], tmp);
3285 3286 3287 3288 3289 3290 3291
	}
      else
	{
	  loop->from[n] = info->start[n];
	  switch (loopspec[n]->type)
	    {
	    case GFC_SS_CONSTRUCTOR:
3292 3293 3294
	      /* The upper bound is calculated when we expand the
		 constructor.  */
	      gcc_assert (loop->to[n] == NULL_TREE);
3295 3296 3297 3298 3299 3300 3301
	      break;

	    case GFC_SS_SECTION:
	      loop->to[n] = gfc_conv_section_upper_bound (loopspec[n], n,
							  &loop->pre);
	      break;

3302 3303
            case GFC_SS_FUNCTION:
	      /* The loop bound will be set when we generate the call.  */
3304
              gcc_assert (loop->to[n] == NULL_TREE);
3305 3306
              break;

3307
	    default:
3308
	      gcc_unreachable ();
3309 3310 3311 3312 3313
	    }
	}

      /* Transform everything so we have a simple incrementing variable.  */
      if (integer_onep (info->stride[n]))
3314
	info->delta[n] = gfc_index_zero_node;
3315 3316 3317 3318 3319 3320 3321 3322
      else
	{
	  /* Set the delta for this section.  */
	  info->delta[n] = gfc_evaluate_now (loop->from[n], &loop->pre);
	  /* Number of iterations is (end - start + step) / step.
	     with start = 0, this simplifies to
	     last = end / step;
	     for (i = 0; i<=last; i++){...};  */
3323 3324 3325 3326
	  tmp = fold_build2 (MINUS_EXPR, gfc_array_index_type,
			     loop->to[n], loop->from[n]);
	  tmp = fold_build2 (TRUNC_DIV_EXPR, gfc_array_index_type, 
			     tmp, info->stride[n]);
3327 3328
	  loop->to[n] = gfc_evaluate_now (tmp, &loop->pre);
	  /* Make the loop variable start at 0.  */
3329
	  loop->from[n] = gfc_index_zero_node;
3330 3331 3332
	}
    }

3333 3334 3335 3336 3337
  /* Add all the scalar code that can be taken out of the loops.
     This may include calculating the loop bounds, so do it before
     allocating the temporary.  */
  gfc_add_loop_ss_code (loop, loop->ss, false);

3338 3339 3340
  /* If we want a temporary then create it.  */
  if (loop->temp_ss != NULL)
    {
3341
      gcc_assert (loop->temp_ss->type == GFC_SS_TEMP);
3342
      tmp = loop->temp_ss->data.temp.type;
3343
      len = loop->temp_ss->string_length;
3344 3345 3346 3347
      n = loop->temp_ss->data.temp.dimen;
      memset (&loop->temp_ss->data.info, 0, sizeof (gfc_ss_info));
      loop->temp_ss->type = GFC_SS_SECTION;
      loop->temp_ss->data.info.dimen = n;
3348 3349
      gfc_trans_create_temp_array (&loop->pre, &loop->post, loop,
				   &loop->temp_ss->data.info, tmp, false, true,
3350
				   false);
3351 3352 3353 3354 3355 3356 3357 3358 3359 3360 3361 3362 3363 3364 3365
    }

  for (n = 0; n < loop->temp_dim; n++)
    loopspec[loop->order[n]] = NULL;

  mpz_clear (i);

  /* For array parameters we don't have loop variables, so don't calculate the
     translations.  */
  if (loop->array_parameter)
    return;

  /* Calculate the translation from loop variables to array indices.  */
  for (ss = loop->ss; ss != gfc_ss_terminator; ss = ss->loop_chain)
    {
3366
      if (ss->type != GFC_SS_SECTION && ss->type != GFC_SS_COMPONENT)
3367 3368 3369 3370 3371 3372 3373 3374
	continue;

      info = &ss->data.info;

      for (n = 0; n < info->dimen; n++)
	{
	  dim = info->dim[n];

3375
	  /* If we are specifying the range the delta is already set.  */
3376 3377 3378 3379
	  if (loopspec[n] != ss)
	    {
	      /* Calculate the offset relative to the loop variable.
	         First multiply by the stride.  */
3380 3381 3382 3383
	      tmp = loop->from[n];
	      if (!integer_onep (info->stride[n]))
		tmp = fold_build2 (MULT_EXPR, gfc_array_index_type,
				   tmp, info->stride[n]);
3384 3385

	      /* Then subtract this from our starting value.  */
3386 3387
	      tmp = fold_build2 (MINUS_EXPR, gfc_array_index_type,
				 info->start[n], tmp);
3388 3389 3390 3391 3392 3393 3394 3395 3396 3397

	      info->delta[n] = gfc_evaluate_now (tmp, &loop->pre);
	    }
	}
    }
}


/* Fills in an array descriptor, and returns the size of the array.  The size
   will be a simple_val, ie a variable or a constant.  Also calculates the
3398
   offset of the base.  Returns the size of the array.
3399 3400 3401 3402 3403 3404 3405 3406 3407 3408 3409 3410 3411 3412 3413 3414 3415 3416 3417 3418 3419 3420 3421 3422 3423 3424 3425
   {
    stride = 1;
    offset = 0;
    for (n = 0; n < rank; n++)
      {
        a.lbound[n] = specified_lower_bound;
        offset = offset + a.lbond[n] * stride;
        size = 1 - lbound;
        a.ubound[n] = specified_upper_bound;
        a.stride[n] = stride;
        size = ubound + size; //size = ubound + 1 - lbound
        stride = stride * size;
      }
    return (stride);
   }  */
/*GCC ARRAYS*/

static tree
gfc_array_init_size (tree descriptor, int rank, tree * poffset,
		     gfc_expr ** lower, gfc_expr ** upper,
		     stmtblock_t * pblock)
{
  tree type;
  tree tmp;
  tree size;
  tree offset;
  tree stride;
3426 3427 3428 3429 3430 3431 3432
  tree cond;
  tree or_expr;
  tree thencase;
  tree elsecase;
  tree var;
  stmtblock_t thenblock;
  stmtblock_t elseblock;
3433 3434 3435 3436 3437 3438
  gfc_expr *ubound;
  gfc_se se;
  int n;

  type = TREE_TYPE (descriptor);

3439 3440
  stride = gfc_index_one_node;
  offset = gfc_index_zero_node;
3441 3442 3443

  /* Set the dtype.  */
  tmp = gfc_conv_descriptor_dtype (descriptor);
3444
  gfc_add_modify_expr (pblock, tmp, gfc_get_dtype (TREE_TYPE (descriptor)));
3445

3446 3447
  or_expr = NULL_TREE;

3448 3449 3450 3451 3452 3453 3454 3455 3456 3457 3458
  for (n = 0; n < rank; n++)
    {
      /* We have 3 possibilities for determining the size of the array:
         lower == NULL    => lbound = 1, ubound = upper[n]
         upper[n] = NULL  => lbound = 1, ubound = lower[n]
         upper[n] != NULL => lbound = lower[n], ubound = upper[n]  */
      ubound = upper[n];

      /* Set lower bound.  */
      gfc_init_se (&se, NULL);
      if (lower == NULL)
3459
	se.expr = gfc_index_one_node;
3460 3461
      else
	{
3462
	  gcc_assert (lower[n]);
3463 3464 3465 3466 3467 3468 3469
          if (ubound)
            {
	      gfc_conv_expr_type (&se, lower[n], gfc_array_index_type);
	      gfc_add_block_to_block (pblock, &se.pre);
            }
          else
            {
3470
              se.expr = gfc_index_one_node;
3471 3472 3473 3474 3475 3476 3477
              ubound = lower[n];
            }
	}
      tmp = gfc_conv_descriptor_lbound (descriptor, gfc_rank_cst[n]);
      gfc_add_modify_expr (pblock, tmp, se.expr);

      /* Work out the offset for this component.  */
3478 3479
      tmp = fold_build2 (MULT_EXPR, gfc_array_index_type, se.expr, stride);
      offset = fold_build2 (MINUS_EXPR, gfc_array_index_type, offset, tmp);
3480 3481

      /* Start the calculation for the size of this dimension.  */
3482 3483
      size = build2 (MINUS_EXPR, gfc_array_index_type,
		     gfc_index_one_node, se.expr);
3484 3485 3486

      /* Set upper bound.  */
      gfc_init_se (&se, NULL);
3487
      gcc_assert (ubound);
3488 3489 3490 3491 3492 3493 3494 3495 3496 3497 3498
      gfc_conv_expr_type (&se, ubound, gfc_array_index_type);
      gfc_add_block_to_block (pblock, &se.pre);

      tmp = gfc_conv_descriptor_ubound (descriptor, gfc_rank_cst[n]);
      gfc_add_modify_expr (pblock, tmp, se.expr);

      /* Store the stride.  */
      tmp = gfc_conv_descriptor_stride (descriptor, gfc_rank_cst[n]);
      gfc_add_modify_expr (pblock, tmp, stride);

      /* Calculate the size of this dimension.  */
3499
      size = fold_build2 (PLUS_EXPR, gfc_array_index_type, se.expr, size);
3500

3501
      /* Check whether the size for this dimension is negative.  */
3502 3503 3504 3505 3506 3507 3508
      cond = fold_build2 (LE_EXPR, boolean_type_node, size,
			  gfc_index_zero_node);
      if (n == 0)
	or_expr = cond;
      else
	or_expr = fold_build2 (TRUTH_OR_EXPR, boolean_type_node, or_expr, cond);

3509
      /* Multiply the stride by the number of elements in this dimension.  */
3510
      stride = fold_build2 (MULT_EXPR, gfc_array_index_type, stride, size);
3511 3512 3513 3514 3515 3516
      stride = gfc_evaluate_now (stride, pblock);
    }

  /* The stride is the number of elements in the array, so multiply by the
     size of an element to get the total size.  */
  tmp = TYPE_SIZE_UNIT (gfc_get_element_type (type));
3517 3518
  size = fold_build2 (MULT_EXPR, gfc_array_index_type, stride,
		      fold_convert (gfc_array_index_type, tmp));
3519 3520 3521 3522 3523 3524 3525

  if (poffset != NULL)
    {
      offset = gfc_evaluate_now (offset, pblock);
      *poffset = offset;
    }

3526 3527 3528 3529 3530
  if (integer_zerop (or_expr))
    return size;
  if (integer_onep (or_expr))
    return gfc_index_zero_node;

3531 3532 3533 3534 3535 3536 3537 3538 3539 3540 3541 3542 3543 3544
  var = gfc_create_var (TREE_TYPE (size), "size");
  gfc_start_block (&thenblock);
  gfc_add_modify_expr (&thenblock, var, gfc_index_zero_node);
  thencase = gfc_finish_block (&thenblock);

  gfc_start_block (&elseblock);
  gfc_add_modify_expr (&elseblock, var, size);
  elsecase = gfc_finish_block (&elseblock);

  tmp = gfc_evaluate_now (or_expr, pblock);
  tmp = build3_v (COND_EXPR, tmp, thencase, elsecase);
  gfc_add_expr_to_block (pblock, tmp);

  return var;
3545 3546 3547
}


3548
/* Initializes the descriptor and generates a call to _gfor_allocate.  Does
3549 3550 3551
   the work for an ALLOCATE statement.  */
/*GCC ARRAYS*/

3552 3553
bool
gfc_array_allocate (gfc_se * se, gfc_expr * expr, tree pstat)
3554 3555 3556 3557 3558 3559 3560
{
  tree tmp;
  tree pointer;
  tree offset;
  tree size;
  gfc_expr **lower;
  gfc_expr **upper;
Paul Thomas committed
3561 3562
  gfc_ref *ref, *prev_ref = NULL;
  bool allocatable_array;
3563 3564 3565 3566 3567 3568 3569

  ref = expr->ref;

  /* Find the last reference in the chain.  */
  while (ref && ref->next != NULL)
    {
      gcc_assert (ref->type != REF_ARRAY || ref->u.ar.type == AR_ELEMENT);
Paul Thomas committed
3570
      prev_ref = ref;
3571 3572 3573 3574 3575
      ref = ref->next;
    }

  if (ref == NULL || ref->type != REF_ARRAY)
    return false;
3576

Paul Thomas committed
3577 3578 3579 3580 3581
  if (!prev_ref)
    allocatable_array = expr->symtree->n.sym->attr.allocatable;
  else
    allocatable_array = prev_ref->u.c.component->allocatable;

3582 3583 3584 3585 3586 3587 3588 3589 3590
  /* Figure out the size of the array.  */
  switch (ref->u.ar.type)
    {
    case AR_ELEMENT:
      lower = NULL;
      upper = ref->u.ar.start;
      break;

    case AR_FULL:
3591
      gcc_assert (ref->u.ar.as->type == AS_EXPLICIT);
3592 3593 3594 3595 3596 3597 3598 3599 3600 3601 3602

      lower = ref->u.ar.as->lower;
      upper = ref->u.ar.as->upper;
      break;

    case AR_SECTION:
      lower = ref->u.ar.start;
      upper = ref->u.ar.end;
      break;

    default:
3603
      gcc_unreachable ();
3604 3605 3606 3607 3608 3609 3610
      break;
    }

  size = gfc_array_init_size (se->expr, ref->u.ar.as->rank, &offset,
			      lower, upper, &se->pre);

  /* Allocate memory to store the data.  */
3611 3612
  pointer = gfc_conv_descriptor_data_get (se->expr);
  STRIP_NOPS (pointer);
3613

3614 3615
  /* The allocate_array variants take the old pointer as first argument.  */
  if (allocatable_array)
3616
    tmp = gfc_allocate_array_with_status (&se->pre, pointer, size, pstat);
3617
  else
3618
    tmp = gfc_allocate_with_status (&se->pre, size, pstat);
3619
  tmp = build2 (MODIFY_EXPR, void_type_node, pointer, tmp);
3620 3621 3622 3623
  gfc_add_expr_to_block (&se->pre, tmp);

  tmp = gfc_conv_descriptor_offset (se->expr);
  gfc_add_modify_expr (&se->pre, tmp, offset);
3624

Paul Thomas committed
3625 3626 3627 3628 3629 3630 3631 3632
  if (expr->ts.type == BT_DERIVED
	&& expr->ts.derived->attr.alloc_comp)
    {
      tmp = gfc_nullify_alloc_comp (expr->ts.derived, se->expr,
				    ref->u.ar.as->rank);
      gfc_add_expr_to_block (&se->pre, tmp);
    }

3633
  return true;
3634 3635 3636 3637 3638 3639 3640 3641
}


/* Deallocate an array variable.  Also used when an allocated variable goes
   out of scope.  */
/*GCC ARRAYS*/

tree
3642
gfc_array_deallocate (tree descriptor, tree pstat)
3643 3644 3645 3646 3647 3648 3649
{
  tree var;
  tree tmp;
  stmtblock_t block;

  gfc_start_block (&block);
  /* Get a pointer to the data.  */
3650 3651
  var = gfc_conv_descriptor_data_get (descriptor);
  STRIP_NOPS (var);
3652 3653

  /* Parameter is the address of the data component.  */
3654
  tmp = gfc_deallocate_with_status (var, pstat, false);
3655 3656
  gfc_add_expr_to_block (&block, tmp);

3657 3658 3659 3660 3661
  /* Zero the data pointer.  */
  tmp = build2 (MODIFY_EXPR, void_type_node,
                var, build_int_cst (TREE_TYPE (var), 0));
  gfc_add_expr_to_block (&block, tmp);

3662 3663 3664 3665 3666 3667 3668 3669 3670 3671 3672 3673 3674 3675 3676 3677 3678
  return gfc_finish_block (&block);
}


/* Create an array constructor from an initialization expression.
   We assume the frontend already did any expansions and conversions.  */

tree
gfc_conv_array_initializer (tree type, gfc_expr * expr)
{
  gfc_constructor *c;
  tree tmp;
  mpz_t maxval;
  gfc_se se;
  HOST_WIDE_INT hi;
  unsigned HOST_WIDE_INT lo;
  tree index, range;
3679
  VEC(constructor_elt,gc) *v = NULL;
3680 3681 3682 3683 3684 3685 3686 3687

  switch (expr->expr_type)
    {
    case EXPR_CONSTANT:
    case EXPR_STRUCTURE:
      /* A single scalar or derived type value.  Create an array with all
         elements equal to that value.  */
      gfc_init_se (&se, NULL);
3688 3689 3690 3691 3692
      
      if (expr->expr_type == EXPR_CONSTANT)
	gfc_conv_constant (&se, expr);
      else
	gfc_conv_structure (&se, expr, 1);
3693 3694

      tmp = TYPE_MAX_VALUE (TYPE_DOMAIN (type));
3695
      gcc_assert (tmp && INTEGER_CST_P (tmp));
3696 3697 3698 3699 3700 3701 3702 3703
      hi = TREE_INT_CST_HIGH (tmp);
      lo = TREE_INT_CST_LOW (tmp);
      lo++;
      if (lo == 0)
	hi++;
      /* This will probably eat buckets of memory for large arrays.  */
      while (hi != 0 || lo != 0)
        {
3704
	  CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, se.expr);
3705 3706 3707 3708 3709 3710 3711
          if (lo == 0)
            hi--;
          lo--;
        }
      break;

    case EXPR_ARRAY:
3712
      /* Create a vector of all the elements.  */
3713 3714 3715 3716 3717 3718 3719 3720 3721 3722 3723 3724 3725 3726 3727 3728 3729 3730 3731 3732 3733 3734 3735 3736 3737 3738 3739 3740 3741 3742 3743
      for (c = expr->value.constructor; c; c = c->next)
        {
          if (c->iterator)
            {
              /* Problems occur when we get something like
                 integer :: a(lots) = (/(i, i=1,lots)/)  */
              /* TODO: Unexpanded array initializers.  */
              internal_error
                ("Possible frontend bug: array constructor not expanded");
	    }
          if (mpz_cmp_si (c->n.offset, 0) != 0)
            index = gfc_conv_mpz_to_tree (c->n.offset, gfc_index_integer_kind);
          else
            index = NULL_TREE;
	  mpz_init (maxval);
          if (mpz_cmp_si (c->repeat, 0) != 0)
            {
              tree tmp1, tmp2;

              mpz_set (maxval, c->repeat);
              mpz_add (maxval, c->n.offset, maxval);
              mpz_sub_ui (maxval, maxval, 1);
              tmp2 = gfc_conv_mpz_to_tree (maxval, gfc_index_integer_kind);
              if (mpz_cmp_si (c->n.offset, 0) != 0)
                {
                  mpz_add_ui (maxval, c->n.offset, 1);
                  tmp1 = gfc_conv_mpz_to_tree (maxval, gfc_index_integer_kind);
                }
              else
                tmp1 = gfc_conv_mpz_to_tree (c->n.offset, gfc_index_integer_kind);

3744
              range = build2 (RANGE_EXPR, integer_type_node, tmp1, tmp2);
3745 3746 3747 3748 3749 3750 3751 3752 3753 3754 3755
            }
          else
            range = NULL;
	  mpz_clear (maxval);

          gfc_init_se (&se, NULL);
	  switch (c->expr->expr_type)
	    {
	    case EXPR_CONSTANT:
	      gfc_conv_constant (&se, c->expr);
              if (range == NULL_TREE)
3756
		CONSTRUCTOR_APPEND_ELT (v, index, se.expr);
3757 3758 3759
              else
                {
                  if (index != NULL_TREE)
3760 3761
		    CONSTRUCTOR_APPEND_ELT (v, index, se.expr);
		  CONSTRUCTOR_APPEND_ELT (v, range, se.expr);
3762 3763 3764 3765 3766
                }
	      break;

	    case EXPR_STRUCTURE:
              gfc_conv_structure (&se, c->expr, 1);
3767
	      CONSTRUCTOR_APPEND_ELT (v, index, se.expr);
3768 3769 3770
	      break;

	    default:
3771
	      gcc_unreachable ();
3772 3773 3774 3775
	    }
        }
      break;

Paul Thomas committed
3776 3777 3778
    case EXPR_NULL:
      return gfc_build_null_descriptor (type);

3779
    default:
3780
      gcc_unreachable ();
3781 3782 3783
    }

  /* Create a constructor from the list of elements.  */
3784
  tmp = build_constructor (type, v);
3785 3786 3787 3788 3789 3790 3791 3792 3793 3794 3795 3796 3797 3798 3799 3800 3801 3802 3803 3804 3805 3806 3807 3808 3809 3810
  TREE_CONSTANT (tmp) = 1;
  TREE_INVARIANT (tmp) = 1;
  return tmp;
}


/* Generate code to evaluate non-constant array bounds.  Sets *poffset and
   returns the size (in elements) of the array.  */

static tree
gfc_trans_array_bounds (tree type, gfc_symbol * sym, tree * poffset,
                        stmtblock_t * pblock)
{
  gfc_array_spec *as;
  tree size;
  tree stride;
  tree offset;
  tree ubound;
  tree lbound;
  tree tmp;
  gfc_se se;

  int dim;

  as = sym->as;

3811 3812
  size = gfc_index_one_node;
  offset = gfc_index_zero_node;
3813 3814 3815 3816 3817 3818 3819 3820 3821 3822 3823 3824 3825 3826 3827 3828 3829 3830 3831
  for (dim = 0; dim < as->rank; dim++)
    {
      /* Evaluate non-constant array bound expressions.  */
      lbound = GFC_TYPE_ARRAY_LBOUND (type, dim);
      if (as->lower[dim] && !INTEGER_CST_P (lbound))
        {
          gfc_init_se (&se, NULL);
          gfc_conv_expr_type (&se, as->lower[dim], gfc_array_index_type);
          gfc_add_block_to_block (pblock, &se.pre);
          gfc_add_modify_expr (pblock, lbound, se.expr);
        }
      ubound = GFC_TYPE_ARRAY_UBOUND (type, dim);
      if (as->upper[dim] && !INTEGER_CST_P (ubound))
        {
          gfc_init_se (&se, NULL);
          gfc_conv_expr_type (&se, as->upper[dim], gfc_array_index_type);
          gfc_add_block_to_block (pblock, &se.pre);
          gfc_add_modify_expr (pblock, ubound, se.expr);
        }
3832
      /* The offset of this dimension.  offset = offset - lbound * stride.  */
3833 3834
      tmp = fold_build2 (MULT_EXPR, gfc_array_index_type, lbound, size);
      offset = fold_build2 (MINUS_EXPR, gfc_array_index_type, offset, tmp);
3835 3836 3837 3838 3839

      /* The size of this dimension, and the stride of the next.  */
      if (dim + 1 < as->rank)
        stride = GFC_TYPE_ARRAY_STRIDE (type, dim + 1);
      else
3840
	stride = GFC_TYPE_ARRAY_SIZE (type);
3841 3842 3843 3844

      if (ubound != NULL_TREE && !(stride && INTEGER_CST_P (stride)))
        {
          /* Calculate stride = size * (ubound + 1 - lbound).  */
3845 3846 3847 3848
          tmp = fold_build2 (MINUS_EXPR, gfc_array_index_type,
			     gfc_index_one_node, lbound);
          tmp = fold_build2 (PLUS_EXPR, gfc_array_index_type, ubound, tmp);
          tmp = fold_build2 (MULT_EXPR, gfc_array_index_type, size, tmp);
3849 3850 3851 3852
          if (stride)
            gfc_add_modify_expr (pblock, stride, tmp);
          else
            stride = gfc_evaluate_now (tmp, pblock);
Paul Thomas committed
3853 3854 3855 3856 3857 3858 3859 3860

	  /* Make sure that negative size arrays are translated
	     to being zero size.  */
	  tmp = build2 (GE_EXPR, boolean_type_node,
			stride, gfc_index_zero_node);
	  tmp = build3 (COND_EXPR, gfc_array_index_type, tmp,
			stride, gfc_index_zero_node);
	  gfc_add_modify_expr (pblock, stride, tmp);
3861 3862 3863 3864 3865
        }

      size = stride;
    }

3866 3867
  gfc_trans_vla_type_sizes (sym, pblock);

3868 3869 3870 3871 3872 3873 3874 3875 3876 3877 3878 3879 3880 3881 3882 3883 3884
  *poffset = offset;
  return size;
}


/* Generate code to initialize/allocate an array variable.  */

tree
gfc_trans_auto_array_allocation (tree decl, gfc_symbol * sym, tree fnbody)
{
  stmtblock_t block;
  tree type;
  tree tmp;
  tree size;
  tree offset;
  bool onstack;

3885
  gcc_assert (!(sym->attr.pointer || sym->attr.allocatable));
3886 3887 3888 3889 3890 3891

  /* Do nothing for USEd variables.  */
  if (sym->attr.use_assoc)
    return fnbody;

  type = TREE_TYPE (decl);
3892
  gcc_assert (GFC_ARRAY_TYPE_P (type));
3893 3894 3895 3896 3897 3898 3899 3900
  onstack = TREE_CODE (type) != POINTER_TYPE;

  gfc_start_block (&block);

  /* Evaluate character string length.  */
  if (sym->ts.type == BT_CHARACTER
      && onstack && !INTEGER_CST_P (sym->ts.cl->backend_decl))
    {
3901
      gfc_conv_string_length (sym->ts.cl, &block);
3902

3903 3904
      gfc_trans_vla_type_sizes (sym, &block);

3905
      /* Emit a DECL_EXPR for this variable, which will cause the
3906
	 gimplifier to allocate storage, and all that good stuff.  */
3907
      tmp = build1 (DECL_EXPR, TREE_TYPE (decl), decl);
3908 3909 3910 3911 3912 3913 3914 3915 3916 3917 3918
      gfc_add_expr_to_block (&block, tmp);
    }

  if (onstack)
    {
      gfc_add_expr_to_block (&block, fnbody);
      return gfc_finish_block (&block);
    }

  type = TREE_TYPE (type);

3919 3920
  gcc_assert (!sym->attr.use_assoc);
  gcc_assert (!TREE_STATIC (decl));
3921
  gcc_assert (!sym->module);
3922 3923 3924

  if (sym->ts.type == BT_CHARACTER
      && !INTEGER_CST_P (sym->ts.cl->backend_decl))
3925
    gfc_conv_string_length (sym->ts.cl, &block);
3926 3927 3928

  size = gfc_trans_array_bounds (type, sym, &offset, &block);

Asher Langton committed
3929 3930 3931 3932 3933 3934 3935 3936 3937
  /* Don't actually allocate space for Cray Pointees.  */
  if (sym->attr.cray_pointee)
    {
      if (TREE_CODE (GFC_TYPE_ARRAY_OFFSET (type)) == VAR_DECL)
	gfc_add_modify_expr (&block, GFC_TYPE_ARRAY_OFFSET (type), offset);
      gfc_add_expr_to_block (&block, fnbody);
      return gfc_finish_block (&block);
    }

3938 3939 3940
  /* The size is the number of elements in the array, so multiply by the
     size of an element to get the total size.  */
  tmp = TYPE_SIZE_UNIT (gfc_get_element_type (type));
3941 3942
  size = fold_build2 (MULT_EXPR, gfc_array_index_type, size,
		      fold_convert (gfc_array_index_type, tmp));
3943 3944

  /* Allocate memory to hold the data.  */
3945
  tmp = gfc_call_malloc (&block, TREE_TYPE (decl), size);
3946 3947 3948 3949 3950 3951 3952 3953
  gfc_add_modify_expr (&block, decl, tmp);

  /* Set offset of the array.  */
  if (TREE_CODE (GFC_TYPE_ARRAY_OFFSET (type)) == VAR_DECL)
    gfc_add_modify_expr (&block, GFC_TYPE_ARRAY_OFFSET (type), offset);


  /* Automatic arrays should not have initializers.  */
3954
  gcc_assert (!sym->value);
3955 3956 3957 3958

  gfc_add_expr_to_block (&block, fnbody);

  /* Free the temporary.  */
3959
  tmp = gfc_call_free (convert (pvoid_type_node, decl));
3960 3961 3962 3963 3964 3965 3966 3967 3968 3969 3970 3971 3972 3973 3974 3975
  gfc_add_expr_to_block (&block, tmp);

  return gfc_finish_block (&block);
}


/* Generate entry and exit code for g77 calling convention arrays.  */

tree
gfc_trans_g77_array (gfc_symbol * sym, tree body)
{
  tree parm;
  tree type;
  locus loc;
  tree offset;
  tree tmp;
3976
  tree stmt;  
3977 3978 3979 3980 3981 3982 3983 3984
  stmtblock_t block;

  gfc_get_backend_locus (&loc);
  gfc_set_backend_locus (&sym->declared_at);

  /* Descriptor type.  */
  parm = sym->backend_decl;
  type = TREE_TYPE (parm);
3985
  gcc_assert (GFC_ARRAY_TYPE_P (type));
3986 3987 3988 3989

  gfc_start_block (&block);

  if (sym->ts.type == BT_CHARACTER
3990
      && TREE_CODE (sym->ts.cl->backend_decl) == VAR_DECL)
3991
    gfc_conv_string_length (sym->ts.cl, &block);
3992 3993 3994 3995 3996 3997 3998 3999

  /* Evaluate the bounds of the array.  */
  gfc_trans_array_bounds (type, sym, &offset, &block);

  /* Set the offset.  */
  if (TREE_CODE (GFC_TYPE_ARRAY_OFFSET (type)) == VAR_DECL)
    gfc_add_modify_expr (&block, GFC_TYPE_ARRAY_OFFSET (type), offset);

4000
  /* Set the pointer itself if we aren't using the parameter directly.  */
4001 4002 4003 4004 4005
  if (TREE_CODE (parm) != PARM_DECL)
    {
      tmp = convert (TREE_TYPE (parm), GFC_DECL_SAVED_DESCRIPTOR (parm));
      gfc_add_modify_expr (&block, parm, tmp);
    }
4006
  stmt = gfc_finish_block (&block);
4007 4008 4009 4010

  gfc_set_backend_locus (&loc);

  gfc_start_block (&block);
4011

4012
  /* Add the initialization code to the start of the function.  */
4013 4014 4015 4016 4017 4018 4019 4020

  if (sym->attr.optional || sym->attr.not_always_present)
    {
      tmp = gfc_conv_expr_present (sym);
      stmt = build3_v (COND_EXPR, tmp, stmt, build_empty_stmt ());
    }
  
  gfc_add_expr_to_block (&block, stmt);
4021 4022 4023 4024 4025 4026 4027 4028 4029 4030 4031 4032 4033 4034 4035 4036 4037 4038 4039 4040 4041 4042 4043 4044 4045 4046 4047 4048 4049 4050 4051 4052 4053
  gfc_add_expr_to_block (&block, body);

  return gfc_finish_block (&block);
}


/* Modify the descriptor of an array parameter so that it has the
   correct lower bound.  Also move the upper bound accordingly.
   If the array is not packed, it will be copied into a temporary.
   For each dimension we set the new lower and upper bounds.  Then we copy the
   stride and calculate the offset for this dimension.  We also work out
   what the stride of a packed array would be, and see it the two match.
   If the array need repacking, we set the stride to the values we just
   calculated, recalculate the offset and copy the array data.
   Code is also added to copy the data back at the end of the function.
   */

tree
gfc_trans_dummy_array_bias (gfc_symbol * sym, tree tmpdesc, tree body)
{
  tree size;
  tree type;
  tree offset;
  locus loc;
  stmtblock_t block;
  stmtblock_t cleanup;
  tree lbound;
  tree ubound;
  tree dubound;
  tree dlbound;
  tree dumdesc;
  tree tmp;
  tree stmt;
4054
  tree stride, stride2;
4055 4056 4057 4058 4059 4060 4061
  tree stmt_packed;
  tree stmt_unpacked;
  tree partial;
  gfc_se se;
  int n;
  int checkparm;
  int no_repack;
4062
  bool optional_arg;
4063

4064 4065 4066 4067
  /* Do nothing for pointer and allocatable arrays.  */
  if (sym->attr.pointer || sym->attr.allocatable)
    return body;

4068 4069 4070 4071 4072 4073 4074 4075
  if (sym->attr.dummy && gfc_is_nodesc_array (sym))
    return gfc_trans_g77_array (sym, body);

  gfc_get_backend_locus (&loc);
  gfc_set_backend_locus (&sym->declared_at);

  /* Descriptor type.  */
  type = TREE_TYPE (tmpdesc);
4076
  gcc_assert (GFC_ARRAY_TYPE_P (type));
4077
  dumdesc = GFC_DECL_SAVED_DESCRIPTOR (tmpdesc);
4078
  dumdesc = build_fold_indirect_ref (dumdesc);
4079 4080 4081
  gfc_start_block (&block);

  if (sym->ts.type == BT_CHARACTER
4082
      && TREE_CODE (sym->ts.cl->backend_decl) == VAR_DECL)
4083
    gfc_conv_string_length (sym->ts.cl, &block);
4084 4085 4086 4087 4088 4089 4090 4091 4092 4093 4094 4095 4096 4097

  checkparm = (sym->as->type == AS_EXPLICIT && flag_bounds_check);

  no_repack = !(GFC_DECL_PACKED_ARRAY (tmpdesc)
                || GFC_DECL_PARTIAL_PACKED_ARRAY (tmpdesc));

  if (GFC_DECL_PARTIAL_PACKED_ARRAY (tmpdesc))
    {
      /* For non-constant shape arrays we only check if the first dimension
         is contiguous.  Repacking higher dimensions wouldn't gain us
         anything as we still don't know the array stride.  */
      partial = gfc_create_var (boolean_type_node, "partial");
      TREE_USED (partial) = 1;
      tmp = gfc_conv_descriptor_stride (dumdesc, gfc_rank_cst[0]);
4098
      tmp = fold_build2 (EQ_EXPR, boolean_type_node, tmp, gfc_index_one_node);
4099 4100 4101 4102 4103 4104 4105 4106 4107 4108 4109 4110 4111 4112 4113
      gfc_add_modify_expr (&block, partial, tmp);
    }
  else
    {
      partial = NULL_TREE;
    }

  /* The naming of stmt_unpacked and stmt_packed may be counter-intuitive
     here, however I think it does the right thing.  */
  if (no_repack)
    {
      /* Set the first stride.  */
      stride = gfc_conv_descriptor_stride (dumdesc, gfc_rank_cst[0]);
      stride = gfc_evaluate_now (stride, &block);

4114
      tmp = build2 (EQ_EXPR, boolean_type_node, stride, gfc_index_zero_node);
4115 4116
      tmp = build3 (COND_EXPR, gfc_array_index_type, tmp,
		    gfc_index_one_node, stride);
4117 4118 4119 4120 4121 4122 4123 4124
      stride = GFC_TYPE_ARRAY_STRIDE (type, 0);
      gfc_add_modify_expr (&block, stride, tmp);

      /* Allow the user to disable array repacking.  */
      stmt_unpacked = NULL_TREE;
    }
  else
    {
4125
      gcc_assert (integer_onep (GFC_TYPE_ARRAY_STRIDE (type, 0)));
4126
      /* A library call to repack the array if necessary.  */
4127
      tmp = GFC_DECL_SAVED_DESCRIPTOR (tmpdesc);
4128
      stmt_unpacked = build_call_expr (gfor_fndecl_in_pack, 1, tmp);
4129

4130
      stride = gfc_index_one_node;
4131 4132 4133 4134 4135
    }

  /* This is for the case where the array data is used directly without
     calling the repack function.  */
  if (no_repack || partial != NULL_TREE)
4136
    stmt_packed = gfc_conv_descriptor_data_get (dumdesc);
4137 4138 4139 4140 4141 4142 4143
  else
    stmt_packed = NULL_TREE;

  /* Assign the data pointer.  */
  if (stmt_packed != NULL_TREE && stmt_unpacked != NULL_TREE)
    {
      /* Don't repack unknown shape arrays when the first stride is 1.  */
4144 4145
      tmp = build3 (COND_EXPR, TREE_TYPE (stmt_packed), partial,
		    stmt_packed, stmt_unpacked);
4146 4147 4148
    }
  else
    tmp = stmt_packed != NULL_TREE ? stmt_packed : stmt_unpacked;
4149
  gfc_add_modify_expr (&block, tmpdesc, fold_convert (type, tmp));
4150

4151 4152
  offset = gfc_index_zero_node;
  size = gfc_index_one_node;
4153 4154 4155 4156 4157 4158 4159 4160 4161 4162 4163 4164 4165 4166 4167 4168 4169 4170 4171 4172

  /* Evaluate the bounds of the array.  */
  for (n = 0; n < sym->as->rank; n++)
    {
      if (checkparm || !sym->as->upper[n])
	{
	  /* Get the bounds of the actual parameter.  */
	  dubound = gfc_conv_descriptor_ubound (dumdesc, gfc_rank_cst[n]);
	  dlbound = gfc_conv_descriptor_lbound (dumdesc, gfc_rank_cst[n]);
	}
      else
        {
	  dubound = NULL_TREE;
	  dlbound = NULL_TREE;
        }

      lbound = GFC_TYPE_ARRAY_LBOUND (type, n);
      if (!INTEGER_CST_P (lbound))
        {
          gfc_init_se (&se, NULL);
4173
          gfc_conv_expr_type (&se, sym->as->lower[n],
4174 4175 4176 4177 4178 4179 4180 4181 4182 4183 4184 4185 4186 4187 4188 4189 4190 4191 4192 4193 4194 4195 4196
                              gfc_array_index_type);
          gfc_add_block_to_block (&block, &se.pre);
          gfc_add_modify_expr (&block, lbound, se.expr);
        }

      ubound = GFC_TYPE_ARRAY_UBOUND (type, n);
      /* Set the desired upper bound.  */
      if (sym->as->upper[n])
	{
	  /* We know what we want the upper bound to be.  */
          if (!INTEGER_CST_P (ubound))
            {
	      gfc_init_se (&se, NULL);
	      gfc_conv_expr_type (&se, sym->as->upper[n],
                                  gfc_array_index_type);
	      gfc_add_block_to_block (&block, &se.pre);
              gfc_add_modify_expr (&block, ubound, se.expr);
            }

	  /* Check the sizes match.  */
	  if (checkparm)
	    {
	      /* Check (ubound(a) - lbound(a) == ubound(b) - lbound(b)).  */
4197
	      char * msg;
4198

4199 4200
	      tmp = fold_build2 (MINUS_EXPR, gfc_array_index_type,
				 ubound, lbound);
4201
              stride2 = build2 (MINUS_EXPR, gfc_array_index_type,
4202
			       dubound, dlbound);
4203
              tmp = fold_build2 (NE_EXPR, gfc_array_index_type, tmp, stride2);
4204 4205
	      asprintf (&msg, "%s for dimension %d of array '%s'",
			gfc_msg_bounds, n+1, sym->name);
4206
	      gfc_trans_runtime_check (tmp, &block, &loc, msg);
4207
	      gfc_free (msg);
4208 4209 4210 4211 4212 4213
	    }
	}
      else
	{
	  /* For assumed shape arrays move the upper bound by the same amount
	     as the lower bound.  */
4214
          tmp = build2 (MINUS_EXPR, gfc_array_index_type, dubound, dlbound);
4215
          tmp = fold_build2 (PLUS_EXPR, gfc_array_index_type, tmp, lbound);
4216 4217
          gfc_add_modify_expr (&block, ubound, tmp);
	}
4218
      /* The offset of this dimension.  offset = offset - lbound * stride.  */
4219 4220
      tmp = fold_build2 (MULT_EXPR, gfc_array_index_type, lbound, stride);
      offset = fold_build2 (MINUS_EXPR, gfc_array_index_type, offset, tmp);
4221 4222 4223 4224 4225 4226 4227 4228 4229 4230 4231 4232 4233 4234 4235 4236 4237 4238 4239 4240

      /* The size of this dimension, and the stride of the next.  */
      if (n + 1 < sym->as->rank)
        {
          stride = GFC_TYPE_ARRAY_STRIDE (type, n + 1);

          if (no_repack || partial != NULL_TREE)
            {
              stmt_unpacked =
                gfc_conv_descriptor_stride (dumdesc, gfc_rank_cst[n+1]);
            }

          /* Figure out the stride if not a known constant.  */
          if (!INTEGER_CST_P (stride))
            {
              if (no_repack)
                stmt_packed = NULL_TREE;
              else
                {
                  /* Calculate stride = size * (ubound + 1 - lbound).  */
4241 4242 4243 4244 4245 4246
                  tmp = fold_build2 (MINUS_EXPR, gfc_array_index_type,
				     gfc_index_one_node, lbound);
                  tmp = fold_build2 (PLUS_EXPR, gfc_array_index_type,
				     ubound, tmp);
                  size = fold_build2 (MULT_EXPR, gfc_array_index_type,
				      size, tmp);
4247 4248 4249 4250 4251
                  stmt_packed = size;
                }

              /* Assign the stride.  */
              if (stmt_packed != NULL_TREE && stmt_unpacked != NULL_TREE)
4252 4253
		tmp = build3 (COND_EXPR, gfc_array_index_type, partial,
			      stmt_unpacked, stmt_packed);
4254 4255 4256 4257 4258
              else
                tmp = (stmt_packed != NULL_TREE) ? stmt_packed : stmt_unpacked;
              gfc_add_modify_expr (&block, stride, tmp);
            }
        }
4259 4260 4261 4262 4263 4264 4265 4266 4267 4268 4269 4270 4271 4272 4273 4274
      else
	{
	  stride = GFC_TYPE_ARRAY_SIZE (type);

	  if (stride && !INTEGER_CST_P (stride))
	    {
	      /* Calculate size = stride * (ubound + 1 - lbound).  */
	      tmp = fold_build2 (MINUS_EXPR, gfc_array_index_type,
				 gfc_index_one_node, lbound);
	      tmp = fold_build2 (PLUS_EXPR, gfc_array_index_type,
				 ubound, tmp);
	      tmp = fold_build2 (MULT_EXPR, gfc_array_index_type,
				 GFC_TYPE_ARRAY_STRIDE (type, n), tmp);
	      gfc_add_modify_expr (&block, stride, tmp);
	    }
	}
4275 4276 4277 4278 4279 4280
    }

  /* Set the offset.  */
  if (TREE_CODE (GFC_TYPE_ARRAY_OFFSET (type)) == VAR_DECL)
    gfc_add_modify_expr (&block, GFC_TYPE_ARRAY_OFFSET (type), offset);

4281 4282
  gfc_trans_vla_type_sizes (sym, &block);

4283 4284 4285 4286 4287 4288
  stmt = gfc_finish_block (&block);

  gfc_start_block (&block);

  /* Only do the entry/initialization code if the arg is present.  */
  dumdesc = GFC_DECL_SAVED_DESCRIPTOR (tmpdesc);
Jakub Jelinek committed
4289 4290 4291
  optional_arg = (sym->attr.optional
		  || (sym->ns->proc_name->attr.entry_master
		      && sym->attr.dummy));
4292
  if (optional_arg)
4293 4294
    {
      tmp = gfc_conv_expr_present (sym);
4295
      stmt = build3_v (COND_EXPR, tmp, stmt, build_empty_stmt ());
4296 4297 4298 4299 4300 4301 4302 4303 4304 4305 4306 4307 4308 4309
    }
  gfc_add_expr_to_block (&block, stmt);

  /* Add the main function body.  */
  gfc_add_expr_to_block (&block, body);

  /* Cleanup code.  */
  if (!no_repack)
    {
      gfc_start_block (&cleanup);
      
      if (sym->attr.intent != INTENT_IN)
	{
	  /* Copy the data back.  */
4310
	  tmp = build_call_expr (gfor_fndecl_in_unpack, 2, dumdesc, tmpdesc);
4311 4312 4313 4314
	  gfc_add_expr_to_block (&cleanup, tmp);
	}

      /* Free the temporary.  */
4315
      tmp = gfc_call_free (tmpdesc);
4316 4317 4318 4319 4320
      gfc_add_expr_to_block (&cleanup, tmp);

      stmt = gfc_finish_block (&cleanup);
	
      /* Only do the cleanup if the array was repacked.  */
4321
      tmp = build_fold_indirect_ref (dumdesc);
4322
      tmp = gfc_conv_descriptor_data_get (tmp);
4323 4324
      tmp = build2 (NE_EXPR, boolean_type_node, tmp, tmpdesc);
      stmt = build3_v (COND_EXPR, tmp, stmt, build_empty_stmt ());
4325

4326
      if (optional_arg)
4327 4328
        {
          tmp = gfc_conv_expr_present (sym);
4329
          stmt = build3_v (COND_EXPR, tmp, stmt, build_empty_stmt ());
4330 4331 4332 4333 4334 4335 4336 4337 4338
        }
      gfc_add_expr_to_block (&block, stmt);
    }
  /* We don't need to free any memory allocated by internal_pack as it will
     be freed at the end of the function by pop_context.  */
  return gfc_finish_block (&block);
}


4339
/* Convert an array for passing as an actual argument.  Expressions and
4340
   vector subscripts are evaluated and stored in a temporary, which is then
4341 4342
   passed.  For whole arrays the descriptor is passed.  For array sections
   a modified copy of the descriptor is passed, but using the original data.
4343 4344 4345 4346

   This function is also used for array pointer assignments, and there
   are three cases:

4347
     - se->want_pointer && !se->direct_byref
4348 4349 4350
	 EXPR is an actual argument.  On exit, se->expr contains a
	 pointer to the array descriptor.

4351
     - !se->want_pointer && !se->direct_byref
4352 4353 4354 4355
	 EXPR is an actual argument to an intrinsic function or the
	 left-hand side of a pointer assignment.  On exit, se->expr
	 contains the descriptor for EXPR.

4356
     - !se->want_pointer && se->direct_byref
4357 4358 4359 4360
	 EXPR is the right-hand side of a pointer assignment and
	 se->expr is the descriptor for the previously-evaluated
	 left-hand side.  The function creates an assignment from
	 EXPR to se->expr.  */
4361 4362 4363 4364 4365 4366 4367 4368 4369 4370 4371 4372 4373 4374 4375 4376

void
gfc_conv_expr_descriptor (gfc_se * se, gfc_expr * expr, gfc_ss * ss)
{
  gfc_loopinfo loop;
  gfc_ss *secss;
  gfc_ss_info *info;
  int need_tmp;
  int n;
  tree tmp;
  tree desc;
  stmtblock_t block;
  tree start;
  tree offset;
  int full;

4377
  gcc_assert (ss != gfc_ss_terminator);
4378

4379 4380
  /* Special case things we know we can pass easily.  */
  switch (expr->expr_type)
4381
    {
4382 4383 4384
    case EXPR_VARIABLE:
      /* If we have a linear array section, we can pass it directly.
	 Otherwise we need to copy it into a temporary.  */
4385 4386 4387 4388 4389 4390

      /* Find the SS for the array section.  */
      secss = ss;
      while (secss != gfc_ss_terminator && secss->type != GFC_SS_SECTION)
	secss = secss->next;

4391
      gcc_assert (secss != gfc_ss_terminator);
4392 4393 4394 4395 4396
      info = &secss->data.info;

      /* Get the descriptor for the array.  */
      gfc_conv_ss_descriptor (&se->pre, secss, 0);
      desc = info->descriptor;
4397 4398 4399 4400 4401

      need_tmp = gfc_ref_needs_temporary_p (expr->ref);
      if (need_tmp)
	full = 0;
      else if (GFC_ARRAY_TYPE_P (TREE_TYPE (desc)))
4402 4403 4404 4405 4406 4407 4408 4409 4410
	{
	  /* Create a new descriptor if the array doesn't have one.  */
	  full = 0;
	}
      else if (info->ref->u.ar.type == AR_FULL)
	full = 1;
      else if (se->direct_byref)
	full = 0;
      else
4411
	full = gfc_full_array_ref_p (info->ref);
4412

4413 4414 4415 4416 4417 4418 4419 4420 4421 4422
      if (full)
	{
	  if (se->direct_byref)
	    {
	      /* Copy the descriptor for pointer assignments.  */
	      gfc_add_modify_expr (&se->pre, se->expr, desc);
	    }
	  else if (se->want_pointer)
	    {
	      /* We pass full arrays directly.  This means that pointers and
4423
		 allocatable arrays should also work.  */
4424
	      se->expr = build_fold_addr_expr (desc);
4425 4426 4427 4428 4429
	    }
	  else
	    {
	      se->expr = desc;
	    }
4430

4431
	  if (expr->ts.type == BT_CHARACTER)
4432 4433
	    se->string_length = gfc_get_expr_charlen (expr);

4434 4435
	  return;
	}
4436 4437 4438 4439 4440 4441
      break;
      
    case EXPR_FUNCTION:
      /* A transformational function return value will be a temporary
	 array descriptor.  We still need to go through the scalarizer
	 to create the descriptor.  Elemental functions ar handled as
4442
	 arbitrary expressions, i.e. copy to a temporary.  */
4443 4444 4445 4446 4447 4448 4449 4450
      secss = ss;
      /* Look for the SS for this function.  */
      while (secss != gfc_ss_terminator
	     && (secss->type != GFC_SS_FUNCTION || secss->expr != expr))
      	secss = secss->next;

      if (se->direct_byref)
	{
4451
	  gcc_assert (secss != gfc_ss_terminator);
4452 4453 4454

	  /* For pointer assignments pass the descriptor directly.  */
	  se->ss = secss;
4455
	  se->expr = build_fold_addr_expr (se->expr);
4456 4457 4458 4459 4460 4461 4462 4463 4464 4465 4466 4467 4468 4469 4470 4471 4472 4473
	  gfc_conv_expr (se, expr);
	  return;
	}

      if (secss == gfc_ss_terminator)
	{
	  /* Elemental function.  */
	  need_tmp = 1;
	  info = NULL;
	}
      else
	{
	  /* Transformational function.  */
	  info = &secss->data.info;
	  need_tmp = 0;
	}
      break;

4474 4475 4476 4477 4478 4479 4480 4481 4482 4483 4484 4485 4486 4487 4488 4489 4490 4491
    case EXPR_ARRAY:
      /* Constant array constructors don't need a temporary.  */
      if (ss->type == GFC_SS_CONSTRUCTOR
	  && expr->ts.type != BT_CHARACTER
	  && gfc_constant_array_constructor_p (expr->value.constructor))
	{
	  need_tmp = 0;
	  info = &ss->data.info;
	  secss = ss;
	}
      else
	{
	  need_tmp = 1;
	  secss = NULL;
	  info = NULL;
	}
      break;

4492 4493
    default:
      /* Something complicated.  Copy it into a temporary.  */
4494 4495 4496
      need_tmp = 1;
      secss = NULL;
      info = NULL;
4497
      break;
4498 4499
    }

4500

4501 4502 4503 4504 4505
  gfc_init_loopinfo (&loop);

  /* Associate the SS with the loop.  */
  gfc_add_ss_to_loop (&loop, ss);

4506
  /* Tell the scalarizer not to bother creating loop variables, etc.  */
4507 4508 4509
  if (!need_tmp)
    loop.array_parameter = 1;
  else
4510 4511
    /* The right-hand side of a pointer assignment mustn't use a temporary.  */
    gcc_assert (!se->direct_byref);
4512 4513 4514 4515 4516 4517 4518 4519 4520 4521

  /* Setup the scalarizing loops and bounds.  */
  gfc_conv_ss_startstride (&loop);

  if (need_tmp)
    {
      /* Tell the scalarizer to make a temporary.  */
      loop.temp_ss = gfc_get_ss ();
      loop.temp_ss->type = GFC_SS_TEMP;
      loop.temp_ss->next = gfc_ss_terminator;
4522 4523 4524 4525 4526 4527

      if (expr->ts.type == BT_CHARACTER && !expr->ts.cl->backend_decl)
	gfc_conv_string_length (expr->ts.cl, &se->pre);

      loop.temp_ss->data.temp.type = gfc_typenode_for_spec (&expr->ts);

4528
      if (expr->ts.type == BT_CHARACTER)
4529
	loop.temp_ss->string_length = expr->ts.cl->backend_decl;
4530
      else
4531 4532 4533
	loop.temp_ss->string_length = NULL;

      se->string_length = loop.temp_ss->string_length;
4534 4535 4536 4537 4538 4539 4540 4541 4542 4543 4544 4545 4546 4547 4548 4549 4550 4551 4552 4553 4554 4555 4556 4557 4558 4559 4560 4561 4562
      loop.temp_ss->data.temp.dimen = loop.dimen;
      gfc_add_ss_to_loop (&loop, loop.temp_ss);
    }

  gfc_conv_loop_setup (&loop);

  if (need_tmp)
    {
      /* Copy into a temporary and pass that.  We don't need to copy the data
         back because expressions and vector subscripts must be INTENT_IN.  */
      /* TODO: Optimize passing function return values.  */
      gfc_se lse;
      gfc_se rse;

      /* Start the copying loops.  */
      gfc_mark_ss_chain_used (loop.temp_ss, 1);
      gfc_mark_ss_chain_used (ss, 1);
      gfc_start_scalarized_body (&loop, &block);

      /* Copy each data element.  */
      gfc_init_se (&lse, NULL);
      gfc_copy_loopinfo_to_se (&lse, &loop);
      gfc_init_se (&rse, NULL);
      gfc_copy_loopinfo_to_se (&rse, &loop);

      lse.ss = loop.temp_ss;
      rse.ss = ss;

      gfc_conv_scalarized_array_ref (&lse, NULL);
4563 4564 4565
      if (expr->ts.type == BT_CHARACTER)
	{
	  gfc_conv_expr (&rse, expr);
4566 4567
	  if (POINTER_TYPE_P (TREE_TYPE (rse.expr)))
	    rse.expr = build_fold_indirect_ref (rse.expr);
4568 4569 4570
	}
      else
        gfc_conv_expr_val (&rse, expr);
4571 4572 4573 4574 4575 4576 4577 4578 4579 4580 4581

      gfc_add_block_to_block (&block, &rse.pre);
      gfc_add_block_to_block (&block, &lse.pre);

      gfc_add_modify_expr (&block, lse.expr, rse.expr);

      /* Finish the copying loops.  */
      gfc_trans_scalarizing_loops (&loop, &block);

      desc = loop.temp_ss->data.info.descriptor;

4582
      gcc_assert (is_gimple_lvalue (desc));
4583
    }
4584 4585 4586
  else if (expr->expr_type == EXPR_FUNCTION)
    {
      desc = info->descriptor;
4587
      se->string_length = ss->string_length;
4588
    }
4589 4590
  else
    {
4591 4592 4593 4594 4595
      /* We pass sections without copying to a temporary.  Make a new
	 descriptor and point it at the section we want.  The loop variable
	 limits will be the limits of the section.
	 A function may decide to repack the array to speed up access, but
	 we're not bothered about that here.  */
4596
      int dim, ndim;
4597 4598 4599 4600 4601 4602 4603
      tree parm;
      tree parmtype;
      tree stride;
      tree from;
      tree to;
      tree base;

4604
      /* Set the string_length for a character array.  */
4605
      if (expr->ts.type == BT_CHARACTER)
4606
	se->string_length =  gfc_get_expr_charlen (expr);
4607

4608
      desc = info->descriptor;
4609
      gcc_assert (secss && secss != gfc_ss_terminator);
4610 4611 4612 4613 4614 4615 4616 4617 4618 4619 4620 4621 4622 4623 4624
      if (se->direct_byref)
	{
	  /* For pointer assignments we fill in the destination.  */
	  parm = se->expr;
	  parmtype = TREE_TYPE (parm);
	}
      else
	{
	  /* Otherwise make a new one.  */
	  parmtype = gfc_get_element_type (TREE_TYPE (desc));
	  parmtype = gfc_get_array_type_bounds (parmtype, loop.dimen,
						loop.from, loop.to, 0);
	  parm = gfc_create_var (parmtype, "parm");
	}

4625
      offset = gfc_index_zero_node;
4626 4627 4628 4629 4630 4631 4632
      dim = 0;

      /* The following can be somewhat confusing.  We have two
         descriptors, a new one and the original array.
         {parm, parmtype, dim} refer to the new one.
         {desc, type, n, secss, loop} refer to the original, which maybe
         a descriptorless array.
4633
         The bounds of the scalarization are the bounds of the section.
4634 4635 4636 4637 4638
         We don't have to worry about numeric overflows when calculating
         the offsets because all elements are within the array data.  */

      /* Set the dtype.  */
      tmp = gfc_conv_descriptor_dtype (parm);
4639
      gfc_add_modify_expr (&loop.pre, tmp, gfc_get_dtype (parmtype));
4640

4641 4642 4643 4644
      /* Set offset for assignments to pointer only to zero if it is not
         the full array.  */
      if (se->direct_byref
	  && info->ref && info->ref->u.ar.type != AR_FULL)
4645
	base = gfc_index_zero_node;
4646 4647
      else if (GFC_ARRAY_TYPE_P (TREE_TYPE (desc)))
	base = gfc_evaluate_now (gfc_conv_array_offset (desc), &loop.pre);
4648 4649 4650
      else
	base = NULL_TREE;

4651 4652
      ndim = info->ref ? info->ref->u.ar.dimen : info->dimen;
      for (n = 0; n < ndim; n++)
4653 4654 4655 4656
	{
	  stride = gfc_conv_array_stride (desc, n);

	  /* Work out the offset.  */
4657 4658
	  if (info->ref
	      && info->ref->u.ar.dimen_type[n] == DIMEN_ELEMENT)
4659
	    {
4660
	      gcc_assert (info->subscript[n]
4661 4662 4663 4664 4665 4666
		      && info->subscript[n]->type == GFC_SS_SCALAR);
	      start = info->subscript[n]->data.scalar.expr;
	    }
	  else
	    {
	      /* Check we haven't somehow got out of sync.  */
4667
	      gcc_assert (info->dim[dim] == n);
4668 4669 4670 4671 4672 4673 4674

	      /* Evaluate and remember the start of the section.  */
	      start = info->start[dim];
	      stride = gfc_evaluate_now (stride, &loop.pre);
	    }

	  tmp = gfc_conv_array_lbound (desc, n);
4675
	  tmp = fold_build2 (MINUS_EXPR, TREE_TYPE (tmp), start, tmp);
4676

4677 4678
	  tmp = fold_build2 (MULT_EXPR, TREE_TYPE (tmp), tmp, stride);
	  offset = fold_build2 (PLUS_EXPR, TREE_TYPE (tmp), offset, tmp);
4679

4680 4681
	  if (info->ref
	      && info->ref->u.ar.dimen_type[n] == DIMEN_ELEMENT)
4682 4683 4684 4685 4686 4687
	    {
	      /* For elemental dimensions, we only need the offset.  */
	      continue;
	    }

	  /* Vector subscripts need copying and are handled elsewhere.  */
4688 4689
	  if (info->ref)
	    gcc_assert (info->ref->u.ar.dimen_type[n] == DIMEN_RANGE);
4690 4691 4692 4693

	  /* Set the new lower bound.  */
	  from = loop.from[dim];
	  to = loop.to[dim];
4694

4695 4696
	  /* If we have an array section or are assigning make sure that
	     the lower bound is 1.  References to the full
4697
	     array should otherwise keep the original bounds.  */
4698
	  if ((!info->ref
4699
	          || info->ref->u.ar.type != AR_FULL)
4700
	      && !integer_onep (from))
4701
	    {
4702 4703 4704
	      tmp = fold_build2 (MINUS_EXPR, gfc_array_index_type,
				 gfc_index_one_node, from);
	      to = fold_build2 (PLUS_EXPR, gfc_array_index_type, to, tmp);
4705
	      from = gfc_index_one_node;
4706 4707 4708 4709 4710 4711 4712 4713 4714 4715
	    }
	  tmp = gfc_conv_descriptor_lbound (parm, gfc_rank_cst[dim]);
	  gfc_add_modify_expr (&loop.pre, tmp, from);

	  /* Set the new upper bound.  */
	  tmp = gfc_conv_descriptor_ubound (parm, gfc_rank_cst[dim]);
	  gfc_add_modify_expr (&loop.pre, tmp, to);

	  /* Multiply the stride by the section stride to get the
	     total stride.  */
4716 4717
	  stride = fold_build2 (MULT_EXPR, gfc_array_index_type,
				stride, info->stride[dim]);
4718

4719
	  if (se->direct_byref && info->ref && info->ref->u.ar.type != AR_FULL)
4720 4721 4722 4723 4724 4725 4726 4727 4728 4729 4730 4731 4732 4733
	    {
	      base = fold_build2 (MINUS_EXPR, TREE_TYPE (base),
				  base, stride);
	    }
	  else if (GFC_ARRAY_TYPE_P (TREE_TYPE (desc)))
	    {
	      tmp = gfc_conv_array_lbound (desc, n);
	      tmp = fold_build2 (MINUS_EXPR, TREE_TYPE (base),
				 tmp, loop.from[dim]);
	      tmp = fold_build2 (MULT_EXPR, TREE_TYPE (base),
				 tmp, gfc_conv_array_stride (desc, n));
	      base = fold_build2 (PLUS_EXPR, TREE_TYPE (base),
				  tmp, base);
	    }
4734 4735 4736 4737 4738 4739 4740 4741

	  /* Store the new stride.  */
	  tmp = gfc_conv_descriptor_stride (parm, gfc_rank_cst[dim]);
	  gfc_add_modify_expr (&loop.pre, tmp, stride);

	  dim++;
	}

4742 4743 4744 4745 4746 4747 4748 4749 4750 4751 4752
      if (se->data_not_needed)
	gfc_conv_descriptor_data_set (&loop.pre, parm, gfc_index_zero_node);
      else
	{
	  /* Point the data pointer at the first element in the section.  */
	  tmp = gfc_conv_array_data (desc);
	  tmp = build_fold_indirect_ref (tmp);
	  tmp = gfc_build_array_ref (tmp, offset);
	  offset = gfc_build_addr_expr (gfc_array_dataptr_type (desc), tmp);
	  gfc_conv_descriptor_data_set (&loop.pre, parm, offset);
	}
4753

4754
      if ((se->direct_byref || GFC_ARRAY_TYPE_P (TREE_TYPE (desc)))
4755
	  && !se->data_not_needed)
4756 4757 4758 4759 4760 4761 4762 4763 4764 4765 4766 4767
	{
	  /* Set the offset.  */
	  tmp = gfc_conv_descriptor_offset (parm);
	  gfc_add_modify_expr (&loop.pre, tmp, base);
	}
      else
	{
	  /* Only the callee knows what the correct offset it, so just set
	     it to zero here.  */
	  tmp = gfc_conv_descriptor_offset (parm);
	  gfc_add_modify_expr (&loop.pre, tmp, gfc_index_zero_node);
	}
4768 4769
      desc = parm;
    }
4770

4771 4772 4773 4774
  if (!se->direct_byref)
    {
      /* Get a pointer to the new descriptor.  */
      if (se->want_pointer)
4775
	se->expr = build_fold_addr_expr (desc);
4776 4777
      else
	se->expr = desc;
4778 4779 4780 4781 4782 4783 4784 4785 4786 4787 4788 4789 4790 4791 4792 4793 4794 4795
    }

  gfc_add_block_to_block (&se->pre, &loop.pre);
  gfc_add_block_to_block (&se->post, &loop.post);

  /* Cleanup the scalarizer.  */
  gfc_cleanup_loop (&loop);
}


/* Convert an array for passing as an actual parameter.  */
/* TODO: Optimize passing g77 arrays.  */

void
gfc_conv_array_parameter (gfc_se * se, gfc_expr * expr, gfc_ss * ss, int g77)
{
  tree ptr;
  tree desc;
4796
  tree tmp = NULL_TREE;
4797
  tree stmt;
4798 4799
  tree parent = DECL_CONTEXT (current_function_decl);
  bool full_array_var, this_array_result;
4800 4801 4802
  gfc_symbol *sym;
  stmtblock_t block;

4803 4804 4805 4806
  full_array_var = (expr->expr_type == EXPR_VARIABLE
		      && expr->ref->u.ar.type == AR_FULL);
  sym = full_array_var ? expr->symtree->n.sym : NULL;

4807 4808 4809 4810 4811 4812 4813
  if (expr->expr_type == EXPR_ARRAY && expr->ts.type == BT_CHARACTER)
    {
      get_array_ctor_strlen (&se->pre, expr->value.constructor, &tmp);
      expr->ts.cl->backend_decl = gfc_evaluate_now (tmp, &se->pre);
      se->string_length = expr->ts.cl->backend_decl;
    }

4814 4815 4816 4817 4818 4819 4820
  /* Is this the result of the enclosing procedure?  */
  this_array_result = (full_array_var && sym->attr.flavor == FL_PROCEDURE);
  if (this_array_result
	&& (sym->backend_decl != current_function_decl)
	&& (sym->backend_decl != parent))
    this_array_result = false;

4821
  /* Passing address of the array if it is not pointer or assumed-shape.  */
4822
  if (full_array_var && g77 && !this_array_result)
4823
    {
4824
      tmp = gfc_get_symbol_decl (sym);
Asher Langton committed
4825

4826 4827
      if (sym->ts.type == BT_CHARACTER)
	se->string_length = sym->ts.cl->backend_decl;
4828 4829 4830
      if (!sym->attr.pointer && sym->as->type != AS_ASSUMED_SHAPE 
          && !sym->attr.allocatable)
        {
Paul Brook committed
4831
	  /* Some variables are declared directly, others are declared as
4832 4833 4834
	     pointers and allocated on the heap.  */
          if (sym->attr.dummy || POINTER_TYPE_P (TREE_TYPE (tmp)))
            se->expr = tmp;
4835
          else
4836
	    se->expr = build_fold_addr_expr (tmp);
4837 4838 4839 4840
	  return;
        }
      if (sym->attr.allocatable)
        {
4841 4842 4843 4844 4845 4846 4847
	  if (sym->attr.dummy)
	    {
	      gfc_conv_expr_descriptor (se, expr, ss);
	      se->expr = gfc_conv_array_data (se->expr);
	    }
	  else
	    se->expr = gfc_conv_array_data (tmp);
4848 4849 4850 4851
          return;
        }
    }

4852 4853 4854 4855 4856 4857 4858 4859 4860 4861 4862 4863 4864 4865 4866 4867 4868 4869 4870
  if (this_array_result)
    {
      /* Result of the enclosing function.  */
      gfc_conv_expr_descriptor (se, expr, ss);
      se->expr = build_fold_addr_expr (se->expr);

      if (g77 && TREE_TYPE (TREE_TYPE (se->expr)) != NULL_TREE
	      && GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (TREE_TYPE (se->expr))))
	se->expr = gfc_conv_array_data (build_fold_indirect_ref (se->expr));

      return;
    }
  else
    {
      /* Every other type of array.  */
      se->want_pointer = 1;
      gfc_conv_expr_descriptor (se, expr, ss);
    }

4871

Paul Thomas committed
4872 4873 4874 4875 4876 4877 4878 4879 4880 4881 4882
  /* Deallocate the allocatable components of structures that are
     not variable.  */
  if (expr->ts.type == BT_DERIVED
	&& expr->ts.derived->attr.alloc_comp
	&& expr->expr_type != EXPR_VARIABLE)
    {
      tmp = build_fold_indirect_ref (se->expr);
      tmp = gfc_deallocate_alloc_comp (expr->ts.derived, tmp, expr->rank);
      gfc_add_expr_to_block (&se->post, tmp);
    }

4883 4884 4885 4886
  if (g77)
    {
      desc = se->expr;
      /* Repack the array.  */
4887
      ptr = build_call_expr (gfor_fndecl_in_pack, 1, desc);
4888 4889 4890 4891 4892 4893
      ptr = gfc_evaluate_now (ptr, &se->pre);
      se->expr = ptr;

      gfc_start_block (&block);

      /* Copy the data back.  */
4894
      tmp = build_call_expr (gfor_fndecl_in_unpack, 2, desc, ptr);
4895 4896 4897
      gfc_add_expr_to_block (&block, tmp);

      /* Free the temporary.  */
4898
      tmp = gfc_call_free (convert (pvoid_type_node, ptr));
4899 4900 4901 4902 4903 4904 4905
      gfc_add_expr_to_block (&block, tmp);

      stmt = gfc_finish_block (&block);

      gfc_init_block (&block);
      /* Only if it was repacked.  This code needs to be executed before the
         loop cleanup code.  */
4906
      tmp = build_fold_indirect_ref (desc);
4907
      tmp = gfc_conv_array_data (tmp);
4908 4909
      tmp = build2 (NE_EXPR, boolean_type_node,
		    fold_convert (TREE_TYPE (tmp), ptr), tmp);
4910
      tmp = build3_v (COND_EXPR, tmp, stmt, build_empty_stmt ());
4911 4912 4913 4914 4915 4916 4917 4918 4919 4920

      gfc_add_expr_to_block (&block, tmp);
      gfc_add_block_to_block (&block, &se->post);

      gfc_init_block (&se->post);
      gfc_add_block_to_block (&se->post, &block);
    }
}


4921
/* Generate code to deallocate an array, if it is allocated.  */
4922 4923

tree
4924
gfc_trans_dealloc_allocated (tree descriptor)
4925 4926
{ 
  tree tmp;
Paul Thomas committed
4927
  tree var;
4928 4929 4930 4931
  stmtblock_t block;

  gfc_start_block (&block);

4932 4933
  var = gfc_conv_descriptor_data_get (descriptor);
  STRIP_NOPS (var);
Paul Thomas committed
4934

4935
  /* Call array_deallocate with an int * present in the second argument.
Paul Thomas committed
4936 4937
     Although it is ignored here, it's presence ensures that arrays that
     are already deallocated are ignored.  */
4938
  tmp = gfc_deallocate_with_status (var, NULL_TREE, true);
4939
  gfc_add_expr_to_block (&block, tmp);
4940 4941 4942 4943 4944 4945

  /* Zero the data pointer.  */
  tmp = build2 (MODIFY_EXPR, void_type_node,
		var, build_int_cst (TREE_TYPE (var), 0));
  gfc_add_expr_to_block (&block, tmp);

Paul Thomas committed
4946 4947 4948 4949 4950 4951 4952 4953 4954 4955 4956 4957 4958 4959 4960 4961 4962 4963 4964 4965 4966 4967 4968 4969
  return gfc_finish_block (&block);
}


/* This helper function calculates the size in words of a full array.  */

static tree
get_full_array_size (stmtblock_t *block, tree decl, int rank)
{
  tree idx;
  tree nelems;
  tree tmp;
  idx = gfc_rank_cst[rank - 1];
  nelems = gfc_conv_descriptor_ubound (decl, idx);
  tmp = gfc_conv_descriptor_lbound (decl, idx);
  tmp = build2 (MINUS_EXPR, gfc_array_index_type, nelems, tmp);
  tmp = build2 (PLUS_EXPR, gfc_array_index_type,
		tmp, gfc_index_one_node);
  tmp = gfc_evaluate_now (tmp, block);

  nelems = gfc_conv_descriptor_stride (decl, idx);
  tmp = build2 (MULT_EXPR, gfc_array_index_type, nelems, tmp);
  return gfc_evaluate_now (tmp, block);
}
4970

Paul Thomas committed
4971 4972 4973 4974 4975 4976 4977 4978 4979 4980 4981 4982 4983

/* Allocate dest to the same size as src, and copy src -> dest.  */

tree
gfc_duplicate_allocatable(tree dest, tree src, tree type, int rank)
{
  tree tmp;
  tree size;
  tree nelems;
  tree null_cond;
  tree null_data;
  stmtblock_t block;

4984
  /* If the source is null, set the destination to null.  */
Paul Thomas committed
4985 4986 4987 4988 4989 4990 4991 4992
  gfc_init_block (&block);
  gfc_conv_descriptor_data_set (&block, dest, null_pointer_node);
  null_data = gfc_finish_block (&block);

  gfc_init_block (&block);

  nelems = get_full_array_size (&block, src, rank);
  size = fold_build2 (MULT_EXPR, gfc_array_index_type, nelems,
4993 4994
		      fold_convert (gfc_array_index_type,
				    TYPE_SIZE_UNIT (gfc_get_element_type (type))));
Paul Thomas committed
4995 4996

  /* Allocate memory to the destination.  */
4997 4998
  tmp = gfc_call_malloc (&block, TREE_TYPE (gfc_conv_descriptor_data_get (src)),
			 size);
Paul Thomas committed
4999 5000 5001 5002 5003
  gfc_conv_descriptor_data_set (&block, dest, tmp);

  /* We know the temporary and the value will be the same length,
     so can use memcpy.  */
  tmp = built_in_decls[BUILT_IN_MEMCPY];
5004 5005
  tmp = build_call_expr (tmp, 3, gfc_conv_descriptor_data_get (dest),
  			 gfc_conv_descriptor_data_get (src), size);
Paul Thomas committed
5006
  gfc_add_expr_to_block (&block, tmp);
5007 5008
  tmp = gfc_finish_block (&block);

Paul Thomas committed
5009 5010 5011 5012 5013 5014 5015 5016 5017 5018 5019 5020 5021 5022 5023 5024 5025 5026 5027 5028 5029 5030 5031 5032 5033 5034 5035 5036 5037 5038 5039 5040 5041 5042 5043 5044 5045
  /* Null the destination if the source is null; otherwise do
     the allocate and copy.  */
  null_cond = gfc_conv_descriptor_data_get (src);
  null_cond = convert (pvoid_type_node, null_cond);
  null_cond = build2 (NE_EXPR, boolean_type_node, null_cond,
		      null_pointer_node);
  return build3_v (COND_EXPR, null_cond, tmp, null_data);
}


/* Recursively traverse an object of derived type, generating code to
   deallocate, nullify or copy allocatable components.  This is the work horse
   function for the functions named in this enum.  */

enum {DEALLOCATE_ALLOC_COMP = 1, NULLIFY_ALLOC_COMP, COPY_ALLOC_COMP};

static tree
structure_alloc_comps (gfc_symbol * der_type, tree decl,
		       tree dest, int rank, int purpose)
{
  gfc_component *c;
  gfc_loopinfo loop;
  stmtblock_t fnblock;
  stmtblock_t loopbody;
  tree tmp;
  tree comp;
  tree dcmp;
  tree nelems;
  tree index;
  tree var;
  tree cdecl;
  tree ctype;
  tree vref, dref;
  tree null_cond = NULL_TREE;

  gfc_init_block (&fnblock);

5046 5047 5048
  if (POINTER_TYPE_P (TREE_TYPE (decl)))
    decl = build_fold_indirect_ref (decl);

Paul Thomas committed
5049 5050 5051 5052 5053 5054 5055 5056 5057 5058 5059 5060 5061 5062 5063 5064 5065 5066 5067 5068
  /* If this an array of derived types with allocatable components
     build a loop and recursively call this function.  */
  if (TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE
	|| GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (decl)))
    {
      tmp = gfc_conv_array_data (decl);
      var = build_fold_indirect_ref (tmp);
	
      /* Get the number of elements - 1 and set the counter.  */
      if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (decl)))
	{
	  /* Use the descriptor for an allocatable array.  Since this
	     is a full array reference, we only need the descriptor
	     information from dimension = rank.  */
	  tmp = get_full_array_size (&fnblock, decl, rank);
	  tmp = build2 (MINUS_EXPR, gfc_array_index_type,
			tmp, gfc_index_one_node);

	  null_cond = gfc_conv_descriptor_data_get (decl);
	  null_cond = build2 (NE_EXPR, boolean_type_node, null_cond,
5069
			      build_int_cst (TREE_TYPE (null_cond), 0));
Paul Thomas committed
5070 5071 5072 5073 5074 5075 5076 5077 5078 5079 5080 5081 5082 5083 5084 5085 5086 5087 5088 5089 5090 5091 5092 5093 5094 5095 5096 5097 5098 5099 5100
	}
      else
	{
	  /*  Otherwise use the TYPE_DOMAIN information.  */
	  tmp =  array_type_nelts (TREE_TYPE (decl));
	  tmp = fold_convert (gfc_array_index_type, tmp);
	}

      /* Remember that this is, in fact, the no. of elements - 1.  */
      nelems = gfc_evaluate_now (tmp, &fnblock);
      index = gfc_create_var (gfc_array_index_type, "S");

      /* Build the body of the loop.  */
      gfc_init_block (&loopbody);

      vref = gfc_build_array_ref (var, index);

      if (purpose == COPY_ALLOC_COMP)
        {
          tmp = gfc_duplicate_allocatable (dest, decl, TREE_TYPE(decl), rank);
	  gfc_add_expr_to_block (&fnblock, tmp);

	  tmp = build_fold_indirect_ref (gfc_conv_descriptor_data_get (dest));
	  dref = gfc_build_array_ref (tmp, index);
	  tmp = structure_alloc_comps (der_type, vref, dref, rank, purpose);
	}
      else
        tmp = structure_alloc_comps (der_type, vref, NULL_TREE, rank, purpose);

      gfc_add_expr_to_block (&loopbody, tmp);

5101
      /* Build the loop and return.  */
Paul Thomas committed
5102 5103 5104 5105 5106 5107 5108 5109 5110 5111 5112 5113 5114 5115 5116 5117
      gfc_init_loopinfo (&loop);
      loop.dimen = 1;
      loop.from[0] = gfc_index_zero_node;
      loop.loopvar[0] = index;
      loop.to[0] = nelems;
      gfc_trans_scalarizing_loops (&loop, &loopbody);
      gfc_add_block_to_block (&fnblock, &loop.pre);

      tmp = gfc_finish_block (&fnblock);
      if (null_cond != NULL_TREE)
	tmp = build3_v (COND_EXPR, null_cond, tmp, build_empty_stmt ());

      return tmp;
    }

  /* Otherwise, act on the components or recursively call self to
5118
     act on a chain of components.  */
Paul Thomas committed
5119 5120 5121 5122 5123 5124 5125 5126 5127 5128 5129 5130 5131 5132 5133 5134 5135 5136 5137 5138 5139 5140 5141 5142 5143 5144 5145 5146 5147 5148 5149 5150 5151 5152 5153 5154 5155 5156 5157 5158 5159 5160 5161 5162 5163 5164 5165 5166 5167 5168 5169 5170 5171 5172 5173 5174 5175 5176 5177 5178 5179 5180 5181 5182 5183 5184 5185 5186 5187 5188 5189 5190 5191 5192 5193 5194 5195 5196 5197 5198 5199 5200 5201 5202 5203 5204 5205 5206 5207 5208
  for (c = der_type->components; c; c = c->next)
    {
      bool cmp_has_alloc_comps = (c->ts.type == BT_DERIVED)
				    && c->ts.derived->attr.alloc_comp;
      cdecl = c->backend_decl;
      ctype = TREE_TYPE (cdecl);

      switch (purpose)
	{
	case DEALLOCATE_ALLOC_COMP:
	  /* Do not deallocate the components of ultimate pointer
	     components.  */
	  if (cmp_has_alloc_comps && !c->pointer)
	    {
	      comp = build3 (COMPONENT_REF, ctype, decl, cdecl, NULL_TREE);
	      rank = c->as ? c->as->rank : 0;
	      tmp = structure_alloc_comps (c->ts.derived, comp, NULL_TREE,
					   rank, purpose);
	      gfc_add_expr_to_block (&fnblock, tmp);
	    }

	  if (c->allocatable)
	    {
	      comp = build3 (COMPONENT_REF, ctype, decl, cdecl, NULL_TREE);
	      tmp = gfc_trans_dealloc_allocated (comp);
	      gfc_add_expr_to_block (&fnblock, tmp);
	    }
	  break;

	case NULLIFY_ALLOC_COMP:
	  if (c->pointer)
	    continue;
	  else if (c->allocatable)
	    {
	      comp = build3 (COMPONENT_REF, ctype, decl, cdecl, NULL_TREE);
	      gfc_conv_descriptor_data_set (&fnblock, comp, null_pointer_node);
	    }
          else if (cmp_has_alloc_comps)
	    {
	      comp = build3 (COMPONENT_REF, ctype, decl, cdecl, NULL_TREE);
	      rank = c->as ? c->as->rank : 0;
	      tmp = structure_alloc_comps (c->ts.derived, comp, NULL_TREE,
					   rank, purpose);
	      gfc_add_expr_to_block (&fnblock, tmp);
	    }
	  break;

	case COPY_ALLOC_COMP:
	  if (c->pointer)
	    continue;

	  /* We need source and destination components.  */
	  comp = build3 (COMPONENT_REF, ctype, decl, cdecl, NULL_TREE);
	  dcmp = build3 (COMPONENT_REF, ctype, dest, cdecl, NULL_TREE);
	  dcmp = fold_convert (TREE_TYPE (comp), dcmp);

	  if (c->allocatable && !cmp_has_alloc_comps)
	    {
	      tmp = gfc_duplicate_allocatable(dcmp, comp, ctype, c->as->rank);
	      gfc_add_expr_to_block (&fnblock, tmp);
	    }

          if (cmp_has_alloc_comps)
	    {
	      rank = c->as ? c->as->rank : 0;
	      tmp = fold_convert (TREE_TYPE (dcmp), comp);
	      gfc_add_modify_expr (&fnblock, dcmp, tmp);
	      tmp = structure_alloc_comps (c->ts.derived, comp, dcmp,
					   rank, purpose);
	      gfc_add_expr_to_block (&fnblock, tmp);
	    }
	  break;

	default:
	  gcc_unreachable ();
	  break;
	}
    }

  return gfc_finish_block (&fnblock);
}

/* Recursively traverse an object of derived type, generating code to
   nullify allocatable components.  */

tree
gfc_nullify_alloc_comp (gfc_symbol * der_type, tree decl, int rank)
{
  return structure_alloc_comps (der_type, decl, NULL_TREE, rank,
				NULLIFY_ALLOC_COMP);
5209 5210 5211
}


Paul Thomas committed
5212 5213 5214 5215 5216 5217 5218 5219 5220 5221 5222 5223 5224 5225 5226 5227 5228 5229 5230 5231 5232 5233 5234 5235
/* Recursively traverse an object of derived type, generating code to
   deallocate allocatable components.  */

tree
gfc_deallocate_alloc_comp (gfc_symbol * der_type, tree decl, int rank)
{
  return structure_alloc_comps (der_type, decl, NULL_TREE, rank,
				DEALLOCATE_ALLOC_COMP);
}


/* Recursively traverse an object of derived type, generating code to
   copy its allocatable components.  */

tree
gfc_copy_alloc_comp (gfc_symbol * der_type, tree decl, tree dest, int rank)
{
  return structure_alloc_comps (der_type, decl, dest, rank, COPY_ALLOC_COMP);
}


/* NULLIFY an allocatable/pointer array on function entry, free it on exit.
   Do likewise, recursively if necessary, with the allocatable components of
   derived types.  */
5236 5237 5238 5239 5240 5241 5242 5243 5244

tree
gfc_trans_deferred_array (gfc_symbol * sym, tree body)
{
  tree type;
  tree tmp;
  tree descriptor;
  stmtblock_t fnblock;
  locus loc;
Paul Thomas committed
5245 5246 5247 5248 5249
  int rank;
  bool sym_has_alloc_comp;

  sym_has_alloc_comp = (sym->ts.type == BT_DERIVED)
			  && sym->ts.derived->attr.alloc_comp;
5250 5251

  /* Make sure the frontend gets these right.  */
Paul Thomas committed
5252 5253 5254 5255
  if (!(sym->attr.pointer || sym->attr.allocatable || sym_has_alloc_comp))
    fatal_error ("Possible frontend bug: Deferred array size without pointer, "
		 "allocatable attribute or derived type without allocatable "
		 "components.");
5256 5257 5258

  gfc_init_block (&fnblock);

Paul Thomas committed
5259
  gcc_assert (TREE_CODE (sym->backend_decl) == VAR_DECL
Paul Thomas committed
5260
		|| TREE_CODE (sym->backend_decl) == PARM_DECL);
Paul Thomas committed
5261

5262 5263
  if (sym->ts.type == BT_CHARACTER
      && !INTEGER_CST_P (sym->ts.cl->backend_decl))
5264
    {
5265
      gfc_conv_string_length (sym->ts.cl, &fnblock);
5266 5267
      gfc_trans_vla_type_sizes (sym, &fnblock);
    }
5268

Tobias Schlüter committed
5269
  /* Dummy and use associated variables don't need anything special.  */
5270
  if (sym->attr.dummy || sym->attr.use_assoc)
5271 5272 5273 5274 5275 5276 5277 5278 5279 5280
    {
      gfc_add_expr_to_block (&fnblock, body);

      return gfc_finish_block (&fnblock);
    }

  gfc_get_backend_locus (&loc);
  gfc_set_backend_locus (&sym->declared_at);
  descriptor = sym->backend_decl;

Kazu Hirata committed
5281
  /* Although static, derived types with default initializers and
Paul Thomas committed
5282 5283 5284
     allocatable components must not be nulled wholesale; instead they
     are treated component by component.  */
  if (TREE_STATIC (descriptor) && !sym_has_alloc_comp)
5285 5286 5287 5288 5289 5290 5291 5292
    {
      /* SAVEd variables are not freed on exit.  */
      gfc_trans_static_array_pointer (sym);
      return body;
    }

  /* Get the descriptor type.  */
  type = TREE_TYPE (sym->backend_decl);
Paul Thomas committed
5293 5294 5295
    
  if (sym_has_alloc_comp && !(sym->attr.pointer || sym->attr.allocatable))
    {
Paul Thomas committed
5296 5297 5298 5299 5300 5301
      if (!sym->attr.save)
	{
	  rank = sym->as ? sym->as->rank : 0;
	  tmp = gfc_nullify_alloc_comp (sym->ts.derived, descriptor, rank);
	  gfc_add_expr_to_block (&fnblock, tmp);
	}
Paul Thomas committed
5302 5303
    }
  else if (!GFC_DESCRIPTOR_TYPE_P (type))
5304 5305 5306 5307 5308 5309
    {
      /* If the backend_decl is not a descriptor, we must have a pointer
	 to one.  */
      descriptor = build_fold_indirect_ref (sym->backend_decl);
      type = TREE_TYPE (descriptor);
    }
Paul Thomas committed
5310
  
5311
  /* NULLIFY the data pointer.  */
Paul Thomas committed
5312 5313
  if (GFC_DESCRIPTOR_TYPE_P (type))
    gfc_conv_descriptor_data_set (&fnblock, descriptor, null_pointer_node);
5314 5315 5316 5317

  gfc_add_expr_to_block (&fnblock, body);

  gfc_set_backend_locus (&loc);
Paul Thomas committed
5318 5319 5320 5321

  /* Allocatable arrays need to be freed when they go out of scope.
     The allocatable components of pointers must not be touched.  */
  if (sym_has_alloc_comp && !(sym->attr.function || sym->attr.result)
Paul Thomas committed
5322
      && !sym->attr.pointer && !sym->attr.save)
Paul Thomas committed
5323 5324 5325 5326 5327 5328 5329
    {
      int rank;
      rank = sym->as ? sym->as->rank : 0;
      tmp = gfc_deallocate_alloc_comp (sym->ts.derived, descriptor, rank);
      gfc_add_expr_to_block (&fnblock, tmp);
    }

5330 5331
  if (sym->attr.allocatable)
    {
5332
      tmp = gfc_trans_dealloc_allocated (sym->backend_decl);
5333 5334 5335 5336 5337 5338 5339 5340 5341 5342 5343 5344 5345 5346 5347 5348
      gfc_add_expr_to_block (&fnblock, tmp);
    }

  return gfc_finish_block (&fnblock);
}

/************ Expression Walking Functions ******************/

/* Walk a variable reference.

   Possible extension - multiple component subscripts.
    x(:,:) = foo%a(:)%b(:)
   Transforms to
    forall (i=..., j=...)
      x(i,j) = foo%a(j)%b(i)
    end forall
5349
   This adds a fair amount of complexity because you need to deal with more
5350 5351 5352 5353 5354 5355 5356 5357 5358 5359 5360 5361 5362 5363
   than one ref.  Maybe handle in a similar manner to vector subscripts.
   Maybe not worth the effort.  */


static gfc_ss *
gfc_walk_variable_expr (gfc_ss * ss, gfc_expr * expr)
{
  gfc_ref *ref;
  gfc_array_ref *ar;
  gfc_ss *newss;
  gfc_ss *head;
  int n;

  for (ref = expr->ref; ref; ref = ref->next)
5364 5365 5366 5367
    if (ref->type == REF_ARRAY && ref->u.ar.type != AR_ELEMENT)
      break;

  for (; ref; ref = ref->next)
5368
    {
5369 5370 5371 5372 5373 5374 5375 5376 5377 5378 5379 5380 5381 5382 5383 5384
      if (ref->type == REF_SUBSTRING)
	{
	  newss = gfc_get_ss ();
	  newss->type = GFC_SS_SCALAR;
	  newss->expr = ref->u.ss.start;
	  newss->next = ss;
	  ss = newss;

	  newss = gfc_get_ss ();
	  newss->type = GFC_SS_SCALAR;
	  newss->expr = ref->u.ss.end;
	  newss->next = ss;
	  ss = newss;
	}

      /* We're only interested in array sections from now on.  */
5385 5386 5387 5388 5389 5390 5391
      if (ref->type != REF_ARRAY)
	continue;

      ar = &ref->u.ar;
      switch (ar->type)
	{
	case AR_ELEMENT:
5392 5393 5394 5395 5396 5397 5398 5399
	  for (n = 0; n < ar->dimen; n++)
	    {
	      newss = gfc_get_ss ();
	      newss->type = GFC_SS_SCALAR;
	      newss->expr = ar->start[n];
	      newss->next = ss;
	      ss = newss;
	    }
5400 5401 5402 5403 5404 5405 5406 5407 5408 5409 5410 5411 5412 5413 5414 5415 5416 5417
	  break;

	case AR_FULL:
	  newss = gfc_get_ss ();
	  newss->type = GFC_SS_SECTION;
	  newss->expr = expr;
	  newss->next = ss;
	  newss->data.info.dimen = ar->as->rank;
	  newss->data.info.ref = ref;

	  /* Make sure array is the same as array(:,:), this way
	     we don't need to special case all the time.  */
	  ar->dimen = ar->as->rank;
	  for (n = 0; n < ar->dimen; n++)
	    {
	      newss->data.info.dim[n] = n;
	      ar->dimen_type[n] = DIMEN_RANGE;

5418 5419 5420
	      gcc_assert (ar->start[n] == NULL);
	      gcc_assert (ar->end[n] == NULL);
	      gcc_assert (ar->stride[n] == NULL);
5421
	    }
5422 5423
	  ss = newss;
	  break;
5424 5425 5426 5427 5428 5429 5430 5431 5432 5433 5434 5435 5436 5437 5438 5439 5440 5441 5442 5443

	case AR_SECTION:
	  newss = gfc_get_ss ();
	  newss->type = GFC_SS_SECTION;
	  newss->expr = expr;
	  newss->next = ss;
	  newss->data.info.dimen = 0;
	  newss->data.info.ref = ref;

	  head = newss;

          /* We add SS chains for all the subscripts in the section.  */
	  for (n = 0; n < ar->dimen; n++)
	    {
	      gfc_ss *indexss;

	      switch (ar->dimen_type[n])
		{
		case DIMEN_ELEMENT:
		  /* Add SS for elemental (scalar) subscripts.  */
5444
		  gcc_assert (ar->start[n]);
5445 5446 5447 5448 5449 5450 5451 5452 5453 5454 5455 5456 5457 5458 5459 5460
		  indexss = gfc_get_ss ();
		  indexss->type = GFC_SS_SCALAR;
		  indexss->expr = ar->start[n];
		  indexss->next = gfc_ss_terminator;
		  indexss->loop_chain = gfc_ss_terminator;
		  newss->data.info.subscript[n] = indexss;
		  break;

		case DIMEN_RANGE:
                  /* We don't add anything for sections, just remember this
                     dimension for later.  */
		  newss->data.info.dim[newss->data.info.dimen] = n;
		  newss->data.info.dimen++;
		  break;

		case DIMEN_VECTOR:
5461 5462 5463
		  /* Create a GFC_SS_VECTOR index in which we can store
		     the vector's descriptor.  */
		  indexss = gfc_get_ss ();
5464
		  indexss->type = GFC_SS_VECTOR;
5465 5466 5467
		  indexss->expr = ar->start[n];
		  indexss->next = gfc_ss_terminator;
		  indexss->loop_chain = gfc_ss_terminator;
5468 5469 5470 5471 5472 5473 5474
		  newss->data.info.subscript[n] = indexss;
		  newss->data.info.dim[newss->data.info.dimen] = n;
		  newss->data.info.dimen++;
		  break;

		default:
		  /* We should know what sort of section it is by now.  */
5475
		  gcc_unreachable ();
5476 5477 5478
		}
	    }
	  /* We should have at least one non-elemental dimension.  */
5479
	  gcc_assert (newss->data.info.dimen > 0);
5480
	  ss = newss;
5481 5482 5483 5484
	  break;

	default:
	  /* We should know what sort of section it is by now.  */
5485
	  gcc_unreachable ();
5486 5487 5488 5489 5490 5491 5492 5493 5494 5495 5496 5497 5498 5499 5500 5501 5502
	}

    }
  return ss;
}


/* Walk an expression operator. If only one operand of a binary expression is
   scalar, we must also add the scalar term to the SS chain.  */

static gfc_ss *
gfc_walk_op_expr (gfc_ss * ss, gfc_expr * expr)
{
  gfc_ss *head;
  gfc_ss *head2;
  gfc_ss *newss;

5503 5504
  head = gfc_walk_subexpr (ss, expr->value.op.op1);
  if (expr->value.op.op2 == NULL)
5505 5506
    head2 = head;
  else
5507
    head2 = gfc_walk_subexpr (head, expr->value.op.op2);
5508 5509 5510 5511 5512

  /* All operands are scalar.  Pass back and let the caller deal with it.  */
  if (head2 == ss)
    return head2;

5513
  /* All operands require scalarization.  */
5514
  if (head != ss && (expr->value.op.op2 == NULL || head2 != head))
5515 5516 5517 5518 5519 5520 5521 5522 5523 5524 5525 5526 5527 5528
    return head2;

  /* One of the operands needs scalarization, the other is scalar.
     Create a gfc_ss for the scalar expression.  */
  newss = gfc_get_ss ();
  newss->type = GFC_SS_SCALAR;
  if (head == ss)
    {
      /* First operand is scalar.  We build the chain in reverse order, so
         add the scarar SS after the second operand.  */
      head = head2;
      while (head && head->next != ss)
	head = head->next;
      /* Check we haven't somehow broken the chain.  */
5529
      gcc_assert (head);
5530 5531
      newss->next = ss;
      head->next = newss;
5532
      newss->expr = expr->value.op.op1;
5533 5534 5535
    }
  else				/* head2 == head */
    {
5536
      gcc_assert (head2 == head);
5537 5538 5539
      /* Second operand is scalar.  */
      newss->next = head2;
      head2 = newss;
5540
      newss->expr = expr->value.op.op2;
5541 5542 5543 5544 5545 5546 5547 5548
    }

  return head2;
}


/* Reverse a SS chain.  */

5549
gfc_ss *
5550 5551 5552 5553 5554
gfc_reverse_ss (gfc_ss * ss)
{
  gfc_ss *next;
  gfc_ss *head;

5555
  gcc_assert (ss != NULL);
5556 5557 5558 5559 5560

  head = gfc_ss_terminator;
  while (ss != gfc_ss_terminator)
    {
      next = ss->next;
5561 5562
      /* Check we didn't somehow break the chain.  */
      gcc_assert (next != NULL);
5563 5564 5565 5566 5567 5568 5569 5570 5571 5572 5573 5574
      ss->next = head;
      head = ss;
      ss = next;
    }

  return (head);
}


/* Walk the arguments of an elemental function.  */

gfc_ss *
5575
gfc_walk_elemental_function_args (gfc_ss * ss, gfc_actual_arglist *arg,
5576 5577 5578 5579 5580 5581 5582 5583 5584 5585
				  gfc_ss_type type)
{
  int scalar;
  gfc_ss *head;
  gfc_ss *tail;
  gfc_ss *newss;

  head = gfc_ss_terminator;
  tail = NULL;
  scalar = 1;
5586
  for (; arg; arg = arg->next)
5587 5588 5589 5590 5591 5592 5593
    {
      if (!arg->expr)
	continue;

      newss = gfc_walk_subexpr (head, arg->expr);
      if (newss == head)
	{
5594
	  /* Scalar argument.  */
5595 5596 5597 5598 5599 5600 5601 5602 5603 5604 5605 5606 5607 5608 5609 5610 5611 5612 5613 5614 5615 5616 5617 5618 5619 5620 5621 5622 5623 5624 5625 5626 5627 5628 5629 5630 5631 5632 5633 5634 5635 5636 5637 5638 5639 5640
	  newss = gfc_get_ss ();
	  newss->type = type;
	  newss->expr = arg->expr;
	  newss->next = head;
	}
      else
	scalar = 0;

      head = newss;
      if (!tail)
        {
          tail = head;
          while (tail->next != gfc_ss_terminator)
            tail = tail->next;
        }
    }

  if (scalar)
    {
      /* If all the arguments are scalar we don't need the argument SS.  */
      gfc_free_ss_chain (head);
      /* Pass it back.  */
      return ss;
    }

  /* Add it onto the existing chain.  */
  tail->next = ss;
  return head;
}


/* Walk a function call.  Scalar functions are passed back, and taken out of
   scalarization loops.  For elemental functions we walk their arguments.
   The result of functions returning arrays is stored in a temporary outside
   the loop, so that the function is only called once.  Hence we do not need
   to walk their arguments.  */

static gfc_ss *
gfc_walk_function_expr (gfc_ss * ss, gfc_expr * expr)
{
  gfc_ss *newss;
  gfc_intrinsic_sym *isym;
  gfc_symbol *sym;

  isym = expr->value.function.isym;

5641
  /* Handle intrinsic functions separately.  */
5642 5643 5644 5645 5646 5647 5648 5649 5650 5651 5652 5653 5654 5655 5656 5657 5658 5659 5660 5661 5662
  if (isym)
    return gfc_walk_intrinsic_function (ss, expr, isym);

  sym = expr->value.function.esym;
  if (!sym)
      sym = expr->symtree->n.sym;

  /* A function that returns arrays.  */
  if (gfc_return_by_reference (sym) && sym->result->attr.dimension)
    {
      newss = gfc_get_ss ();
      newss->type = GFC_SS_FUNCTION;
      newss->expr = expr;
      newss->next = ss;
      newss->data.info.dimen = expr->rank;
      return newss;
    }

  /* Walk the parameters of an elemental function.  For now we always pass
     by reference.  */
  if (sym->attr.elemental)
5663 5664
    return gfc_walk_elemental_function_args (ss, expr->value.function.actual,
					     GFC_SS_REFERENCE);
5665

5666
  /* Scalar functions are OK as these are evaluated outside the scalarization
5667 5668 5669 5670 5671 5672 5673 5674 5675 5676 5677 5678 5679 5680 5681 5682 5683 5684 5685 5686 5687 5688 5689 5690 5691
     loop.  Pass back and let the caller deal with it.  */
  return ss;
}


/* An array temporary is constructed for array constructors.  */

static gfc_ss *
gfc_walk_array_constructor (gfc_ss * ss, gfc_expr * expr)
{
  gfc_ss *newss;
  int n;

  newss = gfc_get_ss ();
  newss->type = GFC_SS_CONSTRUCTOR;
  newss->expr = expr;
  newss->next = ss;
  newss->data.info.dimen = expr->rank;
  for (n = 0; n < expr->rank; n++)
    newss->data.info.dim[n] = n;

  return newss;
}


5692
/* Walk an expression.  Add walked expressions to the head of the SS chain.
5693
   A wholly scalar expression will not be added.  */
5694 5695 5696 5697 5698 5699 5700 5701 5702 5703 5704 5705 5706 5707 5708 5709 5710 5711 5712 5713 5714 5715 5716 5717 5718 5719 5720 5721 5722 5723 5724 5725 5726 5727 5728 5729 5730 5731 5732 5733 5734 5735 5736 5737 5738

static gfc_ss *
gfc_walk_subexpr (gfc_ss * ss, gfc_expr * expr)
{
  gfc_ss *head;

  switch (expr->expr_type)
    {
    case EXPR_VARIABLE:
      head = gfc_walk_variable_expr (ss, expr);
      return head;

    case EXPR_OP:
      head = gfc_walk_op_expr (ss, expr);
      return head;

    case EXPR_FUNCTION:
      head = gfc_walk_function_expr (ss, expr);
      return head;

    case EXPR_CONSTANT:
    case EXPR_NULL:
    case EXPR_STRUCTURE:
      /* Pass back and let the caller deal with it.  */
      break;

    case EXPR_ARRAY:
      head = gfc_walk_array_constructor (ss, expr);
      return head;

    case EXPR_SUBSTRING:
      /* Pass back and let the caller deal with it.  */
      break;

    default:
      internal_error ("bad expression type during walk (%d)",
		      expr->expr_type);
    }
  return ss;
}


/* Entry point for expression walking.
   A return value equal to the passed chain means this is
   a scalar expression.  It is up to the caller to take whatever action is
5739
   necessary to translate these.  */
5740 5741 5742 5743 5744 5745 5746 5747 5748

gfc_ss *
gfc_walk_expr (gfc_expr * expr)
{
  gfc_ss *res;

  res = gfc_walk_subexpr (gfc_ss_terminator, expr);
  return gfc_reverse_ss (res);
}