OSDN Git Service

2008-01-20 Paul Thomas <pault@gcc.gnu.org>
[pf3gnuchains/gcc-fork.git] / gcc / fortran / trans-array.c
1 /* Array translation routines
2    Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007
3    Free Software Foundation, Inc.
4    Contributed by Paul Brook <paul@nowt.org>
5    and Steven Bosscher <s.bosscher@student.tudelft.nl>
6
7 This file is part of GCC.
8
9 GCC is free software; you can redistribute it and/or modify it under
10 the terms of the GNU General Public License as published by the Free
11 Software Foundation; either version 3, or (at your option) any later
12 version.
13
14 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
15 WARRANTY; without even the implied warranty of MERCHANTABILITY or
16 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
17 for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with GCC; see the file COPYING3.  If not see
21 <http://www.gnu.org/licenses/>.  */
22
23 /* trans-array.c-- Various array related code, including scalarization,
24                    allocation, initialization and other support routines.  */
25
26 /* How the scalarizer works.
27    In gfortran, array expressions use the same core routines as scalar
28    expressions.
29    First, a Scalarization State (SS) chain is built.  This is done by walking
30    the expression tree, and building a linear list of the terms in the
31    expression.  As the tree is walked, scalar subexpressions are translated.
32
33    The scalarization parameters are stored in a gfc_loopinfo structure.
34    First the start and stride of each term is calculated by
35    gfc_conv_ss_startstride.  During this process the expressions for the array
36    descriptors and data pointers are also translated.
37
38    If the expression is an assignment, we must then resolve any dependencies.
39    In fortran all the rhs values of an assignment must be evaluated before
40    any assignments take place.  This can require a temporary array to store the
41    values.  We also require a temporary when we are passing array expressions
42    or vector subecripts as procedure parameters.
43
44    Array sections are passed without copying to a temporary.  These use the
45    scalarizer to determine the shape of the section.  The flag
46    loop->array_parameter tells the scalarizer that the actual values and loop
47    variables will not be required.
48
49    The function gfc_conv_loop_setup generates the scalarization setup code.
50    It determines the range of the scalarizing loop variables.  If a temporary
51    is required, this is created and initialized.  Code for scalar expressions
52    taken outside the loop is also generated at this time.  Next the offset and
53    scaling required to translate from loop variables to array indices for each
54    term is calculated.
55
56    A call to gfc_start_scalarized_body marks the start of the scalarized
57    expression.  This creates a scope and declares the loop variables.  Before
58    calling this gfc_make_ss_chain_used must be used to indicate which terms
59    will be used inside this loop.
60
61    The scalar gfc_conv_* functions are then used to build the main body of the
62    scalarization loop.  Scalarization loop variables and precalculated scalar
63    values are automatically substituted.  Note that gfc_advance_se_ss_chain
64    must be used, rather than changing the se->ss directly.
65
66    For assignment expressions requiring a temporary two sub loops are
67    generated.  The first stores the result of the expression in the temporary,
68    the second copies it to the result.  A call to
69    gfc_trans_scalarized_loop_boundary marks the end of the main loop code and
70    the start of the copying loop.  The temporary may be less than full rank.
71
72    Finally gfc_trans_scalarizing_loops is called to generate the implicit do
73    loops.  The loops are added to the pre chain of the loopinfo.  The post
74    chain may still contain cleanup code.
75
76    After the loop code has been added into its parent scope gfc_cleanup_loop
77    is called to free all the SS allocated by the scalarizer.  */
78
79 #include "config.h"
80 #include "system.h"
81 #include "coretypes.h"
82 #include "tree.h"
83 #include "tree-gimple.h"
84 #include "ggc.h"
85 #include "toplev.h"
86 #include "real.h"
87 #include "flags.h"
88 #include "gfortran.h"
89 #include "trans.h"
90 #include "trans-stmt.h"
91 #include "trans-types.h"
92 #include "trans-array.h"
93 #include "trans-const.h"
94 #include "dependency.h"
95
96 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 static gfc_ss gfc_ss_terminator_var;
101 gfc_ss * const gfc_ss_terminator = &gfc_ss_terminator_var;
102
103
104 static tree
105 gfc_array_dataptr_type (tree desc)
106 {
107   return (GFC_TYPE_ARRAY_DATAPTR_TYPE (TREE_TYPE (desc)));
108 }
109
110
111 /* Build expressions to access the members of an array descriptor.
112    It's surprisingly easy to mess up here, so never access
113    an array descriptor by "brute force", always use these
114    functions.  This also avoids problems if we change the format
115    of an array descriptor.
116
117    To understand these magic numbers, look at the comments
118    before gfc_build_array_type() in trans-types.c.
119
120    The code within these defines should be the only code which knows the format
121    of an array descriptor.
122
123    Any code just needing to read obtain the bounds of an array should use
124    gfc_conv_array_* rather than the following functions as these will return
125    know constant values, and work with arrays which do not have descriptors.
126
127    Don't forget to #undef these!  */
128
129 #define DATA_FIELD 0
130 #define OFFSET_FIELD 1
131 #define DTYPE_FIELD 2
132 #define DIMENSION_FIELD 3
133
134 #define STRIDE_SUBFIELD 0
135 #define LBOUND_SUBFIELD 1
136 #define UBOUND_SUBFIELD 2
137
138 /* This provides READ-ONLY access to the data field.  The field itself
139    doesn't have the proper type.  */
140
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   t = build3 (COMPONENT_REF, TREE_TYPE (field), desc, field, NULL_TREE);
153   t = fold_convert (GFC_TYPE_ARRAY_DATAPTR_TYPE (type), t);
154
155   return t;
156 }
157
158 /* This provides WRITE access to the data field.
159
160    TUPLES_P is true if we are generating tuples.
161    
162    This function gets called through the following macros:
163      gfc_conv_descriptor_data_set
164      gfc_conv_descriptor_data_set_tuples.  */
165
166 void
167 gfc_conv_descriptor_data_set_internal (stmtblock_t *block,
168                                        tree desc, tree value,
169                                        bool tuples_p)
170 {
171   tree field, type, t;
172
173   type = TREE_TYPE (desc);
174   gcc_assert (GFC_DESCRIPTOR_TYPE_P (type));
175
176   field = TYPE_FIELDS (type);
177   gcc_assert (DATA_FIELD == 0);
178
179   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 /* This provides address access to the data field.  This should only be
185    used by array allocation, passing this on to the runtime.  */
186
187 tree
188 gfc_conv_descriptor_data_addr (tree desc)
189 {
190   tree field, type, t;
191
192   type = TREE_TYPE (desc);
193   gcc_assert (GFC_DESCRIPTOR_TYPE_P (type));
194
195   field = TYPE_FIELDS (type);
196   gcc_assert (DATA_FIELD == 0);
197
198   t = build3 (COMPONENT_REF, TREE_TYPE (field), desc, field, NULL_TREE);
199   return build_fold_addr_expr (t);
200 }
201
202 tree
203 gfc_conv_descriptor_offset (tree desc)
204 {
205   tree type;
206   tree field;
207
208   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 tree
218 gfc_conv_descriptor_dtype (tree desc)
219 {
220   tree field;
221   tree type;
222
223   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 static tree
233 gfc_conv_descriptor_dimension (tree desc, tree dim)
234 {
235   tree field;
236   tree type;
237   tree tmp;
238
239   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           && TREE_CODE (TREE_TYPE (field)) == ARRAY_TYPE
245           && TREE_CODE (TREE_TYPE (TREE_TYPE (field))) == RECORD_TYPE);
246
247   tmp = build3 (COMPONENT_REF, TREE_TYPE (field), desc, field, NULL_TREE);
248   tmp = gfc_build_array_ref (tmp, dim, NULL);
249   return tmp;
250 }
251
252 tree
253 gfc_conv_descriptor_stride (tree desc, tree dim)
254 {
255   tree tmp;
256   tree field;
257
258   tmp = gfc_conv_descriptor_dimension (desc, dim);
259   field = TYPE_FIELDS (TREE_TYPE (tmp));
260   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   return tmp;
265 }
266
267 tree
268 gfc_conv_descriptor_lbound (tree desc, tree dim)
269 {
270   tree tmp;
271   tree field;
272
273   tmp = gfc_conv_descriptor_dimension (desc, dim);
274   field = TYPE_FIELDS (TREE_TYPE (tmp));
275   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   return tmp;
280 }
281
282 tree
283 gfc_conv_descriptor_ubound (tree desc, tree dim)
284 {
285   tree tmp;
286   tree field;
287
288   tmp = gfc_conv_descriptor_dimension (desc, dim);
289   field = TYPE_FIELDS (TREE_TYPE (tmp));
290   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   return tmp;
295 }
296
297
298 /* Build a null array descriptor constructor.  */
299
300 tree
301 gfc_build_null_descriptor (tree type)
302 {
303   tree field;
304   tree tmp;
305
306   gcc_assert (GFC_DESCRIPTOR_TYPE_P (type));
307   gcc_assert (DATA_FIELD == 0);
308   field = TYPE_FIELDS (type);
309
310   /* Set a NULL data pointer.  */
311   tmp = build_constructor_single (type, field, null_pointer_node);
312   TREE_CONSTANT (tmp) = 1;
313   TREE_INVARIANT (tmp) = 1;
314   /* All other fields are ignored.  */
315
316   return tmp;
317 }
318
319
320 /* Cleanup those #defines.  */
321
322 #undef DATA_FIELD
323 #undef OFFSET_FIELD
324 #undef DTYPE_FIELD
325 #undef DIMENSION_FIELD
326 #undef STRIDE_SUBFIELD
327 #undef LBOUND_SUBFIELD
328 #undef UBOUND_SUBFIELD
329
330
331 /* Mark a SS chain as used.  Flags specifies in which loops the SS is used.
332    flags & 1 = Main loop body.
333    flags & 2 = temp copy loop.  */
334
335 void
336 gfc_mark_ss_chain_used (gfc_ss * ss, unsigned flags)
337 {
338   for (; ss != gfc_ss_terminator; ss = ss->next)
339     ss->useflags = flags;
340 }
341
342 static void gfc_free_ss (gfc_ss *);
343
344
345 /* Free a gfc_ss chain.  */
346
347 static void
348 gfc_free_ss_chain (gfc_ss * ss)
349 {
350   gfc_ss *next;
351
352   while (ss != gfc_ss_terminator)
353     {
354       gcc_assert (ss != NULL);
355       next = ss->next;
356       gfc_free_ss (ss);
357       ss = next;
358     }
359 }
360
361
362 /* Free a SS.  */
363
364 static void
365 gfc_free_ss (gfc_ss * ss)
366 {
367   int n;
368
369   switch (ss->type)
370     {
371     case GFC_SS_SECTION:
372       for (n = 0; n < GFC_MAX_DIMENSIONS; n++)
373         {
374           if (ss->data.info.subscript[n])
375             gfc_free_ss_chain (ss->data.info.subscript[n]);
376         }
377       break;
378
379     default:
380       break;
381     }
382
383   gfc_free (ss);
384 }
385
386
387 /* Free all the SS associated with a loop.  */
388
389 void
390 gfc_cleanup_loop (gfc_loopinfo * loop)
391 {
392   gfc_ss *ss;
393   gfc_ss *next;
394
395   ss = loop->ss;
396   while (ss != gfc_ss_terminator)
397     {
398       gcc_assert (ss != NULL);
399       next = ss->loop_chain;
400       gfc_free_ss (ss);
401       ss = next;
402     }
403 }
404
405
406 /* Associate a SS chain with a loop.  */
407
408 void
409 gfc_add_ss_to_loop (gfc_loopinfo * loop, gfc_ss * head)
410 {
411   gfc_ss *ss;
412
413   if (head == gfc_ss_terminator)
414     return;
415
416   ss = head;
417   for (; ss && ss != gfc_ss_terminator; ss = ss->next)
418     {
419       if (ss->next == gfc_ss_terminator)
420         ss->loop_chain = loop->ss;
421       else
422         ss->loop_chain = ss->next;
423     }
424   gcc_assert (ss == gfc_ss_terminator);
425   loop->ss = head;
426 }
427
428
429 /* Generate an initializer for a static pointer or allocatable array.  */
430
431 void
432 gfc_trans_static_array_pointer (gfc_symbol * sym)
433 {
434   tree type;
435
436   gcc_assert (TREE_STATIC (sym->backend_decl));
437   /* Just zero the data member.  */
438   type = TREE_TYPE (sym->backend_decl);
439   DECL_INITIAL (sym->backend_decl) = gfc_build_null_descriptor (type);
440 }
441
442
443 /* If the bounds of SE's loop have not yet been set, see if they can be
444    determined from array spec AS, which is the array spec of a called
445    function.  MAPPING maps the callee's dummy arguments to the values
446    that the caller is passing.  Add any initialization and finalization
447    code to SE.  */
448
449 void
450 gfc_set_loop_bounds_from_array_spec (gfc_interface_mapping * mapping,
451                                      gfc_se * se, gfc_array_spec * as)
452 {
453   int n, dim;
454   gfc_se tmpse;
455   tree lower;
456   tree upper;
457   tree tmp;
458
459   if (as && as->type == AS_EXPLICIT)
460     for (dim = 0; dim < se->loop->dimen; dim++)
461       {
462         n = se->loop->order[dim];
463         if (se->loop->to[n] == NULL_TREE)
464           {
465             /* Evaluate the lower bound.  */
466             gfc_init_se (&tmpse, NULL);
467             gfc_apply_interface_mapping (mapping, &tmpse, as->lower[dim]);
468             gfc_add_block_to_block (&se->pre, &tmpse.pre);
469             gfc_add_block_to_block (&se->post, &tmpse.post);
470             lower = tmpse.expr;
471
472             /* ...and the upper bound.  */
473             gfc_init_se (&tmpse, NULL);
474             gfc_apply_interface_mapping (mapping, &tmpse, as->upper[dim]);
475             gfc_add_block_to_block (&se->pre, &tmpse.pre);
476             gfc_add_block_to_block (&se->post, &tmpse.post);
477             upper = tmpse.expr;
478
479             /* Set the upper bound of the loop to UPPER - LOWER.  */
480             tmp = fold_build2 (MINUS_EXPR, gfc_array_index_type, upper, lower);
481             tmp = gfc_evaluate_now (tmp, &se->pre);
482             se->loop->to[n] = tmp;
483           }
484       }
485 }
486
487
488 /* Generate code to allocate an array temporary, or create a variable to
489    hold the data.  If size is NULL, zero the descriptor so that the
490    callee will allocate the array.  If DEALLOC is true, also generate code to
491    free the array afterwards.
492
493    Initialization code is added to PRE and finalization code to POST.
494    DYNAMIC is true if the caller may want to extend the array later
495    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                                   gfc_ss_info * info, tree size, tree nelem,
500                                   bool dynamic, bool dealloc)
501 {
502   tree tmp;
503   tree desc;
504   bool onstack;
505
506   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   else
515     {
516       /* Allocate the temporary.  */
517       onstack = !dynamic && gfc_can_put_var_on_stack (size);
518
519       if (onstack)
520         {
521           /* Make a temporary variable to hold the data.  */
522           tmp = fold_build2 (MINUS_EXPR, TREE_TYPE (nelem), nelem,
523                              gfc_index_one_node);
524           tmp = build_range_type (gfc_array_index_type, gfc_index_zero_node,
525                                   tmp);
526           tmp = build_array_type (gfc_get_element_type (TREE_TYPE (desc)),
527                                   tmp);
528           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           tmp = gfc_evaluate_now (tmp, pre);
537           gfc_conv_descriptor_data_set (pre, desc, tmp);
538         }
539     }
540   info->data = gfc_conv_descriptor_data_get (desc);
541
542   /* The offset is zero because we create temporaries with a zero
543      lower bound.  */
544   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    functions returning arrays.  Adjusts the loop variables to be
560    zero-based, and calculates the loop bounds for callee allocated arrays.
561    Allocate the array unless it's callee allocated (we have a callee
562    allocated array if 'callee_alloc' is true, or if loop->to[n] is
563    NULL_TREE for any n).  Also fills in the descriptor, data and offset
564    fields of info if known.  Returns the size of the array, or NULL for a
565    callee allocated array.
566
567    PRE, POST, DYNAMIC and DEALLOC are as for gfc_trans_allocate_array_storage.
568  */
569
570 tree
571 gfc_trans_create_temp_array (stmtblock_t * pre, stmtblock_t * post,
572                              gfc_loopinfo * loop, gfc_ss_info * info,
573                              tree eltype, bool dynamic, bool dealloc,
574                              bool callee_alloc)
575 {
576   tree type;
577   tree desc;
578   tree tmp;
579   tree size;
580   tree nelem;
581   tree cond;
582   tree or_expr;
583   int n;
584   int dim;
585
586   gcc_assert (info->dimen > 0);
587   /* Set the lower bound to zero.  */
588   for (dim = 0; dim < info->dimen; dim++)
589     {
590       n = loop->order[dim];
591       if (n < loop->temp_dim)
592         gcc_assert (integer_zerop (loop->from[n]));
593       else
594         {
595           /* Callee allocated arrays may not have a known bound yet.  */
596           if (loop->to[n])
597               loop->to[n] = fold_build2 (MINUS_EXPR, gfc_array_index_type,
598                                          loop->to[n], loop->from[n]);
599           loop->from[n] = gfc_index_zero_node;
600         }
601
602       info->delta[dim] = gfc_index_zero_node;
603       info->start[dim] = gfc_index_zero_node;
604       info->end[dim] = gfc_index_zero_node;
605       info->stride[dim] = gfc_index_one_node;
606       info->dim[dim] = dim;
607     }
608
609   /* Initialize the descriptor.  */
610   type =
611     gfc_get_array_type_bounds (eltype, info->dimen, loop->from, loop->to, 1,
612                                GFC_ARRAY_UNKNOWN);
613   desc = gfc_create_var (type, "atmp");
614   GFC_DECL_PACKED_ARRAY (desc) = 1;
615
616   info->descriptor = desc;
617   size = gfc_index_one_node;
618
619   /* Fill in the array dtype.  */
620   tmp = gfc_conv_descriptor_dtype (desc);
621   gfc_add_modify_expr (pre, tmp, gfc_get_dtype (TREE_TYPE (desc)));
622
623   /*
624      Fill in the bounds and stride.  This is a packed array, so:
625
626      size = 1;
627      for (n = 0; n < rank; n++)
628        {
629          stride[n] = size
630          delta = ubound[n] + 1 - lbound[n];
631          size = size * delta;
632        }
633      size = size * sizeof(element);
634   */
635
636   or_expr = NULL_TREE;
637
638   for (n = 0; n < info->dimen; n++)
639     {
640       if (loop->to[n] == NULL_TREE)
641         {
642           /* For a callee allocated array express the loop bounds in terms
643              of the descriptor fields.  */
644           tmp = build2 (MINUS_EXPR, gfc_array_index_type,
645                         gfc_conv_descriptor_ubound (desc, gfc_rank_cst[n]),
646                         gfc_conv_descriptor_lbound (desc, gfc_rank_cst[n]));
647           loop->to[n] = tmp;
648           size = NULL_TREE;
649           continue;
650         }
651         
652       /* Store the stride and bound components in the descriptor.  */
653       tmp = gfc_conv_descriptor_stride (desc, gfc_rank_cst[n]);
654       gfc_add_modify_expr (pre, tmp, size);
655
656       tmp = gfc_conv_descriptor_lbound (desc, gfc_rank_cst[n]);
657       gfc_add_modify_expr (pre, tmp, gfc_index_zero_node);
658
659       tmp = gfc_conv_descriptor_ubound (desc, gfc_rank_cst[n]);
660       gfc_add_modify_expr (pre, tmp, loop->to[n]);
661
662       tmp = fold_build2 (PLUS_EXPR, gfc_array_index_type,
663                          loop->to[n], gfc_index_one_node);
664
665       /* Check whether the size for this dimension is negative.  */
666       cond = fold_build2 (LE_EXPR, boolean_type_node, tmp,
667                           gfc_index_zero_node);
668       cond = gfc_evaluate_now (cond, pre);
669
670       if (n == 0)
671         or_expr = cond;
672       else
673         or_expr = fold_build2 (TRUTH_OR_EXPR, boolean_type_node, or_expr, cond);
674
675       size = fold_build2 (MULT_EXPR, gfc_array_index_type, size, tmp);
676       size = gfc_evaluate_now (size, pre);
677     }
678
679   /* Get the size of the array.  */
680
681   if (size && !callee_alloc)
682     {
683       /* If or_expr is true, then the extent in at least one
684          dimension is zero and the size is set to zero.  */
685       size = fold_build3 (COND_EXPR, gfc_array_index_type,
686                           or_expr, gfc_index_zero_node, size);
687
688       nelem = size;
689       size = fold_build2 (MULT_EXPR, gfc_array_index_type, size,
690                 fold_convert (gfc_array_index_type,
691                               TYPE_SIZE_UNIT (gfc_get_element_type (type))));
692     }
693   else
694     {
695       nelem = size;
696       size = NULL_TREE;
697     }
698
699   gfc_trans_allocate_array_storage (pre, post, info, size, nelem, dynamic,
700                                     dealloc);
701
702   if (info->dimen > loop->temp_dim)
703     loop->temp_dim = info->dimen;
704
705   return size;
706 }
707
708
709 /* Generate code to transpose array EXPR by creating a new descriptor
710    in which the dimension specifications have been reversed.  */
711
712 void
713 gfc_conv_array_transpose (gfc_se * se, gfc_expr * expr)
714 {
715   tree dest, src, dest_index, src_index;
716   gfc_loopinfo *loop;
717   gfc_ss_info *dest_info, *src_info;
718   gfc_ss *dest_ss, *src_ss;
719   gfc_se src_se;
720   int n;
721
722   loop = se->loop;
723
724   src_ss = gfc_walk_expr (expr);
725   dest_ss = se->ss;
726
727   src_info = &src_ss->data.info;
728   dest_info = &dest_ss->data.info;
729   gcc_assert (dest_info->dimen == 2);
730   gcc_assert (src_info->dimen == 2);
731
732   /* Get a descriptor for EXPR.  */
733   gfc_init_se (&src_se, NULL);
734   gfc_conv_expr_descriptor (&src_se, expr, src_ss);
735   gfc_add_block_to_block (&se->pre, &src_se.pre);
736   gfc_add_block_to_block (&se->post, &src_se.post);
737   src = src_se.expr;
738
739   /* Allocate a new descriptor for the return value.  */
740   dest = gfc_create_var (TREE_TYPE (src), "atmp");
741   dest_info->descriptor = dest;
742   se->expr = dest;
743
744   /* Copy across the dtype field.  */
745   gfc_add_modify_expr (&se->pre,
746                        gfc_conv_descriptor_dtype (dest),
747                        gfc_conv_descriptor_dtype (src));
748
749   /* Copy the dimension information, renumbering dimension 1 to 0 and
750      0 to 1.  */
751   for (n = 0; n < 2; n++)
752     {
753       dest_info->delta[n] = gfc_index_zero_node;
754       dest_info->start[n] = gfc_index_zero_node;
755       dest_info->end[n] = gfc_index_zero_node;
756       dest_info->stride[n] = gfc_index_one_node;
757       dest_info->dim[n] = n;
758
759       dest_index = gfc_rank_cst[n];
760       src_index = gfc_rank_cst[1 - n];
761
762       gfc_add_modify_expr (&se->pre,
763                            gfc_conv_descriptor_stride (dest, dest_index),
764                            gfc_conv_descriptor_stride (src, src_index));
765
766       gfc_add_modify_expr (&se->pre,
767                            gfc_conv_descriptor_lbound (dest, dest_index),
768                            gfc_conv_descriptor_lbound (src, src_index));
769
770       gfc_add_modify_expr (&se->pre,
771                            gfc_conv_descriptor_ubound (dest, dest_index),
772                            gfc_conv_descriptor_ubound (src, src_index));
773
774       if (!loop->to[n])
775         {
776           gcc_assert (integer_zerop (loop->from[n]));
777           loop->to[n] = build2 (MINUS_EXPR, gfc_array_index_type,
778                                 gfc_conv_descriptor_ubound (dest, dest_index),
779                                 gfc_conv_descriptor_lbound (dest, dest_index));
780         }
781     }
782
783   /* Copy the data pointer.  */
784   dest_info->data = gfc_conv_descriptor_data_get (src);
785   gfc_conv_descriptor_data_set (&se->pre, dest, dest_info->data);
786
787   /* Copy the offset.  This is not changed by transposition; the top-left
788      element is still at the same offset as before, except where the loop
789      starts at zero.  */
790   if (!integer_zerop (loop->from[0]))
791     dest_info->offset = gfc_conv_descriptor_offset (src);
792   else
793     dest_info->offset = gfc_index_zero_node;
794
795   gfc_add_modify_expr (&se->pre,
796                        gfc_conv_descriptor_offset (dest),
797                        dest_info->offset);
798           
799   if (dest_info->dimen > loop->temp_dim)
800     loop->temp_dim = dest_info->dimen;
801 }
802
803
804 /* Return the number of iterations in a loop that starts at START,
805    ends at END, and has step STEP.  */
806
807 static tree
808 gfc_get_iteration_count (tree start, tree end, tree step)
809 {
810   tree tmp;
811   tree type;
812
813   type = TREE_TYPE (step);
814   tmp = fold_build2 (MINUS_EXPR, type, end, start);
815   tmp = fold_build2 (FLOOR_DIV_EXPR, type, tmp, step);
816   tmp = fold_build2 (PLUS_EXPR, type, tmp, build_int_cst (type, 1));
817   tmp = fold_build2 (MAX_EXPR, type, tmp, build_int_cst (type, 0));
818   return fold_convert (gfc_array_index_type, tmp);
819 }
820
821
822 /* Extend the data in array DESC by EXTRA elements.  */
823
824 static void
825 gfc_grow_array (stmtblock_t * pblock, tree desc, tree extra)
826 {
827   tree arg0, arg1;
828   tree tmp;
829   tree size;
830   tree ubound;
831
832   if (integer_zerop (extra))
833     return;
834
835   ubound = gfc_conv_descriptor_ubound (desc, gfc_rank_cst[0]);
836
837   /* Add EXTRA to the upper bound.  */
838   tmp = build2 (PLUS_EXPR, gfc_array_index_type, ubound, extra);
839   gfc_add_modify_expr (pblock, ubound, tmp);
840
841   /* Get the value of the current data pointer.  */
842   arg0 = gfc_conv_descriptor_data_get (desc);
843
844   /* Calculate the new array size.  */
845   size = TYPE_SIZE_UNIT (gfc_get_element_type (TREE_TYPE (desc)));
846   tmp = build2 (PLUS_EXPR, gfc_array_index_type, ubound, gfc_index_one_node);
847   arg1 = build2 (MULT_EXPR, size_type_node, fold_convert (size_type_node, tmp),
848                  fold_convert (size_type_node, size));
849
850   /* Call the realloc() function.  */
851   tmp = gfc_call_realloc (pblock, arg0, arg1);
852   gfc_conv_descriptor_data_set (pblock, desc, tmp);
853 }
854
855
856 /* Return true if the bounds of iterator I can only be determined
857    at run time.  */
858
859 static inline bool
860 gfc_iterator_has_dynamic_bounds (gfc_iterator * i)
861 {
862   return (i->start->expr_type != EXPR_CONSTANT
863           || i->end->expr_type != EXPR_CONSTANT
864           || i->step->expr_type != EXPR_CONSTANT);
865 }
866
867
868 /* Split the size of constructor element EXPR into the sum of two terms,
869    one of which can be determined at compile time and one of which must
870    be calculated at run time.  Set *SIZE to the former and return true
871    if the latter might be nonzero.  */
872
873 static bool
874 gfc_get_array_constructor_element_size (mpz_t * size, gfc_expr * expr)
875 {
876   if (expr->expr_type == EXPR_ARRAY)
877     return gfc_get_array_constructor_size (size, expr->value.constructor);
878   else if (expr->rank > 0)
879     {
880       /* Calculate everything at run time.  */
881       mpz_set_ui (*size, 0);
882       return true;
883     }
884   else
885     {
886       /* A single element.  */
887       mpz_set_ui (*size, 1);
888       return false;
889     }
890 }
891
892
893 /* Like gfc_get_array_constructor_element_size, but applied to the whole
894    of array constructor C.  */
895
896 static bool
897 gfc_get_array_constructor_size (mpz_t * size, gfc_constructor * c)
898 {
899   gfc_iterator *i;
900   mpz_t val;
901   mpz_t len;
902   bool dynamic;
903
904   mpz_set_ui (*size, 0);
905   mpz_init (len);
906   mpz_init (val);
907
908   dynamic = false;
909   for (; c; c = c->next)
910     {
911       i = c->iterator;
912       if (i && gfc_iterator_has_dynamic_bounds (i))
913         dynamic = true;
914       else
915         {
916           dynamic |= gfc_get_array_constructor_element_size (&len, c->expr);
917           if (i)
918             {
919               /* Multiply the static part of the element size by the
920                  number of iterations.  */
921               mpz_sub (val, i->end->value.integer, i->start->value.integer);
922               mpz_fdiv_q (val, val, i->step->value.integer);
923               mpz_add_ui (val, val, 1);
924               if (mpz_sgn (val) > 0)
925                 mpz_mul (len, len, val);
926               else
927                 mpz_set_ui (len, 0);
928             }
929           mpz_add (*size, *size, len);
930         }
931     }
932   mpz_clear (len);
933   mpz_clear (val);
934   return dynamic;
935 }
936
937
938 /* Make sure offset is a variable.  */
939
940 static void
941 gfc_put_offset_into_var (stmtblock_t * pblock, tree * poffset,
942                          tree * offsetvar)
943 {
944   /* We should have already created the offset variable.  We cannot
945      create it here because we may be in an inner scope.  */
946   gcc_assert (*offsetvar != NULL_TREE);
947   gfc_add_modify_expr (pblock, *offsetvar, *poffset);
948   *poffset = *offsetvar;
949   TREE_USED (*offsetvar) = 1;
950 }
951
952
953 /* Assign an element of an array constructor.  */
954 static bool first_len;
955 static tree first_len_val; 
956
957 static void
958 gfc_trans_array_ctor_element (stmtblock_t * pblock, tree desc,
959                               tree offset, gfc_se * se, gfc_expr * expr)
960 {
961   tree tmp;
962   tree esize;
963
964   gfc_conv_expr (se, expr);
965
966   /* Store the value.  */
967   tmp = build_fold_indirect_ref (gfc_conv_descriptor_data_get (desc));
968   tmp = gfc_build_array_ref (tmp, offset, NULL);
969
970   esize = size_in_bytes (gfc_get_element_type (TREE_TYPE (desc)));
971   esize = fold_convert (gfc_charlen_type_node, esize);
972
973   if (expr->ts.type == BT_CHARACTER)
974     {
975       gfc_conv_string_parameter (se);
976       if (POINTER_TYPE_P (TREE_TYPE (tmp)))
977         {
978           /* The temporary is an array of pointers.  */
979           se->expr = fold_convert (TREE_TYPE (tmp), se->expr);
980           gfc_add_modify_expr (&se->pre, tmp, se->expr);
981         }
982       else
983         {
984           /* The temporary is an array of string values.  */
985           tmp = gfc_build_addr_expr (pchar_type_node, tmp);
986           /* We know the temporary and the value will be the same length,
987              so can use memcpy.  */
988           gfc_trans_string_copy (&se->pre, esize, tmp,
989                                  se->string_length,
990                                  se->expr);
991         }
992       if (flag_bounds_check)
993         {
994           if (first_len)
995             {
996               gfc_add_modify_expr (&se->pre, first_len_val,
997                                    se->string_length);
998               first_len = false;
999             }
1000           else
1001             {
1002               /* Verify that all constructor elements are of the same
1003                  length.  */
1004               tree cond = fold_build2 (NE_EXPR, boolean_type_node,
1005                                        first_len_val, se->string_length);
1006               gfc_trans_runtime_check
1007                 (cond, &se->pre, &expr->where,
1008                  "Different CHARACTER lengths (%ld/%ld) in array constructor",
1009                  fold_convert (long_integer_type_node, first_len_val),
1010                  fold_convert (long_integer_type_node, se->string_length));
1011             }
1012         }
1013     }
1014   else
1015     {
1016       /* TODO: Should the frontend already have done this conversion?  */
1017       se->expr = fold_convert (TREE_TYPE (tmp), se->expr);
1018       gfc_add_modify_expr (&se->pre, tmp, se->expr);
1019     }
1020
1021   gfc_add_block_to_block (pblock, &se->pre);
1022   gfc_add_block_to_block (pblock, &se->post);
1023 }
1024
1025
1026 /* Add the contents of an array to the constructor.  DYNAMIC is as for
1027    gfc_trans_array_constructor_value.  */
1028
1029 static void
1030 gfc_trans_array_constructor_subarray (stmtblock_t * pblock,
1031                                       tree type ATTRIBUTE_UNUSED,
1032                                       tree desc, gfc_expr * expr,
1033                                       tree * poffset, tree * offsetvar,
1034                                       bool dynamic)
1035 {
1036   gfc_se se;
1037   gfc_ss *ss;
1038   gfc_loopinfo loop;
1039   stmtblock_t body;
1040   tree tmp;
1041   tree size;
1042   int n;
1043
1044   /* We need this to be a variable so we can increment it.  */
1045   gfc_put_offset_into_var (pblock, poffset, offsetvar);
1046
1047   gfc_init_se (&se, NULL);
1048
1049   /* Walk the array expression.  */
1050   ss = gfc_walk_expr (expr);
1051   gcc_assert (ss != gfc_ss_terminator);
1052
1053   /* Initialize the scalarizer.  */
1054   gfc_init_loopinfo (&loop);
1055   gfc_add_ss_to_loop (&loop, ss);
1056
1057   /* Initialize the loop.  */
1058   gfc_conv_ss_startstride (&loop);
1059   gfc_conv_loop_setup (&loop);
1060
1061   /* Make sure the constructed array has room for the new data.  */
1062   if (dynamic)
1063     {
1064       /* Set SIZE to the total number of elements in the subarray.  */
1065       size = gfc_index_one_node;
1066       for (n = 0; n < loop.dimen; n++)
1067         {
1068           tmp = gfc_get_iteration_count (loop.from[n], loop.to[n],
1069                                          gfc_index_one_node);
1070           size = fold_build2 (MULT_EXPR, gfc_array_index_type, size, tmp);
1071         }
1072
1073       /* Grow the constructed array by SIZE elements.  */
1074       gfc_grow_array (&loop.pre, desc, size);
1075     }
1076
1077   /* Make the loop body.  */
1078   gfc_mark_ss_chain_used (ss, 1);
1079   gfc_start_scalarized_body (&loop, &body);
1080   gfc_copy_loopinfo_to_se (&se, &loop);
1081   se.ss = ss;
1082
1083   gfc_trans_array_ctor_element (&body, desc, *poffset, &se, expr);
1084   gcc_assert (se.ss == gfc_ss_terminator);
1085
1086   /* Increment the offset.  */
1087   tmp = build2 (PLUS_EXPR, gfc_array_index_type, *poffset, gfc_index_one_node);
1088   gfc_add_modify_expr (&body, *poffset, tmp);
1089
1090   /* Finish the loop.  */
1091   gfc_trans_scalarizing_loops (&loop, &body);
1092   gfc_add_block_to_block (&loop.pre, &loop.post);
1093   tmp = gfc_finish_block (&loop.pre);
1094   gfc_add_expr_to_block (pblock, tmp);
1095
1096   gfc_cleanup_loop (&loop);
1097 }
1098
1099
1100 /* Assign the values to the elements of an array constructor.  DYNAMIC
1101    is true if descriptor DESC only contains enough data for the static
1102    size calculated by gfc_get_array_constructor_size.  When true, memory
1103    for the dynamic parts must be allocated using realloc.  */
1104
1105 static void
1106 gfc_trans_array_constructor_value (stmtblock_t * pblock, tree type,
1107                                    tree desc, gfc_constructor * c,
1108                                    tree * poffset, tree * offsetvar,
1109                                    bool dynamic)
1110 {
1111   tree tmp;
1112   stmtblock_t body;
1113   gfc_se se;
1114   mpz_t size;
1115
1116   mpz_init (size);
1117   for (; c; c = c->next)
1118     {
1119       /* If this is an iterator or an array, the offset must be a variable.  */
1120       if ((c->iterator || c->expr->rank > 0) && INTEGER_CST_P (*poffset))
1121         gfc_put_offset_into_var (pblock, poffset, offsetvar);
1122
1123       gfc_start_block (&body);
1124
1125       if (c->expr->expr_type == EXPR_ARRAY)
1126         {
1127           /* Array constructors can be nested.  */
1128           gfc_trans_array_constructor_value (&body, type, desc,
1129                                              c->expr->value.constructor,
1130                                              poffset, offsetvar, dynamic);
1131         }
1132       else if (c->expr->rank > 0)
1133         {
1134           gfc_trans_array_constructor_subarray (&body, type, desc, c->expr,
1135                                                 poffset, offsetvar, dynamic);
1136         }
1137       else
1138         {
1139           /* This code really upsets the gimplifier so don't bother for now.  */
1140           gfc_constructor *p;
1141           HOST_WIDE_INT n;
1142           HOST_WIDE_INT size;
1143
1144           p = c;
1145           n = 0;
1146           while (p && !(p->iterator || p->expr->expr_type != EXPR_CONSTANT))
1147             {
1148               p = p->next;
1149               n++;
1150             }
1151           if (n < 4)
1152             {
1153               /* Scalar values.  */
1154               gfc_init_se (&se, NULL);
1155               gfc_trans_array_ctor_element (&body, desc, *poffset,
1156                                             &se, c->expr);
1157
1158               *poffset = fold_build2 (PLUS_EXPR, gfc_array_index_type,
1159                                       *poffset, gfc_index_one_node);
1160             }
1161           else
1162             {
1163               /* Collect multiple scalar constants into a constructor.  */
1164               tree list;
1165               tree init;
1166               tree bound;
1167               tree tmptype;
1168
1169               p = c;
1170               list = NULL_TREE;
1171               /* Count the number of consecutive scalar constants.  */
1172               while (p && !(p->iterator
1173                             || p->expr->expr_type != EXPR_CONSTANT))
1174                 {
1175                   gfc_init_se (&se, NULL);
1176                   gfc_conv_constant (&se, p->expr);
1177                   if (p->expr->ts.type == BT_CHARACTER
1178                       && POINTER_TYPE_P (type))
1179                     {
1180                       /* For constant character array constructors we build
1181                          an array of pointers.  */
1182                       se.expr = gfc_build_addr_expr (pchar_type_node,
1183                                                      se.expr);
1184                     }
1185                     
1186                   list = tree_cons (NULL_TREE, se.expr, list);
1187                   c = p;
1188                   p = p->next;
1189                 }
1190
1191               bound = build_int_cst (NULL_TREE, n - 1);
1192               /* Create an array type to hold them.  */
1193               tmptype = build_range_type (gfc_array_index_type,
1194                                           gfc_index_zero_node, bound);
1195               tmptype = build_array_type (type, tmptype);
1196
1197               init = build_constructor_from_list (tmptype, nreverse (list));
1198               TREE_CONSTANT (init) = 1;
1199               TREE_INVARIANT (init) = 1;
1200               TREE_STATIC (init) = 1;
1201               /* Create a static variable to hold the data.  */
1202               tmp = gfc_create_var (tmptype, "data");
1203               TREE_STATIC (tmp) = 1;
1204               TREE_CONSTANT (tmp) = 1;
1205               TREE_INVARIANT (tmp) = 1;
1206               TREE_READONLY (tmp) = 1;
1207               DECL_INITIAL (tmp) = init;
1208               init = tmp;
1209
1210               /* Use BUILTIN_MEMCPY to assign the values.  */
1211               tmp = gfc_conv_descriptor_data_get (desc);
1212               tmp = build_fold_indirect_ref (tmp);
1213               tmp = gfc_build_array_ref (tmp, *poffset, NULL);
1214               tmp = build_fold_addr_expr (tmp);
1215               init = build_fold_addr_expr (init);
1216
1217               size = TREE_INT_CST_LOW (TYPE_SIZE_UNIT (type));
1218               bound = build_int_cst (NULL_TREE, n * size);
1219               tmp = build_call_expr (built_in_decls[BUILT_IN_MEMCPY], 3,
1220                                      tmp, init, bound);
1221               gfc_add_expr_to_block (&body, tmp);
1222
1223               *poffset = fold_build2 (PLUS_EXPR, gfc_array_index_type,
1224                                       *poffset,
1225                                       build_int_cst (gfc_array_index_type, n));
1226             }
1227           if (!INTEGER_CST_P (*poffset))
1228             {
1229               gfc_add_modify_expr (&body, *offsetvar, *poffset);
1230               *poffset = *offsetvar;
1231             }
1232         }
1233
1234       /* The frontend should already have done any expansions possible
1235          at compile-time.  */
1236       if (!c->iterator)
1237         {
1238           /* Pass the code as is.  */
1239           tmp = gfc_finish_block (&body);
1240           gfc_add_expr_to_block (pblock, tmp);
1241         }
1242       else
1243         {
1244           /* Build the implied do-loop.  */
1245           tree cond;
1246           tree end;
1247           tree step;
1248           tree loopvar;
1249           tree exit_label;
1250           tree loopbody;
1251           tree tmp2;
1252           tree tmp_loopvar;
1253
1254           loopbody = gfc_finish_block (&body);
1255
1256           if (c->iterator->var->symtree->n.sym->backend_decl)
1257             {
1258               gfc_init_se (&se, NULL);
1259               gfc_conv_expr (&se, c->iterator->var);
1260               gfc_add_block_to_block (pblock, &se.pre);
1261               loopvar = se.expr;
1262             }
1263           else
1264             {
1265               /* If the iterator appears in a specification expression in
1266                  an interface mapping, we need to make a temp for the loop
1267                  variable because it is not declared locally.  */
1268               loopvar = gfc_typenode_for_spec (&c->iterator->var->ts);
1269               loopvar = gfc_create_var (loopvar, "loopvar");
1270             }
1271
1272           /* Make a temporary, store the current value in that
1273              and return it, once the loop is done.  */
1274           tmp_loopvar = gfc_create_var (TREE_TYPE (loopvar), "loopvar");
1275           gfc_add_modify_expr (pblock, tmp_loopvar, loopvar);
1276
1277           /* Initialize the loop.  */
1278           gfc_init_se (&se, NULL);
1279           gfc_conv_expr_val (&se, c->iterator->start);
1280           gfc_add_block_to_block (pblock, &se.pre);
1281           gfc_add_modify_expr (pblock, loopvar, se.expr);
1282
1283           gfc_init_se (&se, NULL);
1284           gfc_conv_expr_val (&se, c->iterator->end);
1285           gfc_add_block_to_block (pblock, &se.pre);
1286           end = gfc_evaluate_now (se.expr, pblock);
1287
1288           gfc_init_se (&se, NULL);
1289           gfc_conv_expr_val (&se, c->iterator->step);
1290           gfc_add_block_to_block (pblock, &se.pre);
1291           step = gfc_evaluate_now (se.expr, pblock);
1292
1293           /* If this array expands dynamically, and the number of iterations
1294              is not constant, we won't have allocated space for the static
1295              part of C->EXPR's size.  Do that now.  */
1296           if (dynamic && gfc_iterator_has_dynamic_bounds (c->iterator))
1297             {
1298               /* Get the number of iterations.  */
1299               tmp = gfc_get_iteration_count (loopvar, end, step);
1300
1301               /* Get the static part of C->EXPR's size.  */
1302               gfc_get_array_constructor_element_size (&size, c->expr);
1303               tmp2 = gfc_conv_mpz_to_tree (size, gfc_index_integer_kind);
1304
1305               /* Grow the array by TMP * TMP2 elements.  */
1306               tmp = fold_build2 (MULT_EXPR, gfc_array_index_type, tmp, tmp2);
1307               gfc_grow_array (pblock, desc, tmp);
1308             }
1309
1310           /* Generate the loop body.  */
1311           exit_label = gfc_build_label_decl (NULL_TREE);
1312           gfc_start_block (&body);
1313
1314           /* Generate the exit condition.  Depending on the sign of
1315              the step variable we have to generate the correct
1316              comparison.  */
1317           tmp = fold_build2 (GT_EXPR, boolean_type_node, step, 
1318                              build_int_cst (TREE_TYPE (step), 0));
1319           cond = fold_build3 (COND_EXPR, boolean_type_node, tmp,
1320                               build2 (GT_EXPR, boolean_type_node,
1321                                       loopvar, end),
1322                               build2 (LT_EXPR, boolean_type_node,
1323                                       loopvar, end));
1324           tmp = build1_v (GOTO_EXPR, exit_label);
1325           TREE_USED (exit_label) = 1;
1326           tmp = build3_v (COND_EXPR, cond, tmp, build_empty_stmt ());
1327           gfc_add_expr_to_block (&body, tmp);
1328
1329           /* The main loop body.  */
1330           gfc_add_expr_to_block (&body, loopbody);
1331
1332           /* Increase loop variable by step.  */
1333           tmp = build2 (PLUS_EXPR, TREE_TYPE (loopvar), loopvar, step);
1334           gfc_add_modify_expr (&body, loopvar, tmp);
1335
1336           /* Finish the loop.  */
1337           tmp = gfc_finish_block (&body);
1338           tmp = build1_v (LOOP_EXPR, tmp);
1339           gfc_add_expr_to_block (pblock, tmp);
1340
1341           /* Add the exit label.  */
1342           tmp = build1_v (LABEL_EXPR, exit_label);
1343           gfc_add_expr_to_block (pblock, tmp);
1344
1345           /* Restore the original value of the loop counter.  */
1346           gfc_add_modify_expr (pblock, loopvar, tmp_loopvar);
1347         }
1348     }
1349   mpz_clear (size);
1350 }
1351
1352
1353 /* Figure out the string length of a variable reference expression.
1354    Used by get_array_ctor_strlen.  */
1355
1356 static void
1357 get_array_ctor_var_strlen (gfc_expr * expr, tree * len)
1358 {
1359   gfc_ref *ref;
1360   gfc_typespec *ts;
1361   mpz_t char_len;
1362
1363   /* Don't bother if we already know the length is a constant.  */
1364   if (*len && INTEGER_CST_P (*len))
1365     return;
1366
1367   ts = &expr->symtree->n.sym->ts;
1368   for (ref = expr->ref; ref; ref = ref->next)
1369     {
1370       switch (ref->type)
1371         {
1372         case REF_ARRAY:
1373           /* Array references don't change the string length.  */
1374           break;
1375
1376         case REF_COMPONENT:
1377           /* Use the length of the component.  */
1378           ts = &ref->u.c.component->ts;
1379           break;
1380
1381         case REF_SUBSTRING:
1382           if (ref->u.ss.start->expr_type != EXPR_CONSTANT
1383               || ref->u.ss.end->expr_type != EXPR_CONSTANT)
1384             break;
1385           mpz_init_set_ui (char_len, 1);
1386           mpz_add (char_len, char_len, ref->u.ss.end->value.integer);
1387           mpz_sub (char_len, char_len, ref->u.ss.start->value.integer);
1388           *len = gfc_conv_mpz_to_tree (char_len,
1389                                        gfc_default_character_kind);
1390           *len = convert (gfc_charlen_type_node, *len);
1391           mpz_clear (char_len);
1392           return;
1393
1394         default:
1395           /* TODO: Substrings are tricky because we can't evaluate the
1396              expression more than once.  For now we just give up, and hope
1397              we can figure it out elsewhere.  */
1398           return;
1399         }
1400     }
1401
1402   *len = ts->cl->backend_decl;
1403 }
1404
1405
1406 /* A catch-all to obtain the string length for anything that is not a
1407    constant, array or variable.  */
1408 static void
1409 get_array_ctor_all_strlen (stmtblock_t *block, gfc_expr *e, tree *len)
1410 {
1411   gfc_se se;
1412   gfc_ss *ss;
1413
1414   /* Don't bother if we already know the length is a constant.  */
1415   if (*len && INTEGER_CST_P (*len))
1416     return;
1417
1418   if (!e->ref && e->ts.cl && e->ts.cl->length
1419         && e->ts.cl->length->expr_type == EXPR_CONSTANT)
1420     {
1421       /* This is easy.  */
1422       gfc_conv_const_charlen (e->ts.cl);
1423       *len = e->ts.cl->backend_decl;
1424     }
1425   else
1426     {
1427       /* Otherwise, be brutal even if inefficient.  */
1428       ss = gfc_walk_expr (e);
1429       gfc_init_se (&se, NULL);
1430
1431       /* No function call, in case of side effects.  */
1432       se.no_function_call = 1;
1433       if (ss == gfc_ss_terminator)
1434         gfc_conv_expr (&se, e);
1435       else
1436         gfc_conv_expr_descriptor (&se, e, ss);
1437
1438       /* Fix the value.  */
1439       *len = gfc_evaluate_now (se.string_length, &se.pre);
1440
1441       gfc_add_block_to_block (block, &se.pre);
1442       gfc_add_block_to_block (block, &se.post);
1443
1444       e->ts.cl->backend_decl = *len;
1445     }
1446 }
1447
1448
1449 /* Figure out the string length of a character array constructor.
1450    Returns TRUE if all elements are character constants.  */
1451
1452 bool
1453 get_array_ctor_strlen (stmtblock_t *block, gfc_constructor * c, tree * len)
1454 {
1455   bool is_const;
1456   
1457   is_const = TRUE;
1458
1459   if (c == NULL)
1460     {
1461       *len = build_int_cstu (gfc_charlen_type_node, 0);
1462       return is_const;
1463     }
1464
1465   for (; c; c = c->next)
1466     {
1467       switch (c->expr->expr_type)
1468         {
1469         case EXPR_CONSTANT:
1470           if (!(*len && INTEGER_CST_P (*len)))
1471             *len = build_int_cstu (gfc_charlen_type_node,
1472                                    c->expr->value.character.length);
1473           break;
1474
1475         case EXPR_ARRAY:
1476           if (!get_array_ctor_strlen (block, c->expr->value.constructor, len))
1477             is_const = false;
1478           break;
1479
1480         case EXPR_VARIABLE:
1481           is_const = false;
1482           get_array_ctor_var_strlen (c->expr, len);
1483           break;
1484
1485         default:
1486           is_const = false;
1487           get_array_ctor_all_strlen (block, c->expr, len);
1488           break;
1489         }
1490     }
1491
1492   return is_const;
1493 }
1494
1495 /* Check whether the array constructor C consists entirely of constant
1496    elements, and if so returns the number of those elements, otherwise
1497    return zero.  Note, an empty or NULL array constructor returns zero.  */
1498
1499 unsigned HOST_WIDE_INT
1500 gfc_constant_array_constructor_p (gfc_constructor * c)
1501 {
1502   unsigned HOST_WIDE_INT nelem = 0;
1503
1504   while (c)
1505     {
1506       if (c->iterator
1507           || c->expr->rank > 0
1508           || c->expr->expr_type != EXPR_CONSTANT)
1509         return 0;
1510       c = c->next;
1511       nelem++;
1512     }
1513   return nelem;
1514 }
1515
1516
1517 /* Given EXPR, the constant array constructor specified by an EXPR_ARRAY,
1518    and the tree type of it's elements, TYPE, return a static constant
1519    variable that is compile-time initialized.  */
1520
1521 tree
1522 gfc_build_constant_array_constructor (gfc_expr * expr, tree type)
1523 {
1524   tree tmptype, list, init, tmp;
1525   HOST_WIDE_INT nelem;
1526   gfc_constructor *c;
1527   gfc_array_spec as;
1528   gfc_se se;
1529   int i;
1530
1531   /* First traverse the constructor list, converting the constants
1532      to tree to build an initializer.  */
1533   nelem = 0;
1534   list = NULL_TREE;
1535   c = expr->value.constructor;
1536   while (c)
1537     {
1538       gfc_init_se (&se, NULL);
1539       gfc_conv_constant (&se, c->expr);
1540       if (c->expr->ts.type == BT_CHARACTER
1541           && POINTER_TYPE_P (type))
1542         se.expr = gfc_build_addr_expr (pchar_type_node, se.expr);
1543       list = tree_cons (NULL_TREE, se.expr, list);
1544       c = c->next;
1545       nelem++;
1546     }
1547
1548   /* Next determine the tree type for the array.  We use the gfortran
1549      front-end's gfc_get_nodesc_array_type in order to create a suitable
1550      GFC_ARRAY_TYPE_P that may be used by the scalarizer.  */
1551
1552   memset (&as, 0, sizeof (gfc_array_spec));
1553
1554   as.rank = expr->rank;
1555   as.type = AS_EXPLICIT;
1556   if (!expr->shape)
1557     {
1558       as.lower[0] = gfc_int_expr (0);
1559       as.upper[0] = gfc_int_expr (nelem - 1);
1560     }
1561   else
1562     for (i = 0; i < expr->rank; i++)
1563       {
1564         int tmp = (int) mpz_get_si (expr->shape[i]);
1565         as.lower[i] = gfc_int_expr (0);
1566         as.upper[i] = gfc_int_expr (tmp - 1);
1567       }
1568
1569   tmptype = gfc_get_nodesc_array_type (type, &as, PACKED_STATIC);
1570
1571   init = build_constructor_from_list (tmptype, nreverse (list));
1572
1573   TREE_CONSTANT (init) = 1;
1574   TREE_INVARIANT (init) = 1;
1575   TREE_STATIC (init) = 1;
1576
1577   tmp = gfc_create_var (tmptype, "A");
1578   TREE_STATIC (tmp) = 1;
1579   TREE_CONSTANT (tmp) = 1;
1580   TREE_INVARIANT (tmp) = 1;
1581   TREE_READONLY (tmp) = 1;
1582   DECL_INITIAL (tmp) = init;
1583
1584   return tmp;
1585 }
1586
1587
1588 /* Translate a constant EXPR_ARRAY array constructor for the scalarizer.
1589    This mostly initializes the scalarizer state info structure with the
1590    appropriate values to directly use the array created by the function
1591    gfc_build_constant_array_constructor.  */
1592
1593 static void
1594 gfc_trans_constant_array_constructor (gfc_loopinfo * loop,
1595                                       gfc_ss * ss, tree type)
1596 {
1597   gfc_ss_info *info;
1598   tree tmp;
1599   int i;
1600
1601   tmp = gfc_build_constant_array_constructor (ss->expr, type);
1602
1603   info = &ss->data.info;
1604
1605   info->descriptor = tmp;
1606   info->data = build_fold_addr_expr (tmp);
1607   info->offset = fold_build1 (NEGATE_EXPR, gfc_array_index_type,
1608                               loop->from[0]);
1609
1610   for (i = 0; i < info->dimen; i++)
1611     {
1612       info->delta[i] = gfc_index_zero_node;
1613       info->start[i] = gfc_index_zero_node;
1614       info->end[i] = gfc_index_zero_node;
1615       info->stride[i] = gfc_index_one_node;
1616       info->dim[i] = i;
1617     }
1618
1619   if (info->dimen > loop->temp_dim)
1620     loop->temp_dim = info->dimen;
1621 }
1622
1623 /* Helper routine of gfc_trans_array_constructor to determine if the
1624    bounds of the loop specified by LOOP are constant and simple enough
1625    to use with gfc_trans_constant_array_constructor.  Returns the
1626    the iteration count of the loop if suitable, and NULL_TREE otherwise.  */
1627
1628 static tree
1629 constant_array_constructor_loop_size (gfc_loopinfo * loop)
1630 {
1631   tree size = gfc_index_one_node;
1632   tree tmp;
1633   int i;
1634
1635   for (i = 0; i < loop->dimen; i++)
1636     {
1637       /* If the bounds aren't constant, return NULL_TREE.  */
1638       if (!INTEGER_CST_P (loop->from[i]) || !INTEGER_CST_P (loop->to[i]))
1639         return NULL_TREE;
1640       if (!integer_zerop (loop->from[i]))
1641         {
1642           /* Only allow nonzero "from" in one-dimensional arrays.  */
1643           if (loop->dimen != 1)
1644             return NULL_TREE;
1645           tmp = fold_build2 (MINUS_EXPR, gfc_array_index_type,
1646                              loop->to[i], loop->from[i]);
1647         }
1648       else
1649         tmp = loop->to[i];
1650       tmp = fold_build2 (PLUS_EXPR, gfc_array_index_type,
1651                          tmp, gfc_index_one_node);
1652       size = fold_build2 (MULT_EXPR, gfc_array_index_type, size, tmp);
1653     }
1654
1655   return size;
1656 }
1657
1658
1659 /* Array constructors are handled by constructing a temporary, then using that
1660    within the scalarization loop.  This is not optimal, but seems by far the
1661    simplest method.  */
1662
1663 static void
1664 gfc_trans_array_constructor (gfc_loopinfo * loop, gfc_ss * ss)
1665 {
1666   gfc_constructor *c;
1667   tree offset;
1668   tree offsetvar;
1669   tree desc;
1670   tree type;
1671   bool dynamic;
1672
1673   if (flag_bounds_check && ss->expr->ts.type == BT_CHARACTER)
1674     {  
1675       first_len_val = gfc_create_var (gfc_charlen_type_node, "len");
1676       first_len = true;
1677     }
1678
1679   ss->data.info.dimen = loop->dimen;
1680
1681   c = ss->expr->value.constructor;
1682   if (ss->expr->ts.type == BT_CHARACTER)
1683     {
1684       bool const_string = get_array_ctor_strlen (&loop->pre, c, &ss->string_length);
1685
1686       /* Complex character array constructors should have been taken care of
1687          and not end up here.  */
1688       gcc_assert (ss->string_length);
1689
1690       ss->expr->ts.cl->backend_decl = ss->string_length;
1691
1692       type = gfc_get_character_type_len (ss->expr->ts.kind, ss->string_length);
1693       if (const_string)
1694         type = build_pointer_type (type);
1695     }
1696   else
1697     type = gfc_typenode_for_spec (&ss->expr->ts);
1698
1699   /* See if the constructor determines the loop bounds.  */
1700   dynamic = false;
1701
1702   if (ss->expr->shape && loop->dimen > 1 && loop->to[0] == NULL_TREE)
1703     {
1704       /* We have a multidimensional parameter.  */
1705       int n;
1706       for (n = 0; n < ss->expr->rank; n++)
1707       {
1708         loop->from[n] = gfc_index_zero_node;
1709         loop->to[n] = gfc_conv_mpz_to_tree (ss->expr->shape [n],
1710                                             gfc_index_integer_kind);
1711         loop->to[n] = fold_build2 (MINUS_EXPR, gfc_array_index_type,
1712                                    loop->to[n], gfc_index_one_node);
1713       }
1714     }
1715
1716   if (loop->to[0] == NULL_TREE)
1717     {
1718       mpz_t size;
1719
1720       /* We should have a 1-dimensional, zero-based loop.  */
1721       gcc_assert (loop->dimen == 1);
1722       gcc_assert (integer_zerop (loop->from[0]));
1723
1724       /* Split the constructor size into a static part and a dynamic part.
1725          Allocate the static size up-front and record whether the dynamic
1726          size might be nonzero.  */
1727       mpz_init (size);
1728       dynamic = gfc_get_array_constructor_size (&size, c);
1729       mpz_sub_ui (size, size, 1);
1730       loop->to[0] = gfc_conv_mpz_to_tree (size, gfc_index_integer_kind);
1731       mpz_clear (size);
1732     }
1733
1734   /* Special case constant array constructors.  */
1735   if (!dynamic)
1736     {
1737       unsigned HOST_WIDE_INT nelem = gfc_constant_array_constructor_p (c);
1738       if (nelem > 0)
1739         {
1740           tree size = constant_array_constructor_loop_size (loop);
1741           if (size && compare_tree_int (size, nelem) == 0)
1742             {
1743               gfc_trans_constant_array_constructor (loop, ss, type);
1744               return;
1745             }
1746         }
1747     }
1748
1749   gfc_trans_create_temp_array (&loop->pre, &loop->post, loop, &ss->data.info,
1750                                type, dynamic, true, false);
1751
1752   desc = ss->data.info.descriptor;
1753   offset = gfc_index_zero_node;
1754   offsetvar = gfc_create_var_np (gfc_array_index_type, "offset");
1755   TREE_NO_WARNING (offsetvar) = 1;
1756   TREE_USED (offsetvar) = 0;
1757   gfc_trans_array_constructor_value (&loop->pre, type, desc, c,
1758                                      &offset, &offsetvar, dynamic);
1759
1760   /* If the array grows dynamically, the upper bound of the loop variable
1761      is determined by the array's final upper bound.  */
1762   if (dynamic)
1763     loop->to[0] = gfc_conv_descriptor_ubound (desc, gfc_rank_cst[0]);
1764
1765   if (TREE_USED (offsetvar))
1766     pushdecl (offsetvar);
1767   else
1768     gcc_assert (INTEGER_CST_P (offset));
1769 #if 0
1770   /* Disable bound checking for now because it's probably broken.  */
1771   if (flag_bounds_check)
1772     {
1773       gcc_unreachable ();
1774     }
1775 #endif
1776 }
1777
1778
1779 /* INFO describes a GFC_SS_SECTION in loop LOOP, and this function is
1780    called after evaluating all of INFO's vector dimensions.  Go through
1781    each such vector dimension and see if we can now fill in any missing
1782    loop bounds.  */
1783
1784 static void
1785 gfc_set_vector_loop_bounds (gfc_loopinfo * loop, gfc_ss_info * info)
1786 {
1787   gfc_se se;
1788   tree tmp;
1789   tree desc;
1790   tree zero;
1791   int n;
1792   int dim;
1793
1794   for (n = 0; n < loop->dimen; n++)
1795     {
1796       dim = info->dim[n];
1797       if (info->ref->u.ar.dimen_type[dim] == DIMEN_VECTOR
1798           && loop->to[n] == NULL)
1799         {
1800           /* Loop variable N indexes vector dimension DIM, and we don't
1801              yet know the upper bound of loop variable N.  Set it to the
1802              difference between the vector's upper and lower bounds.  */
1803           gcc_assert (loop->from[n] == gfc_index_zero_node);
1804           gcc_assert (info->subscript[dim]
1805                       && info->subscript[dim]->type == GFC_SS_VECTOR);
1806
1807           gfc_init_se (&se, NULL);
1808           desc = info->subscript[dim]->data.info.descriptor;
1809           zero = gfc_rank_cst[0];
1810           tmp = fold_build2 (MINUS_EXPR, gfc_array_index_type,
1811                              gfc_conv_descriptor_ubound (desc, zero),
1812                              gfc_conv_descriptor_lbound (desc, zero));
1813           tmp = gfc_evaluate_now (tmp, &loop->pre);
1814           loop->to[n] = tmp;
1815         }
1816     }
1817 }
1818
1819
1820 /* Add the pre and post chains for all the scalar expressions in a SS chain
1821    to loop.  This is called after the loop parameters have been calculated,
1822    but before the actual scalarizing loops.  */
1823
1824 static void
1825 gfc_add_loop_ss_code (gfc_loopinfo * loop, gfc_ss * ss, bool subscript)
1826 {
1827   gfc_se se;
1828   int n;
1829
1830   /* TODO: This can generate bad code if there are ordering dependencies.
1831      eg. a callee allocated function and an unknown size constructor.  */
1832   gcc_assert (ss != NULL);
1833
1834   for (; ss != gfc_ss_terminator; ss = ss->loop_chain)
1835     {
1836       gcc_assert (ss);
1837
1838       switch (ss->type)
1839         {
1840         case GFC_SS_SCALAR:
1841           /* Scalar expression.  Evaluate this now.  This includes elemental
1842              dimension indices, but not array section bounds.  */
1843           gfc_init_se (&se, NULL);
1844           gfc_conv_expr (&se, ss->expr);
1845           gfc_add_block_to_block (&loop->pre, &se.pre);
1846
1847           if (ss->expr->ts.type != BT_CHARACTER)
1848             {
1849               /* Move the evaluation of scalar expressions outside the
1850                  scalarization loop.  */
1851               if (subscript)
1852                 se.expr = convert(gfc_array_index_type, se.expr);
1853               se.expr = gfc_evaluate_now (se.expr, &loop->pre);
1854               gfc_add_block_to_block (&loop->pre, &se.post);
1855             }
1856           else
1857             gfc_add_block_to_block (&loop->post, &se.post);
1858
1859           ss->data.scalar.expr = se.expr;
1860           ss->string_length = se.string_length;
1861           break;
1862
1863         case GFC_SS_REFERENCE:
1864           /* Scalar reference.  Evaluate this now.  */
1865           gfc_init_se (&se, NULL);
1866           gfc_conv_expr_reference (&se, ss->expr);
1867           gfc_add_block_to_block (&loop->pre, &se.pre);
1868           gfc_add_block_to_block (&loop->post, &se.post);
1869
1870           ss->data.scalar.expr = gfc_evaluate_now (se.expr, &loop->pre);
1871           ss->string_length = se.string_length;
1872           break;
1873
1874         case GFC_SS_SECTION:
1875           /* Add the expressions for scalar and vector subscripts.  */
1876           for (n = 0; n < GFC_MAX_DIMENSIONS; n++)
1877             if (ss->data.info.subscript[n])
1878               gfc_add_loop_ss_code (loop, ss->data.info.subscript[n], true);
1879
1880           gfc_set_vector_loop_bounds (loop, &ss->data.info);
1881           break;
1882
1883         case GFC_SS_VECTOR:
1884           /* Get the vector's descriptor and store it in SS.  */
1885           gfc_init_se (&se, NULL);
1886           gfc_conv_expr_descriptor (&se, ss->expr, gfc_walk_expr (ss->expr));
1887           gfc_add_block_to_block (&loop->pre, &se.pre);
1888           gfc_add_block_to_block (&loop->post, &se.post);
1889           ss->data.info.descriptor = se.expr;
1890           break;
1891
1892         case GFC_SS_INTRINSIC:
1893           gfc_add_intrinsic_ss_code (loop, ss);
1894           break;
1895
1896         case GFC_SS_FUNCTION:
1897           /* Array function return value.  We call the function and save its
1898              result in a temporary for use inside the loop.  */
1899           gfc_init_se (&se, NULL);
1900           se.loop = loop;
1901           se.ss = ss;
1902           gfc_conv_expr (&se, ss->expr);
1903           gfc_add_block_to_block (&loop->pre, &se.pre);
1904           gfc_add_block_to_block (&loop->post, &se.post);
1905           ss->string_length = se.string_length;
1906           break;
1907
1908         case GFC_SS_CONSTRUCTOR:
1909           if (ss->expr->ts.type == BT_CHARACTER
1910                 && ss->string_length== NULL
1911                 && ss->expr->ts.cl
1912                 && ss->expr->ts.cl->length)
1913             {
1914               gfc_init_se (&se, NULL);
1915               gfc_conv_expr_type (&se, ss->expr->ts.cl->length,
1916                                   gfc_charlen_type_node);
1917               ss->string_length = se.expr;
1918               gfc_add_block_to_block (&loop->pre, &se.pre);
1919               gfc_add_block_to_block (&loop->post, &se.post);
1920             }
1921           gfc_trans_array_constructor (loop, ss);
1922           break;
1923
1924         case GFC_SS_TEMP:
1925         case GFC_SS_COMPONENT:
1926           /* Do nothing.  These are handled elsewhere.  */
1927           break;
1928
1929         default:
1930           gcc_unreachable ();
1931         }
1932     }
1933 }
1934
1935
1936 /* Translate expressions for the descriptor and data pointer of a SS.  */
1937 /*GCC ARRAYS*/
1938
1939 static void
1940 gfc_conv_ss_descriptor (stmtblock_t * block, gfc_ss * ss, int base)
1941 {
1942   gfc_se se;
1943   tree tmp;
1944
1945   /* Get the descriptor for the array to be scalarized.  */
1946   gcc_assert (ss->expr->expr_type == EXPR_VARIABLE);
1947   gfc_init_se (&se, NULL);
1948   se.descriptor_only = 1;
1949   gfc_conv_expr_lhs (&se, ss->expr);
1950   gfc_add_block_to_block (block, &se.pre);
1951   ss->data.info.descriptor = se.expr;
1952   ss->string_length = se.string_length;
1953
1954   if (base)
1955     {
1956       /* Also the data pointer.  */
1957       tmp = gfc_conv_array_data (se.expr);
1958       /* If this is a variable or address of a variable we use it directly.
1959          Otherwise we must evaluate it now to avoid breaking dependency
1960          analysis by pulling the expressions for elemental array indices
1961          inside the loop.  */
1962       if (!(DECL_P (tmp)
1963             || (TREE_CODE (tmp) == ADDR_EXPR
1964                 && DECL_P (TREE_OPERAND (tmp, 0)))))
1965         tmp = gfc_evaluate_now (tmp, block);
1966       ss->data.info.data = tmp;
1967
1968       tmp = gfc_conv_array_offset (se.expr);
1969       ss->data.info.offset = gfc_evaluate_now (tmp, block);
1970     }
1971 }
1972
1973
1974 /* Initialize a gfc_loopinfo structure.  */
1975
1976 void
1977 gfc_init_loopinfo (gfc_loopinfo * loop)
1978 {
1979   int n;
1980
1981   memset (loop, 0, sizeof (gfc_loopinfo));
1982   gfc_init_block (&loop->pre);
1983   gfc_init_block (&loop->post);
1984
1985   /* Initially scalarize in order.  */
1986   for (n = 0; n < GFC_MAX_DIMENSIONS; n++)
1987     loop->order[n] = n;
1988
1989   loop->ss = gfc_ss_terminator;
1990 }
1991
1992
1993 /* Copies the loop variable info to a gfc_se structure. Does not copy the SS
1994    chain.  */
1995
1996 void
1997 gfc_copy_loopinfo_to_se (gfc_se * se, gfc_loopinfo * loop)
1998 {
1999   se->loop = loop;
2000 }
2001
2002
2003 /* Return an expression for the data pointer of an array.  */
2004
2005 tree
2006 gfc_conv_array_data (tree descriptor)
2007 {
2008   tree type;
2009
2010   type = TREE_TYPE (descriptor);
2011   if (GFC_ARRAY_TYPE_P (type))
2012     {
2013       if (TREE_CODE (type) == POINTER_TYPE)
2014         return descriptor;
2015       else
2016         {
2017           /* Descriptorless arrays.  */
2018           return build_fold_addr_expr (descriptor);
2019         }
2020     }
2021   else
2022     return gfc_conv_descriptor_data_get (descriptor);
2023 }
2024
2025
2026 /* Return an expression for the base offset of an array.  */
2027
2028 tree
2029 gfc_conv_array_offset (tree descriptor)
2030 {
2031   tree type;
2032
2033   type = TREE_TYPE (descriptor);
2034   if (GFC_ARRAY_TYPE_P (type))
2035     return GFC_TYPE_ARRAY_OFFSET (type);
2036   else
2037     return gfc_conv_descriptor_offset (descriptor);
2038 }
2039
2040
2041 /* Get an expression for the array stride.  */
2042
2043 tree
2044 gfc_conv_array_stride (tree descriptor, int dim)
2045 {
2046   tree tmp;
2047   tree type;
2048
2049   type = TREE_TYPE (descriptor);
2050
2051   /* For descriptorless arrays use the array size.  */
2052   tmp = GFC_TYPE_ARRAY_STRIDE (type, dim);
2053   if (tmp != NULL_TREE)
2054     return tmp;
2055
2056   tmp = gfc_conv_descriptor_stride (descriptor, gfc_rank_cst[dim]);
2057   return tmp;
2058 }
2059
2060
2061 /* Like gfc_conv_array_stride, but for the lower bound.  */
2062
2063 tree
2064 gfc_conv_array_lbound (tree descriptor, int dim)
2065 {
2066   tree tmp;
2067   tree type;
2068
2069   type = TREE_TYPE (descriptor);
2070
2071   tmp = GFC_TYPE_ARRAY_LBOUND (type, dim);
2072   if (tmp != NULL_TREE)
2073     return tmp;
2074
2075   tmp = gfc_conv_descriptor_lbound (descriptor, gfc_rank_cst[dim]);
2076   return tmp;
2077 }
2078
2079
2080 /* Like gfc_conv_array_stride, but for the upper bound.  */
2081
2082 tree
2083 gfc_conv_array_ubound (tree descriptor, int dim)
2084 {
2085   tree tmp;
2086   tree type;
2087
2088   type = TREE_TYPE (descriptor);
2089
2090   tmp = GFC_TYPE_ARRAY_UBOUND (type, dim);
2091   if (tmp != NULL_TREE)
2092     return tmp;
2093
2094   /* This should only ever happen when passing an assumed shape array
2095      as an actual parameter.  The value will never be used.  */
2096   if (GFC_ARRAY_TYPE_P (TREE_TYPE (descriptor)))
2097     return gfc_index_zero_node;
2098
2099   tmp = gfc_conv_descriptor_ubound (descriptor, gfc_rank_cst[dim]);
2100   return tmp;
2101 }
2102
2103
2104 /* Generate code to perform an array index bound check.  */
2105
2106 static tree
2107 gfc_trans_array_bound_check (gfc_se * se, tree descriptor, tree index, int n,
2108                              locus * where, bool check_upper)
2109 {
2110   tree fault;
2111   tree tmp;
2112   char *msg;
2113   const char * name = NULL;
2114
2115   if (!flag_bounds_check)
2116     return index;
2117
2118   index = gfc_evaluate_now (index, &se->pre);
2119
2120   /* We find a name for the error message.  */
2121   if (se->ss)
2122     name = se->ss->expr->symtree->name;
2123
2124   if (!name && se->loop && se->loop->ss && se->loop->ss->expr
2125       && se->loop->ss->expr->symtree)
2126     name = se->loop->ss->expr->symtree->name;
2127
2128   if (!name && se->loop && se->loop->ss && se->loop->ss->loop_chain
2129       && se->loop->ss->loop_chain->expr
2130       && se->loop->ss->loop_chain->expr->symtree)
2131     name = se->loop->ss->loop_chain->expr->symtree->name;
2132
2133   if (!name && se->loop && se->loop->ss && se->loop->ss->loop_chain
2134       && se->loop->ss->loop_chain->expr->symtree)
2135     name = se->loop->ss->loop_chain->expr->symtree->name;
2136
2137   if (!name && se->loop && se->loop->ss && se->loop->ss->expr)
2138     {
2139       if (se->loop->ss->expr->expr_type == EXPR_FUNCTION
2140           && se->loop->ss->expr->value.function.name)
2141         name = se->loop->ss->expr->value.function.name;
2142       else
2143         if (se->loop->ss->type == GFC_SS_CONSTRUCTOR
2144             || se->loop->ss->type == GFC_SS_SCALAR)
2145           name = "unnamed constant";
2146     }
2147
2148   /* Check lower bound.  */
2149   tmp = gfc_conv_array_lbound (descriptor, n);
2150   fault = fold_build2 (LT_EXPR, boolean_type_node, index, tmp);
2151   if (name)
2152     asprintf (&msg, "%s for array '%s', lower bound of dimension %d exceeded"
2153               "(%%ld < %%ld)", gfc_msg_fault, name, n+1);
2154   else
2155     asprintf (&msg, "%s, lower bound of dimension %d exceeded (%%ld < %%ld)",
2156               gfc_msg_fault, n+1);
2157   gfc_trans_runtime_check (fault, &se->pre, where, msg,
2158                            fold_convert (long_integer_type_node, index),
2159                            fold_convert (long_integer_type_node, tmp));
2160   gfc_free (msg);
2161
2162   /* Check upper bound.  */
2163   if (check_upper)
2164     {
2165       tmp = gfc_conv_array_ubound (descriptor, n);
2166       fault = fold_build2 (GT_EXPR, boolean_type_node, index, tmp);
2167       if (name)
2168         asprintf (&msg, "%s for array '%s', upper bound of dimension %d "
2169                         " exceeded (%%ld > %%ld)", gfc_msg_fault, name, n+1);
2170       else
2171         asprintf (&msg, "%s, upper bound of dimension %d exceeded (%%ld > %%ld)",
2172                   gfc_msg_fault, n+1);
2173       gfc_trans_runtime_check (fault, &se->pre, where, msg,
2174                                fold_convert (long_integer_type_node, index),
2175                                fold_convert (long_integer_type_node, tmp));
2176       gfc_free (msg);
2177     }
2178
2179   return index;
2180 }
2181
2182
2183 /* Return the offset for an index.  Performs bound checking for elemental
2184    dimensions.  Single element references are processed separately.  */
2185
2186 static tree
2187 gfc_conv_array_index_offset (gfc_se * se, gfc_ss_info * info, int dim, int i,
2188                              gfc_array_ref * ar, tree stride)
2189 {
2190   tree index;
2191   tree desc;
2192   tree data;
2193
2194   /* Get the index into the array for this dimension.  */
2195   if (ar)
2196     {
2197       gcc_assert (ar->type != AR_ELEMENT);
2198       switch (ar->dimen_type[dim])
2199         {
2200         case DIMEN_ELEMENT:
2201           gcc_assert (i == -1);
2202           /* Elemental dimension.  */
2203           gcc_assert (info->subscript[dim]
2204                       && info->subscript[dim]->type == GFC_SS_SCALAR);
2205           /* We've already translated this value outside the loop.  */
2206           index = info->subscript[dim]->data.scalar.expr;
2207
2208           index = gfc_trans_array_bound_check (se, info->descriptor,
2209                         index, dim, &ar->where,
2210                         (ar->as->type != AS_ASSUMED_SIZE
2211                          && !ar->as->cp_was_assumed) || dim < ar->dimen - 1);
2212           break;
2213
2214         case DIMEN_VECTOR:
2215           gcc_assert (info && se->loop);
2216           gcc_assert (info->subscript[dim]
2217                       && info->subscript[dim]->type == GFC_SS_VECTOR);
2218           desc = info->subscript[dim]->data.info.descriptor;
2219
2220           /* Get a zero-based index into the vector.  */
2221           index = fold_build2 (MINUS_EXPR, gfc_array_index_type,
2222                                se->loop->loopvar[i], se->loop->from[i]);
2223
2224           /* Multiply the index by the stride.  */
2225           index = fold_build2 (MULT_EXPR, gfc_array_index_type,
2226                                index, gfc_conv_array_stride (desc, 0));
2227
2228           /* Read the vector to get an index into info->descriptor.  */
2229           data = build_fold_indirect_ref (gfc_conv_array_data (desc));
2230           index = gfc_build_array_ref (data, index, NULL);
2231           index = gfc_evaluate_now (index, &se->pre);
2232
2233           /* Do any bounds checking on the final info->descriptor index.  */
2234           index = gfc_trans_array_bound_check (se, info->descriptor,
2235                         index, dim, &ar->where,
2236                         (ar->as->type != AS_ASSUMED_SIZE
2237                          && !ar->as->cp_was_assumed) || dim < ar->dimen - 1);
2238           break;
2239
2240         case DIMEN_RANGE:
2241           /* Scalarized dimension.  */
2242           gcc_assert (info && se->loop);
2243
2244           /* Multiply the loop variable by the stride and delta.  */
2245           index = se->loop->loopvar[i];
2246           if (!integer_onep (info->stride[i]))
2247             index = fold_build2 (MULT_EXPR, gfc_array_index_type, index,
2248                                  info->stride[i]);
2249           if (!integer_zerop (info->delta[i]))
2250             index = fold_build2 (PLUS_EXPR, gfc_array_index_type, index,
2251                                  info->delta[i]);
2252           break;
2253
2254         default:
2255           gcc_unreachable ();
2256         }
2257     }
2258   else
2259     {
2260       /* Temporary array or derived type component.  */
2261       gcc_assert (se->loop);
2262       index = se->loop->loopvar[se->loop->order[i]];
2263       if (!integer_zerop (info->delta[i]))
2264         index = fold_build2 (PLUS_EXPR, gfc_array_index_type,
2265                              index, info->delta[i]);
2266     }
2267
2268   /* Multiply by the stride.  */
2269   if (!integer_onep (stride))
2270     index = fold_build2 (MULT_EXPR, gfc_array_index_type, index, stride);
2271
2272   return index;
2273 }
2274
2275
2276 /* Build a scalarized reference to an array.  */
2277
2278 static void
2279 gfc_conv_scalarized_array_ref (gfc_se * se, gfc_array_ref * ar)
2280 {
2281   gfc_ss_info *info;
2282   tree decl = NULL_TREE;
2283   tree index;
2284   tree tmp;
2285   int n;
2286
2287   info = &se->ss->data.info;
2288   if (ar)
2289     n = se->loop->order[0];
2290   else
2291     n = 0;
2292
2293   index = gfc_conv_array_index_offset (se, info, info->dim[n], n, ar,
2294                                        info->stride0);
2295   /* Add the offset for this dimension to the stored offset for all other
2296      dimensions.  */
2297   if (!integer_zerop (info->offset))
2298     index = fold_build2 (PLUS_EXPR, gfc_array_index_type, index, info->offset);
2299
2300   if (se->ss->expr && is_subref_array (se->ss->expr))
2301     decl = se->ss->expr->symtree->n.sym->backend_decl;
2302
2303   tmp = build_fold_indirect_ref (info->data);
2304   se->expr = gfc_build_array_ref (tmp, index, decl);
2305 }
2306
2307
2308 /* Translate access of temporary array.  */
2309
2310 void
2311 gfc_conv_tmp_array_ref (gfc_se * se)
2312 {
2313   se->string_length = se->ss->string_length;
2314   gfc_conv_scalarized_array_ref (se, NULL);
2315 }
2316
2317
2318 /* Build an array reference.  se->expr already holds the array descriptor.
2319    This should be either a variable, indirect variable reference or component
2320    reference.  For arrays which do not have a descriptor, se->expr will be
2321    the data pointer.
2322    a(i, j, k) = base[offset + i * stride[0] + j * stride[1] + k * stride[2]]*/
2323
2324 void
2325 gfc_conv_array_ref (gfc_se * se, gfc_array_ref * ar, gfc_symbol * sym,
2326                     locus * where)
2327 {
2328   int n;
2329   tree index;
2330   tree tmp;
2331   tree stride;
2332   gfc_se indexse;
2333
2334   /* Handle scalarized references separately.  */
2335   if (ar->type != AR_ELEMENT)
2336     {
2337       gfc_conv_scalarized_array_ref (se, ar);
2338       gfc_advance_se_ss_chain (se);
2339       return;
2340     }
2341
2342   index = gfc_index_zero_node;
2343
2344   /* Calculate the offsets from all the dimensions.  */
2345   for (n = 0; n < ar->dimen; n++)
2346     {
2347       /* Calculate the index for this dimension.  */
2348       gfc_init_se (&indexse, se);
2349       gfc_conv_expr_type (&indexse, ar->start[n], gfc_array_index_type);
2350       gfc_add_block_to_block (&se->pre, &indexse.pre);
2351
2352       if (flag_bounds_check)
2353         {
2354           /* Check array bounds.  */
2355           tree cond;
2356           char *msg;
2357
2358           /* Evaluate the indexse.expr only once.  */
2359           indexse.expr = save_expr (indexse.expr);
2360
2361           /* Lower bound.  */
2362           tmp = gfc_conv_array_lbound (se->expr, n);
2363           cond = fold_build2 (LT_EXPR, boolean_type_node, 
2364                               indexse.expr, tmp);
2365           asprintf (&msg, "%s for array '%s', "
2366                     "lower bound of dimension %d exceeded (%%ld < %%ld)",
2367                     gfc_msg_fault, sym->name, n+1);
2368           gfc_trans_runtime_check (cond, &se->pre, where, msg,
2369                                    fold_convert (long_integer_type_node,
2370                                                  indexse.expr),
2371                                    fold_convert (long_integer_type_node, tmp));
2372           gfc_free (msg);
2373
2374           /* Upper bound, but not for the last dimension of assumed-size
2375              arrays.  */
2376           if (n < ar->dimen - 1
2377               || (ar->as->type != AS_ASSUMED_SIZE && !ar->as->cp_was_assumed))
2378             {
2379               tmp = gfc_conv_array_ubound (se->expr, n);
2380               cond = fold_build2 (GT_EXPR, boolean_type_node, 
2381                                   indexse.expr, tmp);
2382               asprintf (&msg, "%s for array '%s', "
2383                         "upper bound of dimension %d exceeded (%%ld > %%ld)",
2384                         gfc_msg_fault, sym->name, n+1);
2385               gfc_trans_runtime_check (cond, &se->pre, where, msg,
2386                                    fold_convert (long_integer_type_node,
2387                                                  indexse.expr),
2388                                    fold_convert (long_integer_type_node, tmp));
2389               gfc_free (msg);
2390             }
2391         }
2392
2393       /* Multiply the index by the stride.  */
2394       stride = gfc_conv_array_stride (se->expr, n);
2395       tmp = fold_build2 (MULT_EXPR, gfc_array_index_type, indexse.expr,
2396                          stride);
2397
2398       /* And add it to the total.  */
2399       index = fold_build2 (PLUS_EXPR, gfc_array_index_type, index, tmp);
2400     }
2401
2402   tmp = gfc_conv_array_offset (se->expr);
2403   if (!integer_zerop (tmp))
2404     index = fold_build2 (PLUS_EXPR, gfc_array_index_type, index, tmp);
2405
2406   /* Access the calculated element.  */
2407   tmp = gfc_conv_array_data (se->expr);
2408   tmp = build_fold_indirect_ref (tmp);
2409   se->expr = gfc_build_array_ref (tmp, index, sym->backend_decl);
2410 }
2411
2412
2413 /* Generate the code to be executed immediately before entering a
2414    scalarization loop.  */
2415
2416 static void
2417 gfc_trans_preloop_setup (gfc_loopinfo * loop, int dim, int flag,
2418                          stmtblock_t * pblock)
2419 {
2420   tree index;
2421   tree stride;
2422   gfc_ss_info *info;
2423   gfc_ss *ss;
2424   gfc_se se;
2425   int i;
2426
2427   /* This code will be executed before entering the scalarization loop
2428      for this dimension.  */
2429   for (ss = loop->ss; ss != gfc_ss_terminator; ss = ss->loop_chain)
2430     {
2431       if ((ss->useflags & flag) == 0)
2432         continue;
2433
2434       if (ss->type != GFC_SS_SECTION
2435           && ss->type != GFC_SS_FUNCTION && ss->type != GFC_SS_CONSTRUCTOR
2436           && ss->type != GFC_SS_COMPONENT)
2437         continue;
2438
2439       info = &ss->data.info;
2440
2441       if (dim >= info->dimen)
2442         continue;
2443
2444       if (dim == info->dimen - 1)
2445         {
2446           /* For the outermost loop calculate the offset due to any
2447              elemental dimensions.  It will have been initialized with the
2448              base offset of the array.  */
2449           if (info->ref)
2450             {
2451               for (i = 0; i < info->ref->u.ar.dimen; i++)
2452                 {
2453                   if (info->ref->u.ar.dimen_type[i] != DIMEN_ELEMENT)
2454                     continue;
2455
2456                   gfc_init_se (&se, NULL);
2457                   se.loop = loop;
2458                   se.expr = info->descriptor;
2459                   stride = gfc_conv_array_stride (info->descriptor, i);
2460                   index = gfc_conv_array_index_offset (&se, info, i, -1,
2461                                                        &info->ref->u.ar,
2462                                                        stride);
2463                   gfc_add_block_to_block (pblock, &se.pre);
2464
2465                   info->offset = fold_build2 (PLUS_EXPR, gfc_array_index_type,
2466                                               info->offset, index);
2467                   info->offset = gfc_evaluate_now (info->offset, pblock);
2468                 }
2469
2470               i = loop->order[0];
2471               stride = gfc_conv_array_stride (info->descriptor, info->dim[i]);
2472             }
2473           else
2474             stride = gfc_conv_array_stride (info->descriptor, 0);
2475
2476           /* Calculate the stride of the innermost loop.  Hopefully this will
2477              allow the backend optimizers to do their stuff more effectively.
2478            */
2479           info->stride0 = gfc_evaluate_now (stride, pblock);
2480         }
2481       else
2482         {
2483           /* Add the offset for the previous loop dimension.  */
2484           gfc_array_ref *ar;
2485
2486           if (info->ref)
2487             {
2488               ar = &info->ref->u.ar;
2489               i = loop->order[dim + 1];
2490             }
2491           else
2492             {
2493               ar = NULL;
2494               i = dim + 1;
2495             }
2496
2497           gfc_init_se (&se, NULL);
2498           se.loop = loop;
2499           se.expr = info->descriptor;
2500           stride = gfc_conv_array_stride (info->descriptor, info->dim[i]);
2501           index = gfc_conv_array_index_offset (&se, info, info->dim[i], i,
2502                                                ar, stride);
2503           gfc_add_block_to_block (pblock, &se.pre);
2504           info->offset = fold_build2 (PLUS_EXPR, gfc_array_index_type,
2505                                       info->offset, index);
2506           info->offset = gfc_evaluate_now (info->offset, pblock);
2507         }
2508
2509       /* Remember this offset for the second loop.  */
2510       if (dim == loop->temp_dim - 1)
2511         info->saved_offset = info->offset;
2512     }
2513 }
2514
2515
2516 /* Start a scalarized expression.  Creates a scope and declares loop
2517    variables.  */
2518
2519 void
2520 gfc_start_scalarized_body (gfc_loopinfo * loop, stmtblock_t * pbody)
2521 {
2522   int dim;
2523   int n;
2524   int flags;
2525
2526   gcc_assert (!loop->array_parameter);
2527
2528   for (dim = loop->dimen - 1; dim >= 0; dim--)
2529     {
2530       n = loop->order[dim];
2531
2532       gfc_start_block (&loop->code[n]);
2533
2534       /* Create the loop variable.  */
2535       loop->loopvar[n] = gfc_create_var (gfc_array_index_type, "S");
2536
2537       if (dim < loop->temp_dim)
2538         flags = 3;
2539       else
2540         flags = 1;
2541       /* Calculate values that will be constant within this loop.  */
2542       gfc_trans_preloop_setup (loop, dim, flags, &loop->code[n]);
2543     }
2544   gfc_start_block (pbody);
2545 }
2546
2547
2548 /* Generates the actual loop code for a scalarization loop.  */
2549
2550 static void
2551 gfc_trans_scalarized_loop_end (gfc_loopinfo * loop, int n,
2552                                stmtblock_t * pbody)
2553 {
2554   stmtblock_t block;
2555   tree cond;
2556   tree tmp;
2557   tree loopbody;
2558   tree exit_label;
2559
2560   loopbody = gfc_finish_block (pbody);
2561
2562   /* Initialize the loopvar.  */
2563   gfc_add_modify_expr (&loop->code[n], loop->loopvar[n], loop->from[n]);
2564
2565   exit_label = gfc_build_label_decl (NULL_TREE);
2566
2567   /* Generate the loop body.  */
2568   gfc_init_block (&block);
2569
2570   /* The exit condition.  */
2571   cond = build2 (GT_EXPR, boolean_type_node, loop->loopvar[n], loop->to[n]);
2572   tmp = build1_v (GOTO_EXPR, exit_label);
2573   TREE_USED (exit_label) = 1;
2574   tmp = build3_v (COND_EXPR, cond, tmp, build_empty_stmt ());
2575   gfc_add_expr_to_block (&block, tmp);
2576
2577   /* The main body.  */
2578   gfc_add_expr_to_block (&block, loopbody);
2579
2580   /* Increment the loopvar.  */
2581   tmp = build2 (PLUS_EXPR, gfc_array_index_type,
2582                 loop->loopvar[n], gfc_index_one_node);
2583   gfc_add_modify_expr (&block, loop->loopvar[n], tmp);
2584
2585   /* Build the loop.  */
2586   tmp = gfc_finish_block (&block);
2587   tmp = build1_v (LOOP_EXPR, tmp);
2588   gfc_add_expr_to_block (&loop->code[n], tmp);
2589
2590   /* Add the exit label.  */
2591   tmp = build1_v (LABEL_EXPR, exit_label);
2592   gfc_add_expr_to_block (&loop->code[n], tmp);
2593 }
2594
2595
2596 /* Finishes and generates the loops for a scalarized expression.  */
2597
2598 void
2599 gfc_trans_scalarizing_loops (gfc_loopinfo * loop, stmtblock_t * body)
2600 {
2601   int dim;
2602   int n;
2603   gfc_ss *ss;
2604   stmtblock_t *pblock;
2605   tree tmp;
2606
2607   pblock = body;
2608   /* Generate the loops.  */
2609   for (dim = 0; dim < loop->dimen; dim++)
2610     {
2611       n = loop->order[dim];
2612       gfc_trans_scalarized_loop_end (loop, n, pblock);
2613       loop->loopvar[n] = NULL_TREE;
2614       pblock = &loop->code[n];
2615     }
2616
2617   tmp = gfc_finish_block (pblock);
2618   gfc_add_expr_to_block (&loop->pre, tmp);
2619
2620   /* Clear all the used flags.  */
2621   for (ss = loop->ss; ss; ss = ss->loop_chain)
2622     ss->useflags = 0;
2623 }
2624
2625
2626 /* Finish the main body of a scalarized expression, and start the secondary
2627    copying body.  */
2628
2629 void
2630 gfc_trans_scalarized_loop_boundary (gfc_loopinfo * loop, stmtblock_t * body)
2631 {
2632   int dim;
2633   int n;
2634   stmtblock_t *pblock;
2635   gfc_ss *ss;
2636
2637   pblock = body;
2638   /* We finish as many loops as are used by the temporary.  */
2639   for (dim = 0; dim < loop->temp_dim - 1; dim++)
2640     {
2641       n = loop->order[dim];
2642       gfc_trans_scalarized_loop_end (loop, n, pblock);
2643       loop->loopvar[n] = NULL_TREE;
2644       pblock = &loop->code[n];
2645     }
2646
2647   /* We don't want to finish the outermost loop entirely.  */
2648   n = loop->order[loop->temp_dim - 1];
2649   gfc_trans_scalarized_loop_end (loop, n, pblock);
2650
2651   /* Restore the initial offsets.  */
2652   for (ss = loop->ss; ss != gfc_ss_terminator; ss = ss->loop_chain)
2653     {
2654       if ((ss->useflags & 2) == 0)
2655         continue;
2656
2657       if (ss->type != GFC_SS_SECTION
2658           && ss->type != GFC_SS_FUNCTION && ss->type != GFC_SS_CONSTRUCTOR
2659           && ss->type != GFC_SS_COMPONENT)
2660         continue;
2661
2662       ss->data.info.offset = ss->data.info.saved_offset;
2663     }
2664
2665   /* Restart all the inner loops we just finished.  */
2666   for (dim = loop->temp_dim - 2; dim >= 0; dim--)
2667     {
2668       n = loop->order[dim];
2669
2670       gfc_start_block (&loop->code[n]);
2671
2672       loop->loopvar[n] = gfc_create_var (gfc_array_index_type, "Q");
2673
2674       gfc_trans_preloop_setup (loop, dim, 2, &loop->code[n]);
2675     }
2676
2677   /* Start a block for the secondary copying code.  */
2678   gfc_start_block (body);
2679 }
2680
2681
2682 /* Calculate the upper bound of an array section.  */
2683
2684 static tree
2685 gfc_conv_section_upper_bound (gfc_ss * ss, int n, stmtblock_t * pblock)
2686 {
2687   int dim;
2688   gfc_expr *end;
2689   tree desc;
2690   tree bound;
2691   gfc_se se;
2692   gfc_ss_info *info;
2693
2694   gcc_assert (ss->type == GFC_SS_SECTION);
2695
2696   info = &ss->data.info;
2697   dim = info->dim[n];
2698
2699   if (info->ref->u.ar.dimen_type[dim] == DIMEN_VECTOR)
2700     /* We'll calculate the upper bound once we have access to the
2701        vector's descriptor.  */
2702     return NULL;
2703
2704   gcc_assert (info->ref->u.ar.dimen_type[dim] == DIMEN_RANGE);
2705   desc = info->descriptor;
2706   end = info->ref->u.ar.end[dim];
2707
2708   if (end)
2709     {
2710       /* The upper bound was specified.  */
2711       gfc_init_se (&se, NULL);
2712       gfc_conv_expr_type (&se, end, gfc_array_index_type);
2713       gfc_add_block_to_block (pblock, &se.pre);
2714       bound = se.expr;
2715     }
2716   else
2717     {
2718       /* No upper bound was specified, so use the bound of the array.  */
2719       bound = gfc_conv_array_ubound (desc, dim);
2720     }
2721
2722   return bound;
2723 }
2724
2725
2726 /* Calculate the lower bound of an array section.  */
2727
2728 static void
2729 gfc_conv_section_startstride (gfc_loopinfo * loop, gfc_ss * ss, int n)
2730 {
2731   gfc_expr *start;
2732   gfc_expr *end;
2733   gfc_expr *stride;
2734   tree desc;
2735   gfc_se se;
2736   gfc_ss_info *info;
2737   int dim;
2738
2739   gcc_assert (ss->type == GFC_SS_SECTION);
2740
2741   info = &ss->data.info;
2742   dim = info->dim[n];
2743
2744   if (info->ref->u.ar.dimen_type[dim] == DIMEN_VECTOR)
2745     {
2746       /* We use a zero-based index to access the vector.  */
2747       info->start[n] = gfc_index_zero_node;
2748       info->end[n] = gfc_index_zero_node;
2749       info->stride[n] = gfc_index_one_node;
2750       return;
2751     }
2752
2753   gcc_assert (info->ref->u.ar.dimen_type[dim] == DIMEN_RANGE);
2754   desc = info->descriptor;
2755   start = info->ref->u.ar.start[dim];
2756   end = info->ref->u.ar.end[dim];
2757   stride = info->ref->u.ar.stride[dim];
2758
2759   /* Calculate the start of the range.  For vector subscripts this will
2760      be the range of the vector.  */
2761   if (start)
2762     {
2763       /* Specified section start.  */
2764       gfc_init_se (&se, NULL);
2765       gfc_conv_expr_type (&se, start, gfc_array_index_type);
2766       gfc_add_block_to_block (&loop->pre, &se.pre);
2767       info->start[n] = se.expr;
2768     }
2769   else
2770     {
2771       /* No lower bound specified so use the bound of the array.  */
2772       info->start[n] = gfc_conv_array_lbound (desc, dim);
2773     }
2774   info->start[n] = gfc_evaluate_now (info->start[n], &loop->pre);
2775
2776   /* Similarly calculate the end.  Although this is not used in the
2777      scalarizer, it is needed when checking bounds and where the end
2778      is an expression with side-effects.  */
2779   if (end)
2780     {
2781       /* Specified section start.  */
2782       gfc_init_se (&se, NULL);
2783       gfc_conv_expr_type (&se, end, gfc_array_index_type);
2784       gfc_add_block_to_block (&loop->pre, &se.pre);
2785       info->end[n] = se.expr;
2786     }
2787   else
2788     {
2789       /* No upper bound specified so use the bound of the array.  */
2790       info->end[n] = gfc_conv_array_ubound (desc, dim);
2791     }
2792   info->end[n] = gfc_evaluate_now (info->end[n], &loop->pre);
2793
2794   /* Calculate the stride.  */
2795   if (stride == NULL)
2796     info->stride[n] = gfc_index_one_node;
2797   else
2798     {
2799       gfc_init_se (&se, NULL);
2800       gfc_conv_expr_type (&se, stride, gfc_array_index_type);
2801       gfc_add_block_to_block (&loop->pre, &se.pre);
2802       info->stride[n] = gfc_evaluate_now (se.expr, &loop->pre);
2803     }
2804 }
2805
2806
2807 /* Calculates the range start and stride for a SS chain.  Also gets the
2808    descriptor and data pointer.  The range of vector subscripts is the size
2809    of the vector.  Array bounds are also checked.  */
2810
2811 void
2812 gfc_conv_ss_startstride (gfc_loopinfo * loop)
2813 {
2814   int n;
2815   tree tmp;
2816   gfc_ss *ss;
2817   tree desc;
2818
2819   loop->dimen = 0;
2820   /* Determine the rank of the loop.  */
2821   for (ss = loop->ss;
2822        ss != gfc_ss_terminator && loop->dimen == 0; ss = ss->loop_chain)
2823     {
2824       switch (ss->type)
2825         {
2826         case GFC_SS_SECTION:
2827         case GFC_SS_CONSTRUCTOR:
2828         case GFC_SS_FUNCTION:
2829         case GFC_SS_COMPONENT:
2830           loop->dimen = ss->data.info.dimen;
2831           break;
2832
2833         /* As usual, lbound and ubound are exceptions!.  */
2834         case GFC_SS_INTRINSIC:
2835           switch (ss->expr->value.function.isym->id)
2836             {
2837             case GFC_ISYM_LBOUND:
2838             case GFC_ISYM_UBOUND:
2839               loop->dimen = ss->data.info.dimen;
2840
2841             default:
2842               break;
2843             }
2844
2845         default:
2846           break;
2847         }
2848     }
2849
2850   /* We should have determined the rank of the expression by now.  If
2851      not, that's bad news.  */
2852   gcc_assert (loop->dimen != 0);
2853
2854   /* Loop over all the SS in the chain.  */
2855   for (ss = loop->ss; ss != gfc_ss_terminator; ss = ss->loop_chain)
2856     {
2857       if (ss->expr && ss->expr->shape && !ss->shape)
2858         ss->shape = ss->expr->shape;
2859
2860       switch (ss->type)
2861         {
2862         case GFC_SS_SECTION:
2863           /* Get the descriptor for the array.  */
2864           gfc_conv_ss_descriptor (&loop->pre, ss, !loop->array_parameter);
2865
2866           for (n = 0; n < ss->data.info.dimen; n++)
2867             gfc_conv_section_startstride (loop, ss, n);
2868           break;
2869
2870         case GFC_SS_INTRINSIC:
2871           switch (ss->expr->value.function.isym->id)
2872             {
2873             /* Fall through to supply start and stride.  */
2874             case GFC_ISYM_LBOUND:
2875             case GFC_ISYM_UBOUND:
2876               break;
2877             default:
2878               continue;
2879             }
2880
2881         case GFC_SS_CONSTRUCTOR:
2882         case GFC_SS_FUNCTION:
2883           for (n = 0; n < ss->data.info.dimen; n++)
2884             {
2885               ss->data.info.start[n] = gfc_index_zero_node;
2886               ss->data.info.end[n] = gfc_index_zero_node;
2887               ss->data.info.stride[n] = gfc_index_one_node;
2888             }
2889           break;
2890
2891         default:
2892           break;
2893         }
2894     }
2895
2896   /* The rest is just runtime bound checking.  */
2897   if (flag_bounds_check)
2898     {
2899       stmtblock_t block;
2900       tree lbound, ubound;
2901       tree end;
2902       tree size[GFC_MAX_DIMENSIONS];
2903       tree stride_pos, stride_neg, non_zerosized, tmp2;
2904       gfc_ss_info *info;
2905       char *msg;
2906       int dim;
2907
2908       gfc_start_block (&block);
2909
2910       for (n = 0; n < loop->dimen; n++)
2911         size[n] = NULL_TREE;
2912
2913       for (ss = loop->ss; ss != gfc_ss_terminator; ss = ss->loop_chain)
2914         {
2915           if (ss->type != GFC_SS_SECTION)
2916             continue;
2917
2918           /* TODO: range checking for mapped dimensions.  */
2919           info = &ss->data.info;
2920
2921           /* This code only checks ranges.  Elemental and vector
2922              dimensions are checked later.  */
2923           for (n = 0; n < loop->dimen; n++)
2924             {
2925               bool check_upper;
2926
2927               dim = info->dim[n];
2928               if (info->ref->u.ar.dimen_type[dim] != DIMEN_RANGE)
2929                 continue;
2930
2931               if (dim == info->ref->u.ar.dimen - 1
2932                   && (info->ref->u.ar.as->type == AS_ASSUMED_SIZE
2933                       || info->ref->u.ar.as->cp_was_assumed))
2934                 check_upper = false;
2935               else
2936                 check_upper = true;
2937
2938               /* Zero stride is not allowed.  */
2939               tmp = fold_build2 (EQ_EXPR, boolean_type_node, info->stride[n],
2940                                  gfc_index_zero_node);
2941               asprintf (&msg, "Zero stride is not allowed, for dimension %d "
2942                         "of array '%s'", info->dim[n]+1,
2943                         ss->expr->symtree->name);
2944               gfc_trans_runtime_check (tmp, &block, &ss->expr->where, msg);
2945               gfc_free (msg);
2946
2947               desc = ss->data.info.descriptor;
2948
2949               /* This is the run-time equivalent of resolve.c's
2950                  check_dimension().  The logical is more readable there
2951                  than it is here, with all the trees.  */
2952               lbound = gfc_conv_array_lbound (desc, dim);
2953               end = info->end[n];
2954               if (check_upper)
2955                 ubound = gfc_conv_array_ubound (desc, dim);
2956               else
2957                 ubound = NULL;
2958
2959               /* non_zerosized is true when the selected range is not
2960                  empty.  */
2961               stride_pos = fold_build2 (GT_EXPR, boolean_type_node,
2962                                         info->stride[n], gfc_index_zero_node);
2963               tmp = fold_build2 (LE_EXPR, boolean_type_node, info->start[n],
2964                                  end);
2965               stride_pos = fold_build2 (TRUTH_AND_EXPR, boolean_type_node,
2966                                         stride_pos, tmp);
2967
2968               stride_neg = fold_build2 (LT_EXPR, boolean_type_node,
2969                                         info->stride[n], gfc_index_zero_node);
2970               tmp = fold_build2 (GE_EXPR, boolean_type_node, info->start[n],
2971                                  end);
2972               stride_neg = fold_build2 (TRUTH_AND_EXPR, boolean_type_node,
2973                                         stride_neg, tmp);
2974               non_zerosized = fold_build2 (TRUTH_OR_EXPR, boolean_type_node,
2975                                            stride_pos, stride_neg);
2976
2977               /* Check the start of the range against the lower and upper
2978                  bounds of the array, if the range is not empty.  */
2979               tmp = fold_build2 (LT_EXPR, boolean_type_node, info->start[n],
2980                                  lbound);
2981               tmp = fold_build2 (TRUTH_AND_EXPR, boolean_type_node,
2982                                  non_zerosized, tmp);
2983               asprintf (&msg, "%s, lower bound of dimension %d of array '%s'"
2984                         " exceeded (%%ld < %%ld)", gfc_msg_fault,
2985                         info->dim[n]+1, ss->expr->symtree->name);
2986               gfc_trans_runtime_check (tmp, &block, &ss->expr->where, msg,
2987                                        fold_convert (long_integer_type_node,
2988                                                      info->start[n]),
2989                                        fold_convert (long_integer_type_node,
2990                                                      lbound));
2991               gfc_free (msg);
2992
2993               if (check_upper)
2994                 {
2995                   tmp = fold_build2 (GT_EXPR, boolean_type_node,
2996                                      info->start[n], ubound);
2997                   tmp = fold_build2 (TRUTH_AND_EXPR, boolean_type_node,
2998                                      non_zerosized, tmp);
2999                   asprintf (&msg, "%s, upper bound of dimension %d of array "
3000                             "'%s' exceeded (%%ld > %%ld)", gfc_msg_fault,
3001                             info->dim[n]+1, ss->expr->symtree->name);
3002                   gfc_trans_runtime_check (tmp, &block, &ss->expr->where, msg,
3003                         fold_convert (long_integer_type_node, info->start[n]),
3004                         fold_convert (long_integer_type_node, ubound));
3005                   gfc_free (msg);
3006                 }
3007
3008               /* Compute the last element of the range, which is not
3009                  necessarily "end" (think 0:5:3, which doesn't contain 5)
3010                  and check it against both lower and upper bounds.  */
3011               tmp2 = fold_build2 (MINUS_EXPR, gfc_array_index_type, end,
3012                                   info->start[n]);
3013               tmp2 = fold_build2 (TRUNC_MOD_EXPR, gfc_array_index_type, tmp2,
3014                                   info->stride[n]);
3015               tmp2 = fold_build2 (MINUS_EXPR, gfc_array_index_type, end,
3016                                   tmp2);
3017
3018               tmp = fold_build2 (LT_EXPR, boolean_type_node, tmp2, lbound);
3019               tmp = fold_build2 (TRUTH_AND_EXPR, boolean_type_node,
3020                                  non_zerosized, tmp);
3021               asprintf (&msg, "%s, lower bound of dimension %d of array '%s'"
3022                         " exceeded (%%ld < %%ld)", gfc_msg_fault,
3023                         info->dim[n]+1, ss->expr->symtree->name);
3024               gfc_trans_runtime_check (tmp, &block, &ss->expr->where, msg,
3025                                        fold_convert (long_integer_type_node,
3026                                                      tmp2),
3027                                        fold_convert (long_integer_type_node,
3028                                                      lbound));
3029               gfc_free (msg);
3030
3031               if (check_upper)
3032                 {
3033                   tmp = fold_build2 (GT_EXPR, boolean_type_node, tmp2, ubound);
3034                   tmp = fold_build2 (TRUTH_AND_EXPR, boolean_type_node,
3035                                      non_zerosized, tmp);
3036                   asprintf (&msg, "%s, upper bound of dimension %d of array "
3037                             "'%s' exceeded (%%ld > %%ld)", gfc_msg_fault,
3038                             info->dim[n]+1, ss->expr->symtree->name);
3039                   gfc_trans_runtime_check (tmp, &block, &ss->expr->where, msg,
3040                         fold_convert (long_integer_type_node, tmp2),
3041                         fold_convert (long_integer_type_node, ubound));
3042                   gfc_free (msg);
3043                 }
3044
3045               /* Check the section sizes match.  */
3046               tmp = fold_build2 (MINUS_EXPR, gfc_array_index_type, end,
3047                                  info->start[n]);
3048               tmp = fold_build2 (FLOOR_DIV_EXPR, gfc_array_index_type, tmp,
3049                                  info->stride[n]);
3050               /* We remember the size of the first section, and check all the
3051                  others against this.  */
3052               if (size[n])
3053                 {
3054                   tree tmp3;
3055
3056                   tmp3 = fold_build2 (NE_EXPR, boolean_type_node, tmp, size[n]);
3057
3058                   /* For optional arguments, only check bounds if the
3059                      argument is present.  */
3060                   if (ss->expr->symtree->n.sym->attr.optional
3061                       || ss->expr->symtree->n.sym->attr.not_always_present)
3062                     {
3063                       tree cond;
3064
3065                       cond = gfc_conv_expr_present (ss->expr->symtree->n.sym);
3066                       tmp3 = fold_build2 (TRUTH_AND_EXPR, boolean_type_node,
3067                                           cond, tmp3);
3068                     }
3069
3070                   asprintf (&msg, "%s, size mismatch for dimension %d "
3071                             "of array '%s' (%%ld/%%ld)", gfc_msg_bounds,
3072                             info->dim[n]+1, ss->expr->symtree->name);
3073                   gfc_trans_runtime_check (tmp3, &block, &ss->expr->where, msg,
3074                         fold_convert (long_integer_type_node, tmp),
3075                         fold_convert (long_integer_type_node, size[n]));
3076                   gfc_free (msg);
3077                 }
3078               else
3079                 size[n] = gfc_evaluate_now (tmp, &block);
3080             }
3081         }
3082
3083       tmp = gfc_finish_block (&block);
3084       gfc_add_expr_to_block (&loop->pre, tmp);
3085     }
3086 }
3087
3088
3089 /* Return true if the two SS could be aliased, i.e. both point to the same data
3090    object.  */
3091 /* TODO: resolve aliases based on frontend expressions.  */
3092
3093 static int
3094 gfc_could_be_alias (gfc_ss * lss, gfc_ss * rss)
3095 {
3096   gfc_ref *lref;
3097   gfc_ref *rref;
3098   gfc_symbol *lsym;
3099   gfc_symbol *rsym;
3100
3101   lsym = lss->expr->symtree->n.sym;
3102   rsym = rss->expr->symtree->n.sym;
3103   if (gfc_symbols_could_alias (lsym, rsym))
3104     return 1;
3105
3106   if (rsym->ts.type != BT_DERIVED
3107       && lsym->ts.type != BT_DERIVED)
3108     return 0;
3109
3110   /* For derived types we must check all the component types.  We can ignore
3111      array references as these will have the same base type as the previous
3112      component ref.  */
3113   for (lref = lss->expr->ref; lref != lss->data.info.ref; lref = lref->next)
3114     {
3115       if (lref->type != REF_COMPONENT)
3116         continue;
3117
3118       if (gfc_symbols_could_alias (lref->u.c.sym, rsym))
3119         return 1;
3120
3121       for (rref = rss->expr->ref; rref != rss->data.info.ref;
3122            rref = rref->next)
3123         {
3124           if (rref->type != REF_COMPONENT)
3125             continue;
3126
3127           if (gfc_symbols_could_alias (lref->u.c.sym, rref->u.c.sym))
3128             return 1;
3129         }
3130     }
3131
3132   for (rref = rss->expr->ref; rref != rss->data.info.ref; rref = rref->next)
3133     {
3134       if (rref->type != REF_COMPONENT)
3135         break;
3136
3137       if (gfc_symbols_could_alias (rref->u.c.sym, lsym))
3138         return 1;
3139     }
3140
3141   return 0;
3142 }
3143
3144
3145 /* Resolve array data dependencies.  Creates a temporary if required.  */
3146 /* TODO: Calc dependencies with gfc_expr rather than gfc_ss, and move to
3147    dependency.c.  */
3148
3149 void
3150 gfc_conv_resolve_dependencies (gfc_loopinfo * loop, gfc_ss * dest,
3151                                gfc_ss * rss)
3152 {
3153   gfc_ss *ss;
3154   gfc_ref *lref;
3155   gfc_ref *rref;
3156   gfc_ref *aref;
3157   int nDepend = 0;
3158   int temp_dim = 0;
3159
3160   loop->temp_ss = NULL;
3161   aref = dest->data.info.ref;
3162   temp_dim = 0;
3163
3164   for (ss = rss; ss != gfc_ss_terminator; ss = ss->next)
3165     {
3166       if (ss->type != GFC_SS_SECTION)
3167         continue;
3168
3169       if (gfc_could_be_alias (dest, ss)
3170             || gfc_are_equivalenced_arrays (dest->expr, ss->expr))
3171         {
3172           nDepend = 1;
3173           break;
3174         }
3175
3176       if (dest->expr->symtree->n.sym == ss->expr->symtree->n.sym)
3177         {
3178           lref = dest->expr->ref;
3179           rref = ss->expr->ref;
3180
3181           nDepend = gfc_dep_resolver (lref, rref);
3182           if (nDepend == 1)
3183             break;
3184 #if 0
3185           /* TODO : loop shifting.  */
3186           if (nDepend == 1)
3187             {
3188               /* Mark the dimensions for LOOP SHIFTING */
3189               for (n = 0; n < loop->dimen; n++)
3190                 {
3191                   int dim = dest->data.info.dim[n];
3192
3193                   if (lref->u.ar.dimen_type[dim] == DIMEN_VECTOR)
3194                     depends[n] = 2;
3195                   else if (! gfc_is_same_range (&lref->u.ar,
3196                                                 &rref->u.ar, dim, 0))
3197                     depends[n] = 1;
3198                  }
3199
3200               /* Put all the dimensions with dependencies in the
3201                  innermost loops.  */
3202               dim = 0;
3203               for (n = 0; n < loop->dimen; n++)
3204                 {
3205                   gcc_assert (loop->order[n] == n);
3206                   if (depends[n])
3207                   loop->order[dim++] = n;
3208                 }
3209               temp_dim = dim;
3210               for (n = 0; n < loop->dimen; n++)
3211                 {
3212                   if (! depends[n])
3213                   loop->order[dim++] = n;
3214                 }
3215
3216               gcc_assert (dim == loop->dimen);
3217               break;
3218             }
3219 #endif
3220         }
3221     }
3222
3223   if (nDepend == 1)
3224     {
3225       tree base_type = gfc_typenode_for_spec (&dest->expr->ts);
3226       if (GFC_ARRAY_TYPE_P (base_type)
3227           || GFC_DESCRIPTOR_TYPE_P (base_type))
3228         base_type = gfc_get_element_type (base_type);
3229       loop->temp_ss = gfc_get_ss ();
3230       loop->temp_ss->type = GFC_SS_TEMP;
3231       loop->temp_ss->data.temp.type = base_type;
3232       loop->temp_ss->string_length = dest->string_length;
3233       loop->temp_ss->data.temp.dimen = loop->dimen;
3234       loop->temp_ss->next = gfc_ss_terminator;
3235       gfc_add_ss_to_loop (loop, loop->temp_ss);
3236     }
3237   else
3238     loop->temp_ss = NULL;
3239 }
3240
3241
3242 /* Initialize the scalarization loop.  Creates the loop variables.  Determines
3243    the range of the loop variables.  Creates a temporary if required.
3244    Calculates how to transform from loop variables to array indices for each
3245    expression.  Also generates code for scalar expressions which have been
3246    moved outside the loop.  */
3247
3248 void
3249 gfc_conv_loop_setup (gfc_loopinfo * loop)
3250 {
3251   int n;
3252   int dim;
3253   gfc_ss_info *info;
3254   gfc_ss_info *specinfo;
3255   gfc_ss *ss;
3256   tree tmp;
3257   tree len;
3258   gfc_ss *loopspec[GFC_MAX_DIMENSIONS];
3259   bool dynamic[GFC_MAX_DIMENSIONS];
3260   gfc_constructor *c;
3261   mpz_t *cshape;
3262   mpz_t i;
3263
3264   mpz_init (i);
3265   for (n = 0; n < loop->dimen; n++)
3266     {
3267       loopspec[n] = NULL;
3268       dynamic[n] = false;
3269       /* We use one SS term, and use that to determine the bounds of the
3270          loop for this dimension.  We try to pick the simplest term.  */
3271       for (ss = loop->ss; ss != gfc_ss_terminator; ss = ss->loop_chain)
3272         {
3273           if (ss->shape)
3274             {
3275               /* The frontend has worked out the size for us.  */
3276               loopspec[n] = ss;
3277               continue;
3278             }
3279
3280           if (ss->type == GFC_SS_CONSTRUCTOR)
3281             {
3282               /* An unknown size constructor will always be rank one.
3283                  Higher rank constructors will either have known shape,
3284                  or still be wrapped in a call to reshape.  */
3285               gcc_assert (loop->dimen == 1);
3286
3287               /* Always prefer to use the constructor bounds if the size
3288                  can be determined at compile time.  Prefer not to otherwise,
3289                  since the general case involves realloc, and it's better to
3290                  avoid that overhead if possible.  */
3291               c = ss->expr->value.constructor;
3292               dynamic[n] = gfc_get_array_constructor_size (&i, c);
3293               if (!dynamic[n] || !loopspec[n])
3294                 loopspec[n] = ss;
3295               continue;
3296             }
3297
3298           /* TODO: Pick the best bound if we have a choice between a
3299              function and something else.  */
3300           if (ss->type == GFC_SS_FUNCTION)
3301             {
3302               loopspec[n] = ss;
3303               continue;
3304             }
3305
3306           if (ss->type != GFC_SS_SECTION)
3307             continue;
3308
3309           if (loopspec[n])
3310             specinfo = &loopspec[n]->data.info;
3311           else
3312             specinfo = NULL;
3313           info = &ss->data.info;
3314
3315           if (!specinfo)
3316             loopspec[n] = ss;
3317           /* Criteria for choosing a loop specifier (most important first):
3318              doesn't need realloc
3319              stride of one
3320              known stride
3321              known lower bound
3322              known upper bound
3323            */
3324           else if (loopspec[n]->type == GFC_SS_CONSTRUCTOR && dynamic[n])
3325             loopspec[n] = ss;
3326           else if (integer_onep (info->stride[n])
3327                    && !integer_onep (specinfo->stride[n]))
3328             loopspec[n] = ss;
3329           else if (INTEGER_CST_P (info->stride[n])
3330                    && !INTEGER_CST_P (specinfo->stride[n]))
3331             loopspec[n] = ss;
3332           else if (INTEGER_CST_P (info->start[n])
3333                    && !INTEGER_CST_P (specinfo->start[n]))
3334             loopspec[n] = ss;
3335           /* We don't work out the upper bound.
3336              else if (INTEGER_CST_P (info->finish[n])
3337              && ! INTEGER_CST_P (specinfo->finish[n]))
3338              loopspec[n] = ss; */
3339         }
3340
3341       /* We should have found the scalarization loop specifier.  If not,
3342          that's bad news.  */
3343       gcc_assert (loopspec[n]);
3344
3345       info = &loopspec[n]->data.info;
3346
3347       /* Set the extents of this range.  */
3348       cshape = loopspec[n]->shape;
3349       if (cshape && INTEGER_CST_P (info->start[n])
3350           && INTEGER_CST_P (info->stride[n]))
3351         {
3352           loop->from[n] = info->start[n];
3353           mpz_set (i, cshape[n]);
3354           mpz_sub_ui (i, i, 1);
3355           /* To = from + (size - 1) * stride.  */
3356           tmp = gfc_conv_mpz_to_tree (i, gfc_index_integer_kind);
3357           if (!integer_onep (info->stride[n]))
3358             tmp = fold_build2 (MULT_EXPR, gfc_array_index_type,
3359                                tmp, info->stride[n]);
3360           loop->to[n] = fold_build2 (PLUS_EXPR, gfc_array_index_type,
3361                                      loop->from[n], tmp);
3362         }
3363       else
3364         {
3365           loop->from[n] = info->start[n];
3366           switch (loopspec[n]->type)
3367             {
3368             case GFC_SS_CONSTRUCTOR:
3369               /* The upper bound is calculated when we expand the
3370                  constructor.  */
3371               gcc_assert (loop->to[n] == NULL_TREE);
3372               break;
3373
3374             case GFC_SS_SECTION:
3375               loop->to[n] = gfc_conv_section_upper_bound (loopspec[n], n,
3376                                                           &loop->pre);
3377               break;
3378
3379             case GFC_SS_FUNCTION:
3380               /* The loop bound will be set when we generate the call.  */
3381               gcc_assert (loop->to[n] == NULL_TREE);
3382               break;
3383
3384             default:
3385               gcc_unreachable ();
3386             }
3387         }
3388
3389       /* Transform everything so we have a simple incrementing variable.  */
3390       if (integer_onep (info->stride[n]))
3391         info->delta[n] = gfc_index_zero_node;
3392       else
3393         {
3394           /* Set the delta for this section.  */
3395           info->delta[n] = gfc_evaluate_now (loop->from[n], &loop->pre);
3396           /* Number of iterations is (end - start + step) / step.
3397              with start = 0, this simplifies to
3398              last = end / step;
3399              for (i = 0; i<=last; i++){...};  */
3400           tmp = fold_build2 (MINUS_EXPR, gfc_array_index_type,
3401                              loop->to[n], loop->from[n]);
3402           tmp = fold_build2 (TRUNC_DIV_EXPR, gfc_array_index_type, 
3403                              tmp, info->stride[n]);
3404           loop->to[n] = gfc_evaluate_now (tmp, &loop->pre);
3405           /* Make the loop variable start at 0.  */
3406           loop->from[n] = gfc_index_zero_node;
3407         }
3408     }
3409
3410   /* Add all the scalar code that can be taken out of the loops.
3411      This may include calculating the loop bounds, so do it before
3412      allocating the temporary.  */
3413   gfc_add_loop_ss_code (loop, loop->ss, false);
3414
3415   /* If we want a temporary then create it.  */
3416   if (loop->temp_ss != NULL)
3417     {
3418       gcc_assert (loop->temp_ss->type == GFC_SS_TEMP);
3419
3420       /* Make absolutely sure that this is a complete type.  */
3421       if (loop->temp_ss->string_length)
3422         loop->temp_ss->data.temp.type
3423                 = gfc_get_character_type_len (gfc_default_character_kind,
3424                                               loop->temp_ss->string_length);
3425
3426       tmp = loop->temp_ss->data.temp.type;
3427       len = loop->temp_ss->string_length;
3428       n = loop->temp_ss->data.temp.dimen;
3429       memset (&loop->temp_ss->data.info, 0, sizeof (gfc_ss_info));
3430       loop->temp_ss->type = GFC_SS_SECTION;
3431       loop->temp_ss->data.info.dimen = n;
3432       gfc_trans_create_temp_array (&loop->pre, &loop->post, loop,
3433                                    &loop->temp_ss->data.info, tmp, false, true,
3434                                    false);
3435     }
3436
3437   for (n = 0; n < loop->temp_dim; n++)
3438     loopspec[loop->order[n]] = NULL;
3439
3440   mpz_clear (i);
3441
3442   /* For array parameters we don't have loop variables, so don't calculate the
3443      translations.  */
3444   if (loop->array_parameter)
3445     return;
3446
3447   /* Calculate the translation from loop variables to array indices.  */
3448   for (ss = loop->ss; ss != gfc_ss_terminator; ss = ss->loop_chain)
3449     {
3450       if (ss->type != GFC_SS_SECTION && ss->type != GFC_SS_COMPONENT)
3451         continue;
3452
3453       info = &ss->data.info;
3454
3455       for (n = 0; n < info->dimen; n++)
3456         {
3457           dim = info->dim[n];
3458
3459           /* If we are specifying the range the delta is already set.  */
3460           if (loopspec[n] != ss)
3461             {
3462               /* Calculate the offset relative to the loop variable.
3463                  First multiply by the stride.  */
3464               tmp = loop->from[n];
3465               if (!integer_onep (info->stride[n]))
3466                 tmp = fold_build2 (MULT_EXPR, gfc_array_index_type,
3467                                    tmp, info->stride[n]);
3468
3469               /* Then subtract this from our starting value.  */
3470               tmp = fold_build2 (MINUS_EXPR, gfc_array_index_type,
3471                                  info->start[n], tmp);
3472
3473               info->delta[n] = gfc_evaluate_now (tmp, &loop->pre);
3474             }
3475         }
3476     }
3477 }
3478
3479
3480 /* Fills in an array descriptor, and returns the size of the array.  The size
3481    will be a simple_val, ie a variable or a constant.  Also calculates the
3482    offset of the base.  Returns the size of the array.
3483    {
3484     stride = 1;
3485     offset = 0;
3486     for (n = 0; n < rank; n++)
3487       {
3488         a.lbound[n] = specified_lower_bound;
3489         offset = offset + a.lbond[n] * stride;
3490         size = 1 - lbound;
3491         a.ubound[n] = specified_upper_bound;
3492         a.stride[n] = stride;
3493         size = ubound + size; //size = ubound + 1 - lbound
3494         stride = stride * size;
3495       }
3496     return (stride);
3497    }  */
3498 /*GCC ARRAYS*/
3499
3500 static tree
3501 gfc_array_init_size (tree descriptor, int rank, tree * poffset,
3502                      gfc_expr ** lower, gfc_expr ** upper,
3503                      stmtblock_t * pblock)
3504 {
3505   tree type;
3506   tree tmp;
3507   tree size;
3508   tree offset;
3509   tree stride;
3510   tree cond;
3511   tree or_expr;
3512   tree thencase;
3513   tree elsecase;
3514   tree var;
3515   stmtblock_t thenblock;
3516   stmtblock_t elseblock;
3517   gfc_expr *ubound;
3518   gfc_se se;
3519   int n;
3520
3521   type = TREE_TYPE (descriptor);
3522
3523   stride = gfc_index_one_node;
3524   offset = gfc_index_zero_node;
3525
3526   /* Set the dtype.  */
3527   tmp = gfc_conv_descriptor_dtype (descriptor);
3528   gfc_add_modify_expr (pblock, tmp, gfc_get_dtype (TREE_TYPE (descriptor)));
3529
3530   or_expr = NULL_TREE;
3531
3532   for (n = 0; n < rank; n++)
3533     {
3534       /* We have 3 possibilities for determining the size of the array:
3535          lower == NULL    => lbound = 1, ubound = upper[n]
3536          upper[n] = NULL  => lbound = 1, ubound = lower[n]
3537          upper[n] != NULL => lbound = lower[n], ubound = upper[n]  */
3538       ubound = upper[n];
3539
3540       /* Set lower bound.  */
3541       gfc_init_se (&se, NULL);
3542       if (lower == NULL)
3543         se.expr = gfc_index_one_node;
3544       else
3545         {
3546           gcc_assert (lower[n]);
3547           if (ubound)
3548             {
3549               gfc_conv_expr_type (&se, lower[n], gfc_array_index_type);
3550               gfc_add_block_to_block (pblock, &se.pre);
3551             }
3552           else
3553             {
3554               se.expr = gfc_index_one_node;
3555               ubound = lower[n];
3556             }
3557         }
3558       tmp = gfc_conv_descriptor_lbound (descriptor, gfc_rank_cst[n]);
3559       gfc_add_modify_expr (pblock, tmp, se.expr);
3560
3561       /* Work out the offset for this component.  */
3562       tmp = fold_build2 (MULT_EXPR, gfc_array_index_type, se.expr, stride);
3563       offset = fold_build2 (MINUS_EXPR, gfc_array_index_type, offset, tmp);
3564
3565       /* Start the calculation for the size of this dimension.  */
3566       size = build2 (MINUS_EXPR, gfc_array_index_type,
3567                      gfc_index_one_node, se.expr);
3568
3569       /* Set upper bound.  */
3570       gfc_init_se (&se, NULL);
3571       gcc_assert (ubound);
3572       gfc_conv_expr_type (&se, ubound, gfc_array_index_type);
3573       gfc_add_block_to_block (pblock, &se.pre);
3574
3575       tmp = gfc_conv_descriptor_ubound (descriptor, gfc_rank_cst[n]);
3576       gfc_add_modify_expr (pblock, tmp, se.expr);
3577
3578       /* Store the stride.  */
3579       tmp = gfc_conv_descriptor_stride (descriptor, gfc_rank_cst[n]);
3580       gfc_add_modify_expr (pblock, tmp, stride);
3581
3582       /* Calculate the size of this dimension.  */
3583       size = fold_build2 (PLUS_EXPR, gfc_array_index_type, se.expr, size);
3584
3585       /* Check whether the size for this dimension is negative.  */
3586       cond = fold_build2 (LE_EXPR, boolean_type_node, size,
3587                           gfc_index_zero_node);
3588       if (n == 0)
3589         or_expr = cond;
3590       else
3591         or_expr = fold_build2 (TRUTH_OR_EXPR, boolean_type_node, or_expr, cond);
3592
3593       /* Multiply the stride by the number of elements in this dimension.  */
3594       stride = fold_build2 (MULT_EXPR, gfc_array_index_type, stride, size);
3595       stride = gfc_evaluate_now (stride, pblock);
3596     }
3597
3598   /* The stride is the number of elements in the array, so multiply by the
3599      size of an element to get the total size.  */
3600   tmp = TYPE_SIZE_UNIT (gfc_get_element_type (type));
3601   size = fold_build2 (MULT_EXPR, gfc_array_index_type, stride,
3602                       fold_convert (gfc_array_index_type, tmp));
3603
3604   if (poffset != NULL)
3605     {
3606       offset = gfc_evaluate_now (offset, pblock);
3607       *poffset = offset;
3608     }
3609
3610   if (integer_zerop (or_expr))
3611     return size;
3612   if (integer_onep (or_expr))
3613     return gfc_index_zero_node;
3614
3615   var = gfc_create_var (TREE_TYPE (size), "size");
3616   gfc_start_block (&thenblock);
3617   gfc_add_modify_expr (&thenblock, var, gfc_index_zero_node);
3618   thencase = gfc_finish_block (&thenblock);
3619
3620   gfc_start_block (&elseblock);
3621   gfc_add_modify_expr (&elseblock, var, size);
3622   elsecase = gfc_finish_block (&elseblock);
3623
3624   tmp = gfc_evaluate_now (or_expr, pblock);
3625   tmp = build3_v (COND_EXPR, tmp, thencase, elsecase);
3626   gfc_add_expr_to_block (pblock, tmp);
3627
3628   return var;
3629 }
3630
3631
3632 /* Initializes the descriptor and generates a call to _gfor_allocate.  Does
3633    the work for an ALLOCATE statement.  */
3634 /*GCC ARRAYS*/
3635
3636 bool
3637 gfc_array_allocate (gfc_se * se, gfc_expr * expr, tree pstat)
3638 {
3639   tree tmp;
3640   tree pointer;
3641   tree offset;
3642   tree size;
3643   gfc_expr **lower;
3644   gfc_expr **upper;
3645   gfc_ref *ref, *prev_ref = NULL;
3646   bool allocatable_array;
3647
3648   ref = expr->ref;
3649
3650   /* Find the last reference in the chain.  */
3651   while (ref && ref->next != NULL)
3652     {
3653       gcc_assert (ref->type != REF_ARRAY || ref->u.ar.type == AR_ELEMENT);
3654       prev_ref = ref;
3655       ref = ref->next;
3656     }
3657
3658   if (ref == NULL || ref->type != REF_ARRAY)
3659     return false;
3660
3661   if (!prev_ref)
3662     allocatable_array = expr->symtree->n.sym->attr.allocatable;
3663   else
3664     allocatable_array = prev_ref->u.c.component->allocatable;
3665
3666   /* Figure out the size of the array.  */
3667   switch (ref->u.ar.type)
3668     {
3669     case AR_ELEMENT:
3670       lower = NULL;
3671       upper = ref->u.ar.start;
3672       break;
3673
3674     case AR_FULL:
3675       gcc_assert (ref->u.ar.as->type == AS_EXPLICIT);
3676
3677       lower = ref->u.ar.as->lower;
3678       upper = ref->u.ar.as->upper;
3679       break;
3680
3681     case AR_SECTION:
3682       lower = ref->u.ar.start;
3683       upper = ref->u.ar.end;
3684       break;
3685
3686     default:
3687       gcc_unreachable ();
3688       break;
3689     }
3690
3691   size = gfc_array_init_size (se->expr, ref->u.ar.as->rank, &offset,
3692                               lower, upper, &se->pre);
3693
3694   /* Allocate memory to store the data.  */
3695   pointer = gfc_conv_descriptor_data_get (se->expr);
3696   STRIP_NOPS (pointer);
3697
3698   /* The allocate_array variants take the old pointer as first argument.  */
3699   if (allocatable_array)
3700     tmp = gfc_allocate_array_with_status (&se->pre, pointer, size, pstat);
3701   else
3702     tmp = gfc_allocate_with_status (&se->pre, size, pstat);
3703   tmp = build2 (MODIFY_EXPR, void_type_node, pointer, tmp);
3704   gfc_add_expr_to_block (&se->pre, tmp);
3705
3706   tmp = gfc_conv_descriptor_offset (se->expr);
3707   gfc_add_modify_expr (&se->pre, tmp, offset);
3708
3709   if (expr->ts.type == BT_DERIVED
3710         && expr->ts.derived->attr.alloc_comp)
3711     {
3712       tmp = gfc_nullify_alloc_comp (expr->ts.derived, se->expr,
3713                                     ref->u.ar.as->rank);
3714       gfc_add_expr_to_block (&se->pre, tmp);
3715     }
3716
3717   return true;
3718 }
3719
3720
3721 /* Deallocate an array variable.  Also used when an allocated variable goes
3722    out of scope.  */
3723 /*GCC ARRAYS*/
3724
3725 tree
3726 gfc_array_deallocate (tree descriptor, tree pstat)
3727 {
3728   tree var;
3729   tree tmp;
3730   stmtblock_t block;
3731
3732   gfc_start_block (&block);
3733   /* Get a pointer to the data.  */
3734   var = gfc_conv_descriptor_data_get (descriptor);
3735   STRIP_NOPS (var);
3736
3737   /* Parameter is the address of the data component.  */
3738   tmp = gfc_deallocate_with_status (var, pstat, false);
3739   gfc_add_expr_to_block (&block, tmp);
3740
3741   /* Zero the data pointer.  */
3742   tmp = build2 (MODIFY_EXPR, void_type_node,
3743                 var, build_int_cst (TREE_TYPE (var), 0));
3744   gfc_add_expr_to_block (&block, tmp);
3745
3746   return gfc_finish_block (&block);
3747 }
3748
3749
3750 /* Create an array constructor from an initialization expression.
3751    We assume the frontend already did any expansions and conversions.  */
3752
3753 tree
3754 gfc_conv_array_initializer (tree type, gfc_expr * expr)
3755 {
3756   gfc_constructor *c;
3757   tree tmp;
3758   mpz_t maxval;
3759   gfc_se se;
3760   HOST_WIDE_INT hi;
3761   unsigned HOST_WIDE_INT lo;
3762   tree index, range;
3763   VEC(constructor_elt,gc) *v = NULL;
3764
3765   switch (expr->expr_type)
3766     {
3767     case EXPR_CONSTANT:
3768     case EXPR_STRUCTURE:
3769       /* A single scalar or derived type value.  Create an array with all
3770          elements equal to that value.  */
3771       gfc_init_se (&se, NULL);
3772       
3773       if (expr->expr_type == EXPR_CONSTANT)
3774         gfc_conv_constant (&se, expr);
3775       else
3776         gfc_conv_structure (&se, expr, 1);
3777
3778       tmp = TYPE_MAX_VALUE (TYPE_DOMAIN (type));
3779       gcc_assert (tmp && INTEGER_CST_P (tmp));
3780       hi = TREE_INT_CST_HIGH (tmp);
3781       lo = TREE_INT_CST_LOW (tmp);
3782       lo++;
3783       if (lo == 0)
3784         hi++;
3785       /* This will probably eat buckets of memory for large arrays.  */
3786       while (hi != 0 || lo != 0)
3787         {
3788           CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, se.expr);
3789           if (lo == 0)
3790             hi--;
3791           lo--;
3792         }
3793       break;
3794
3795     case EXPR_ARRAY:
3796       /* Create a vector of all the elements.  */
3797       for (c = expr->value.constructor; c; c = c->next)
3798         {
3799           if (c->iterator)
3800             {
3801               /* Problems occur when we get something like
3802                  integer :: a(lots) = (/(i, i=1,lots)/)  */
3803               /* TODO: Unexpanded array initializers.  */
3804               internal_error
3805                 ("Possible frontend bug: array constructor not expanded");
3806             }
3807           if (mpz_cmp_si (c->n.offset, 0) != 0)
3808             index = gfc_conv_mpz_to_tree (c->n.offset, gfc_index_integer_kind);
3809           else
3810             index = NULL_TREE;
3811           mpz_init (maxval);
3812           if (mpz_cmp_si (c->repeat, 0) != 0)
3813             {
3814               tree tmp1, tmp2;
3815
3816               mpz_set (maxval, c->repeat);
3817               mpz_add (maxval, c->n.offset, maxval);
3818               mpz_sub_ui (maxval, maxval, 1);
3819               tmp2 = gfc_conv_mpz_to_tree (maxval, gfc_index_integer_kind);
3820               if (mpz_cmp_si (c->n.offset, 0) != 0)
3821                 {
3822                   mpz_add_ui (maxval, c->n.offset, 1);
3823                   tmp1 = gfc_conv_mpz_to_tree (maxval, gfc_index_integer_kind);
3824                 }
3825               else
3826                 tmp1 = gfc_conv_mpz_to_tree (c->n.offset, gfc_index_integer_kind);
3827
3828               range = build2 (RANGE_EXPR, integer_type_node, tmp1, tmp2);
3829             }
3830           else
3831             range = NULL;
3832           mpz_clear (maxval);
3833
3834           gfc_init_se (&se, NULL);
3835           switch (c->expr->expr_type)
3836             {
3837             case EXPR_CONSTANT:
3838               gfc_conv_constant (&se, c->expr);
3839               if (range == NULL_TREE)
3840                 CONSTRUCTOR_APPEND_ELT (v, index, se.expr);
3841               else
3842                 {
3843                   if (index != NULL_TREE)
3844                     CONSTRUCTOR_APPEND_ELT (v, index, se.expr);
3845                   CONSTRUCTOR_APPEND_ELT (v, range, se.expr);
3846                 }
3847               break;
3848
3849             case EXPR_STRUCTURE:
3850               gfc_conv_structure (&se, c->expr, 1);
3851               CONSTRUCTOR_APPEND_ELT (v, index, se.expr);
3852               break;
3853
3854             default:
3855               gcc_unreachable ();
3856             }
3857         }
3858       break;
3859
3860     case EXPR_NULL:
3861       return gfc_build_null_descriptor (type);
3862
3863     default:
3864       gcc_unreachable ();
3865     }
3866
3867   /* Create a constructor from the list of elements.  */
3868   tmp = build_constructor (type, v);
3869   TREE_CONSTANT (tmp) = 1;
3870   TREE_INVARIANT (tmp) = 1;
3871   return tmp;
3872 }
3873
3874
3875 /* Generate code to evaluate non-constant array bounds.  Sets *poffset and
3876    returns the size (in elements) of the array.  */
3877
3878 static tree
3879 gfc_trans_array_bounds (tree type, gfc_symbol * sym, tree * poffset,
3880                         stmtblock_t * pblock)
3881 {
3882   gfc_array_spec *as;
3883   tree size;
3884   tree stride;
3885   tree offset;
3886   tree ubound;
3887   tree lbound;
3888   tree tmp;
3889   gfc_se se;
3890
3891   int dim;
3892
3893   as = sym->as;
3894
3895   size = gfc_index_one_node;
3896   offset = gfc_index_zero_node;
3897   for (dim = 0; dim < as->rank; dim++)
3898     {
3899       /* Evaluate non-constant array bound expressions.  */
3900       lbound = GFC_TYPE_ARRAY_LBOUND (type, dim);
3901       if (as->lower[dim] && !INTEGER_CST_P (lbound))
3902         {
3903           gfc_init_se (&se, NULL);
3904           gfc_conv_expr_type (&se, as->lower[dim], gfc_array_index_type);
3905           gfc_add_block_to_block (pblock, &se.pre);
3906           gfc_add_modify_expr (pblock, lbound, se.expr);
3907         }
3908       ubound = GFC_TYPE_ARRAY_UBOUND (type, dim);
3909       if (as->upper[dim] && !INTEGER_CST_P (ubound))
3910         {
3911           gfc_init_se (&se, NULL);
3912           gfc_conv_expr_type (&se, as->upper[dim], gfc_array_index_type);
3913           gfc_add_block_to_block (pblock, &se.pre);
3914           gfc_add_modify_expr (pblock, ubound, se.expr);
3915         }
3916       /* The offset of this dimension.  offset = offset - lbound * stride.  */
3917       tmp = fold_build2 (MULT_EXPR, gfc_array_index_type, lbound, size);
3918       offset = fold_build2 (MINUS_EXPR, gfc_array_index_type, offset, tmp);
3919
3920       /* The size of this dimension, and the stride of the next.  */
3921       if (dim + 1 < as->rank)
3922         stride = GFC_TYPE_ARRAY_STRIDE (type, dim + 1);
3923       else
3924         stride = GFC_TYPE_ARRAY_SIZE (type);
3925
3926       if (ubound != NULL_TREE && !(stride && INTEGER_CST_P (stride)))
3927         {
3928           /* Calculate stride = size * (ubound + 1 - lbound).  */
3929           tmp = fold_build2 (MINUS_EXPR, gfc_array_index_type,
3930                              gfc_index_one_node, lbound);
3931           tmp = fold_build2 (PLUS_EXPR, gfc_array_index_type, ubound, tmp);
3932           tmp = fold_build2 (MULT_EXPR, gfc_array_index_type, size, tmp);
3933           if (stride)
3934             gfc_add_modify_expr (pblock, stride, tmp);
3935           else
3936             stride = gfc_evaluate_now (tmp, pblock);
3937
3938           /* Make sure that negative size arrays are translated
3939              to being zero size.  */
3940           tmp = build2 (GE_EXPR, boolean_type_node,
3941                         stride, gfc_index_zero_node);
3942           tmp = build3 (COND_EXPR, gfc_array_index_type, tmp,
3943                         stride, gfc_index_zero_node);
3944           gfc_add_modify_expr (pblock, stride, tmp);
3945         }
3946
3947       size = stride;
3948     }
3949
3950   gfc_trans_vla_type_sizes (sym, pblock);
3951
3952   *poffset = offset;
3953   return size;
3954 }
3955
3956
3957 /* Generate code to initialize/allocate an array variable.  */
3958
3959 tree
3960 gfc_trans_auto_array_allocation (tree decl, gfc_symbol * sym, tree fnbody)
3961 {
3962   stmtblock_t block;
3963   tree type;
3964   tree tmp;
3965   tree size;
3966   tree offset;
3967   bool onstack;
3968
3969   gcc_assert (!(sym->attr.pointer || sym->attr.allocatable));
3970
3971   /* Do nothing for USEd variables.  */
3972   if (sym->attr.use_assoc)
3973     return fnbody;
3974
3975   type = TREE_TYPE (decl);
3976   gcc_assert (GFC_ARRAY_TYPE_P (type));
3977   onstack = TREE_CODE (type) != POINTER_TYPE;
3978
3979   gfc_start_block (&block);
3980
3981   /* Evaluate character string length.  */
3982   if (sym->ts.type == BT_CHARACTER
3983       && onstack && !INTEGER_CST_P (sym->ts.cl->backend_decl))
3984     {
3985       gfc_conv_string_length (sym->ts.cl, &block);
3986
3987       gfc_trans_vla_type_sizes (sym, &block);
3988
3989       /* Emit a DECL_EXPR for this variable, which will cause the
3990          gimplifier to allocate storage, and all that good stuff.  */
3991       tmp = build1 (DECL_EXPR, TREE_TYPE (decl), decl);
3992       gfc_add_expr_to_block (&block, tmp);
3993     }
3994
3995   if (onstack)
3996     {
3997       gfc_add_expr_to_block (&block, fnbody);
3998       return gfc_finish_block (&block);
3999     }
4000
4001   type = TREE_TYPE (type);
4002
4003   gcc_assert (!sym->attr.use_assoc);
4004   gcc_assert (!TREE_STATIC (decl));
4005   gcc_assert (!sym->module);
4006
4007   if (sym->ts.type == BT_CHARACTER
4008       && !INTEGER_CST_P (sym->ts.cl->backend_decl))
4009     gfc_conv_string_length (sym->ts.cl, &block);
4010
4011   size = gfc_trans_array_bounds (type, sym, &offset, &block);
4012
4013   /* Don't actually allocate space for Cray Pointees.  */
4014   if (sym->attr.cray_pointee)
4015     {
4016       if (TREE_CODE (GFC_TYPE_ARRAY_OFFSET (type)) == VAR_DECL)
4017         gfc_add_modify_expr (&block, GFC_TYPE_ARRAY_OFFSET (type), offset);
4018       gfc_add_expr_to_block (&block, fnbody);
4019       return gfc_finish_block (&block);
4020     }
4021
4022   /* The size is the number of elements in the array, so multiply by the
4023      size of an element to get the total size.  */
4024   tmp = TYPE_SIZE_UNIT (gfc_get_element_type (type));
4025   size = fold_build2 (MULT_EXPR, gfc_array_index_type, size,
4026                       fold_convert (gfc_array_index_type, tmp));
4027
4028   /* Allocate memory to hold the data.  */
4029   tmp = gfc_call_malloc (&block, TREE_TYPE (decl), size);
4030   gfc_add_modify_expr (&block, decl, tmp);
4031
4032   /* Set offset of the array.  */
4033   if (TREE_CODE (GFC_TYPE_ARRAY_OFFSET (type)) == VAR_DECL)
4034     gfc_add_modify_expr (&block, GFC_TYPE_ARRAY_OFFSET (type), offset);
4035
4036
4037   /* Automatic arrays should not have initializers.  */
4038   gcc_assert (!sym->value);
4039
4040   gfc_add_expr_to_block (&block, fnbody);
4041
4042   /* Free the temporary.  */
4043   tmp = gfc_call_free (convert (pvoid_type_node, decl));
4044   gfc_add_expr_to_block (&block, tmp);
4045
4046   return gfc_finish_block (&block);
4047 }
4048
4049
4050 /* Generate entry and exit code for g77 calling convention arrays.  */
4051
4052 tree
4053 gfc_trans_g77_array (gfc_symbol * sym, tree body)
4054 {
4055   tree parm;
4056   tree type;
4057   locus loc;
4058   tree offset;
4059   tree tmp;
4060   tree stmt;  
4061   stmtblock_t block;
4062
4063   gfc_get_backend_locus (&loc);
4064   gfc_set_backend_locus (&sym->declared_at);
4065
4066   /* Descriptor type.  */
4067   parm = sym->backend_decl;
4068   type = TREE_TYPE (parm);
4069   gcc_assert (GFC_ARRAY_TYPE_P (type));
4070
4071   gfc_start_block (&block);
4072
4073   if (sym->ts.type == BT_CHARACTER
4074       && TREE_CODE (sym->ts.cl->backend_decl) == VAR_DECL)
4075     gfc_conv_string_length (sym->ts.cl, &block);
4076
4077   /* Evaluate the bounds of the array.  */
4078   gfc_trans_array_bounds (type, sym, &offset, &block);
4079
4080   /* Set the offset.  */
4081   if (TREE_CODE (GFC_TYPE_ARRAY_OFFSET (type)) == VAR_DECL)
4082     gfc_add_modify_expr (&block, GFC_TYPE_ARRAY_OFFSET (type), offset);
4083
4084   /* Set the pointer itself if we aren't using the parameter directly.  */
4085   if (TREE_CODE (parm) != PARM_DECL)
4086     {
4087       tmp = convert (TREE_TYPE (parm), GFC_DECL_SAVED_DESCRIPTOR (parm));
4088       gfc_add_modify_expr (&block, parm, tmp);
4089     }
4090   stmt = gfc_finish_block (&block);
4091
4092   gfc_set_backend_locus (&loc);
4093
4094   gfc_start_block (&block);
4095
4096   /* Add the initialization code to the start of the function.  */
4097
4098   if (sym->attr.optional || sym->attr.not_always_present)
4099     {
4100       tmp = gfc_conv_expr_present (sym);
4101       stmt = build3_v (COND_EXPR, tmp, stmt, build_empty_stmt ());
4102     }
4103   
4104   gfc_add_expr_to_block (&block, stmt);
4105   gfc_add_expr_to_block (&block, body);
4106
4107   return gfc_finish_block (&block);
4108 }
4109
4110
4111 /* Modify the descriptor of an array parameter so that it has the
4112    correct lower bound.  Also move the upper bound accordingly.
4113    If the array is not packed, it will be copied into a temporary.
4114    For each dimension we set the new lower and upper bounds.  Then we copy the
4115    stride and calculate the offset for this dimension.  We also work out
4116    what the stride of a packed array would be, and see it the two match.
4117    If the array need repacking, we set the stride to the values we just
4118    calculated, recalculate the offset and copy the array data.
4119    Code is also added to copy the data back at the end of the function.
4120    */
4121
4122 tree
4123 gfc_trans_dummy_array_bias (gfc_symbol * sym, tree tmpdesc, tree body)
4124 {
4125   tree size;
4126   tree type;
4127   tree offset;
4128   locus loc;
4129   stmtblock_t block;
4130   stmtblock_t cleanup;
4131   tree lbound;
4132   tree ubound;
4133   tree dubound;
4134   tree dlbound;
4135   tree dumdesc;
4136   tree tmp;
4137   tree stmt;
4138   tree stride, stride2;
4139   tree stmt_packed;
4140   tree stmt_unpacked;
4141   tree partial;
4142   gfc_se se;
4143   int n;
4144   int checkparm;
4145   int no_repack;
4146   bool optional_arg;
4147
4148   /* Do nothing for pointer and allocatable arrays.  */
4149   if (sym->attr.pointer || sym->attr.allocatable)
4150     return body;
4151
4152   if (sym->attr.dummy && gfc_is_nodesc_array (sym))
4153     return gfc_trans_g77_array (sym, body);
4154
4155   gfc_get_backend_locus (&loc);
4156   gfc_set_backend_locus (&sym->declared_at);
4157
4158   /* Descriptor type.  */
4159   type = TREE_TYPE (tmpdesc);
4160   gcc_assert (GFC_ARRAY_TYPE_P (type));
4161   dumdesc = GFC_DECL_SAVED_DESCRIPTOR (tmpdesc);
4162   dumdesc = build_fold_indirect_ref (dumdesc);
4163   gfc_start_block (&block);
4164
4165   if (sym->ts.type == BT_CHARACTER
4166       && TREE_CODE (sym->ts.cl->backend_decl) == VAR_DECL)
4167     gfc_conv_string_length (sym->ts.cl, &block);
4168
4169   checkparm = (sym->as->type == AS_EXPLICIT && flag_bounds_check);
4170
4171   no_repack = !(GFC_DECL_PACKED_ARRAY (tmpdesc)
4172                 || GFC_DECL_PARTIAL_PACKED_ARRAY (tmpdesc));
4173
4174   if (GFC_DECL_PARTIAL_PACKED_ARRAY (tmpdesc))
4175     {
4176       /* For non-constant shape arrays we only check if the first dimension
4177          is contiguous.  Repacking higher dimensions wouldn't gain us
4178          anything as we still don't know the array stride.  */
4179       partial = gfc_create_var (boolean_type_node, "partial");
4180       TREE_USED (partial) = 1;
4181       tmp = gfc_conv_descriptor_stride (dumdesc, gfc_rank_cst[0]);
4182       tmp = fold_build2 (EQ_EXPR, boolean_type_node, tmp, gfc_index_one_node);
4183       gfc_add_modify_expr (&block, partial, tmp);
4184     }
4185   else
4186     {
4187       partial = NULL_TREE;
4188     }
4189
4190   /* The naming of stmt_unpacked and stmt_packed may be counter-intuitive
4191      here, however I think it does the right thing.  */
4192   if (no_repack)
4193     {
4194       /* Set the first stride.  */
4195       stride = gfc_conv_descriptor_stride (dumdesc, gfc_rank_cst[0]);
4196       stride = gfc_evaluate_now (stride, &block);
4197
4198       tmp = build2 (EQ_EXPR, boolean_type_node, stride, gfc_index_zero_node);
4199       tmp = build3 (COND_EXPR, gfc_array_index_type, tmp,
4200                     gfc_index_one_node, stride);
4201       stride = GFC_TYPE_ARRAY_STRIDE (type, 0);
4202       gfc_add_modify_expr (&block, stride, tmp);
4203
4204       /* Allow the user to disable array repacking.  */
4205       stmt_unpacked = NULL_TREE;
4206     }
4207   else
4208     {
4209       gcc_assert (integer_onep (GFC_TYPE_ARRAY_STRIDE (type, 0)));
4210       /* A library call to repack the array if necessary.  */
4211       tmp = GFC_DECL_SAVED_DESCRIPTOR (tmpdesc);
4212       stmt_unpacked = build_call_expr (gfor_fndecl_in_pack, 1, tmp);
4213
4214       stride = gfc_index_one_node;
4215     }
4216
4217   /* This is for the case where the array data is used directly without
4218      calling the repack function.  */
4219   if (no_repack || partial != NULL_TREE)
4220     stmt_packed = gfc_conv_descriptor_data_get (dumdesc);
4221   else
4222     stmt_packed = NULL_TREE;
4223
4224   /* Assign the data pointer.  */
4225   if (stmt_packed != NULL_TREE && stmt_unpacked != NULL_TREE)
4226     {
4227       /* Don't repack unknown shape arrays when the first stride is 1.  */
4228       tmp = build3 (COND_EXPR, TREE_TYPE (stmt_packed), partial,
4229                     stmt_packed, stmt_unpacked);
4230     }
4231   else
4232     tmp = stmt_packed != NULL_TREE ? stmt_packed : stmt_unpacked;
4233   gfc_add_modify_expr (&block, tmpdesc, fold_convert (type, tmp));
4234
4235   offset = gfc_index_zero_node;
4236   size = gfc_index_one_node;
4237
4238   /* Evaluate the bounds of the array.  */
4239   for (n = 0; n < sym->as->rank; n++)
4240     {
4241       if (checkparm || !sym->as->upper[n])
4242         {
4243           /* Get the bounds of the actual parameter.  */
4244           dubound = gfc_conv_descriptor_ubound (dumdesc, gfc_rank_cst[n]);
4245           dlbound = gfc_conv_descriptor_lbound (dumdesc, gfc_rank_cst[n]);
4246         }
4247       else
4248         {
4249           dubound = NULL_TREE;
4250           dlbound = NULL_TREE;
4251         }
4252
4253       lbound = GFC_TYPE_ARRAY_LBOUND (type, n);
4254       if (!INTEGER_CST_P (lbound))
4255         {
4256           gfc_init_se (&se, NULL);
4257           gfc_conv_expr_type (&se, sym->as->lower[n],
4258                               gfc_array_index_type);
4259           gfc_add_block_to_block (&block, &se.pre);
4260           gfc_add_modify_expr (&block, lbound, se.expr);
4261         }
4262
4263       ubound = GFC_TYPE_ARRAY_UBOUND (type, n);
4264       /* Set the desired upper bound.  */
4265       if (sym->as->upper[n])
4266         {
4267           /* We know what we want the upper bound to be.  */
4268           if (!INTEGER_CST_P (ubound))
4269             {
4270               gfc_init_se (&se, NULL);
4271               gfc_conv_expr_type (&se, sym->as->upper[n],
4272                                   gfc_array_index_type);
4273               gfc_add_block_to_block (&block, &se.pre);
4274               gfc_add_modify_expr (&block, ubound, se.expr);
4275             }
4276
4277           /* Check the sizes match.  */
4278           if (checkparm)
4279             {
4280               /* Check (ubound(a) - lbound(a) == ubound(b) - lbound(b)).  */
4281               char * msg;
4282
4283               tmp = fold_build2 (MINUS_EXPR, gfc_array_index_type,
4284                                  ubound, lbound);
4285               stride2 = build2 (MINUS_EXPR, gfc_array_index_type,
4286                                dubound, dlbound);
4287               tmp = fold_build2 (NE_EXPR, gfc_array_index_type, tmp, stride2);
4288               asprintf (&msg, "%s for dimension %d of array '%s'",
4289                         gfc_msg_bounds, n+1, sym->name);
4290               gfc_trans_runtime_check (tmp, &block, &loc, msg);
4291               gfc_free (msg);
4292             }
4293         }
4294       else
4295         {
4296           /* For assumed shape arrays move the upper bound by the same amount
4297              as the lower bound.  */
4298           tmp = build2 (MINUS_EXPR, gfc_array_index_type, dubound, dlbound);
4299           tmp = fold_build2 (PLUS_EXPR, gfc_array_index_type, tmp, lbound);
4300           gfc_add_modify_expr (&block, ubound, tmp);
4301         }
4302       /* The offset of this dimension.  offset = offset - lbound * stride.  */
4303       tmp = fold_build2 (MULT_EXPR, gfc_array_index_type, lbound, stride);
4304       offset = fold_build2 (MINUS_EXPR, gfc_array_index_type, offset, tmp);
4305
4306       /* The size of this dimension, and the stride of the next.  */
4307       if (n + 1 < sym->as->rank)
4308         {
4309           stride = GFC_TYPE_ARRAY_STRIDE (type, n + 1);
4310
4311           if (no_repack || partial != NULL_TREE)
4312             {
4313               stmt_unpacked =
4314                 gfc_conv_descriptor_stride (dumdesc, gfc_rank_cst[n+1]);
4315             }
4316
4317           /* Figure out the stride if not a known constant.  */
4318           if (!INTEGER_CST_P (stride))
4319             {
4320               if (no_repack)
4321                 stmt_packed = NULL_TREE;
4322               else
4323                 {
4324                   /* Calculate stride = size * (ubound + 1 - lbound).  */
4325                   tmp = fold_build2 (MINUS_EXPR, gfc_array_index_type,
4326                                      gfc_index_one_node, lbound);
4327                   tmp = fold_build2 (PLUS_EXPR, gfc_array_index_type,
4328                                      ubound, tmp);
4329                   size = fold_build2 (MULT_EXPR, gfc_array_index_type,
4330                                       size, tmp);
4331                   stmt_packed = size;
4332                 }
4333
4334               /* Assign the stride.  */
4335               if (stmt_packed != NULL_TREE && stmt_unpacked != NULL_TREE)
4336                 tmp = build3 (COND_EXPR, gfc_array_index_type, partial,
4337                               stmt_unpacked, stmt_packed);
4338               else
4339                 tmp = (stmt_packed != NULL_TREE) ? stmt_packed : stmt_unpacked;
4340               gfc_add_modify_expr (&block, stride, tmp);
4341             }
4342         }
4343       else
4344         {
4345           stride = GFC_TYPE_ARRAY_SIZE (type);
4346
4347           if (stride && !INTEGER_CST_P (stride))
4348             {
4349               /* Calculate size = stride * (ubound + 1 - lbound).  */
4350               tmp = fold_build2 (MINUS_EXPR, gfc_array_index_type,
4351                                  gfc_index_one_node, lbound);
4352               tmp = fold_build2 (PLUS_EXPR, gfc_array_index_type,
4353                                  ubound, tmp);
4354               tmp = fold_build2 (MULT_EXPR, gfc_array_index_type,
4355                                  GFC_TYPE_ARRAY_STRIDE (type, n), tmp);
4356               gfc_add_modify_expr (&block, stride, tmp);
4357             }
4358         }
4359     }
4360
4361   /* Set the offset.  */
4362   if (TREE_CODE (GFC_TYPE_ARRAY_OFFSET (type)) == VAR_DECL)
4363     gfc_add_modify_expr (&block, GFC_TYPE_ARRAY_OFFSET (type), offset);
4364
4365   gfc_trans_vla_type_sizes (sym, &block);
4366
4367   stmt = gfc_finish_block (&block);
4368
4369   gfc_start_block (&block);
4370
4371   /* Only do the entry/initialization code if the arg is present.  */
4372   dumdesc = GFC_DECL_SAVED_DESCRIPTOR (tmpdesc);
4373   optional_arg = (sym->attr.optional
4374                   || (sym->ns->proc_name->attr.entry_master
4375                       && sym->attr.dummy));
4376   if (optional_arg)
4377     {
4378       tmp = gfc_conv_expr_present (sym);
4379       stmt = build3_v (COND_EXPR, tmp, stmt, build_empty_stmt ());
4380     }
4381   gfc_add_expr_to_block (&block, stmt);
4382
4383   /* Add the main function body.  */
4384   gfc_add_expr_to_block (&block, body);
4385
4386   /* Cleanup code.  */
4387   if (!no_repack)
4388     {
4389       gfc_start_block (&cleanup);
4390       
4391       if (sym->attr.intent != INTENT_IN)
4392         {
4393           /* Copy the data back.  */
4394           tmp = build_call_expr (gfor_fndecl_in_unpack, 2, dumdesc, tmpdesc);
4395           gfc_add_expr_to_block (&cleanup, tmp);
4396         }
4397
4398       /* Free the temporary.  */
4399       tmp = gfc_call_free (tmpdesc);
4400       gfc_add_expr_to_block (&cleanup, tmp);
4401
4402       stmt = gfc_finish_block (&cleanup);
4403         
4404       /* Only do the cleanup if the array was repacked.  */
4405       tmp = build_fold_indirect_ref (dumdesc);
4406       tmp = gfc_conv_descriptor_data_get (tmp);
4407       tmp = build2 (NE_EXPR, boolean_type_node, tmp, tmpdesc);
4408       stmt = build3_v (COND_EXPR, tmp, stmt, build_empty_stmt ());
4409
4410       if (optional_arg)
4411         {
4412           tmp = gfc_conv_expr_present (sym);
4413           stmt = build3_v (COND_EXPR, tmp, stmt, build_empty_stmt ());
4414         }
4415       gfc_add_expr_to_block (&block, stmt);
4416     }
4417   /* We don't need to free any memory allocated by internal_pack as it will
4418      be freed at the end of the function by pop_context.  */
4419   return gfc_finish_block (&block);
4420 }
4421
4422
4423 /* Calculate the overall offset, including subreferences.  */
4424 static void
4425 gfc_get_dataptr_offset (stmtblock_t *block, tree parm, tree desc, tree offset,
4426                         bool subref, gfc_expr *expr)
4427 {
4428   tree tmp;
4429   tree field;
4430   tree stride;
4431   tree index;
4432   gfc_ref *ref;
4433   gfc_se start;
4434   int n;
4435
4436   /* If offset is NULL and this is not a subreferenced array, there is
4437      nothing to do.  */
4438   if (offset == NULL_TREE)
4439     {
4440       if (subref)
4441         offset = gfc_index_zero_node;
4442       else
4443         return;
4444     }
4445
4446   tmp = gfc_conv_array_data (desc);
4447   tmp = build_fold_indirect_ref (tmp);
4448   tmp = gfc_build_array_ref (tmp, offset, NULL);
4449
4450   /* Offset the data pointer for pointer assignments from arrays with
4451      subreferences; eg. my_integer => my_type(:)%integer_component.  */
4452   if (subref)
4453     {
4454       /* Go past the array reference.  */
4455       for (ref = expr->ref; ref; ref = ref->next)
4456         if (ref->type == REF_ARRAY &&
4457               ref->u.ar.type != AR_ELEMENT)
4458           {
4459             ref = ref->next;
4460             break;
4461           }
4462
4463       /* Calculate the offset for each subsequent subreference.  */
4464       for (; ref; ref = ref->next)
4465         {
4466           switch (ref->type)
4467             {
4468             case REF_COMPONENT:
4469               field = ref->u.c.component->backend_decl;
4470               gcc_assert (field && TREE_CODE (field) == FIELD_DECL);
4471               tmp = build3 (COMPONENT_REF, TREE_TYPE (field), tmp, field, NULL_TREE);
4472               break;
4473
4474             case REF_SUBSTRING:
4475               gcc_assert (TREE_CODE (TREE_TYPE (tmp)) == ARRAY_TYPE);
4476               gfc_init_se (&start, NULL);
4477               gfc_conv_expr_type (&start, ref->u.ss.start, gfc_charlen_type_node);
4478               gfc_add_block_to_block (block, &start.pre);
4479               tmp = gfc_build_array_ref (tmp, start.expr, NULL);
4480               break;
4481
4482             case REF_ARRAY:
4483               gcc_assert (TREE_CODE (TREE_TYPE (tmp)) == ARRAY_TYPE
4484                             && ref->u.ar.type == AR_ELEMENT);
4485
4486               /* TODO - Add bounds checking.  */
4487               stride = gfc_index_one_node;
4488               index = gfc_index_zero_node;
4489               for (n = 0; n < ref->u.ar.dimen; n++)
4490                 {
4491                   tree itmp;
4492                   tree jtmp;
4493
4494                   /* Update the index.  */
4495                   gfc_init_se (&start, NULL);
4496                   gfc_conv_expr_type (&start, ref->u.ar.start[n], gfc_array_index_type);
4497                   itmp = gfc_evaluate_now (start.expr, block);
4498                   gfc_init_se (&start, NULL);
4499                   gfc_conv_expr_type (&start, ref->u.ar.as->lower[n], gfc_array_index_type);
4500                   jtmp = gfc_evaluate_now (start.expr, block);
4501                   itmp = fold_build2 (MINUS_EXPR, gfc_array_index_type, itmp, jtmp);
4502                   itmp = fold_build2 (MULT_EXPR, gfc_array_index_type, itmp, stride);
4503                   index = fold_build2 (PLUS_EXPR, gfc_array_index_type, itmp, index);
4504                   index = gfc_evaluate_now (index, block);
4505
4506                   /* Update the stride.  */
4507                   gfc_init_se (&start, NULL);
4508                   gfc_conv_expr_type (&start, ref->u.ar.as->upper[n], gfc_array_index_type);
4509                   itmp =  fold_build2 (MINUS_EXPR, gfc_array_index_type, start.expr, jtmp);
4510                   itmp =  fold_build2 (PLUS_EXPR, gfc_array_index_type,
4511                                        gfc_index_one_node, itmp);
4512                   stride =  fold_build2 (MULT_EXPR, gfc_array_index_type, stride, itmp);
4513                   stride = gfc_evaluate_now (stride, block);
4514                 }
4515
4516               /* Apply the index to obtain the array element.  */
4517               tmp = gfc_build_array_ref (tmp, index, NULL);
4518               break;
4519
4520             default:
4521               gcc_unreachable ();
4522               break;
4523             }
4524         }
4525     }
4526
4527   /* Set the target data pointer.  */
4528   offset = gfc_build_addr_expr (gfc_array_dataptr_type (desc), tmp);
4529   gfc_conv_descriptor_data_set (block, parm, offset);
4530 }
4531
4532
4533 /* gfc_conv_expr_descriptor needs the character length of elemental
4534    functions before the function is called so that the size of the
4535    temporary can be obtained.  The only way to do this is to convert
4536    the expression, mapping onto the actual arguments.  */
4537 static void
4538 get_elemental_fcn_charlen (gfc_expr *expr, gfc_se *se)
4539 {
4540   gfc_interface_mapping mapping;
4541   gfc_formal_arglist *formal;
4542   gfc_actual_arglist *arg;
4543   gfc_se tse;
4544
4545   formal = expr->symtree->n.sym->formal;
4546   arg = expr->value.function.actual;
4547   gfc_init_interface_mapping (&mapping);
4548
4549   /* Set se = NULL in the calls to the interface mapping, to supress any
4550      backend stuff.  */
4551   for (; arg != NULL; arg = arg->next, formal = formal ? formal->next : NULL)
4552     {
4553       if (!arg->expr)
4554         continue;
4555       if (formal->sym)
4556         gfc_add_interface_mapping (&mapping, formal->sym, NULL, arg->expr);
4557     }
4558
4559   gfc_init_se (&tse, NULL);
4560
4561   /* Build the expression for the character length and convert it.  */
4562   gfc_apply_interface_mapping (&mapping, &tse, expr->ts.cl->length);
4563
4564   gfc_add_block_to_block (&se->pre, &tse.pre);
4565   gfc_add_block_to_block (&se->post, &tse.post);
4566   tse.expr = fold_convert (gfc_charlen_type_node, tse.expr);
4567   tse.expr = fold_build2 (MAX_EXPR, gfc_charlen_type_node, tse.expr,
4568                           build_int_cst (gfc_charlen_type_node, 0));
4569   expr->ts.cl->backend_decl = tse.expr;
4570   gfc_free_interface_mapping (&mapping);
4571 }
4572
4573
4574 /* Convert an array for passing as an actual argument.  Expressions and
4575    vector subscripts are evaluated and stored in a temporary, which is then
4576    passed.  For whole arrays the descriptor is passed.  For array sections
4577    a modified copy of the descriptor is passed, but using the original data.
4578
4579    This function is also used for array pointer assignments, and there
4580    are three cases:
4581
4582      - se->want_pointer && !se->direct_byref
4583          EXPR is an actual argument.  On exit, se->expr contains a
4584          pointer to the array descriptor.
4585
4586      - !se->want_pointer && !se->direct_byref
4587          EXPR is an actual argument to an intrinsic function or the
4588          left-hand side of a pointer assignment.  On exit, se->expr
4589          contains the descriptor for EXPR.
4590
4591      - !se->want_pointer && se->direct_byref
4592          EXPR is the right-hand side of a pointer assignment and
4593          se->expr is the descriptor for the previously-evaluated
4594          left-hand side.  The function creates an assignment from
4595          EXPR to se->expr.  */
4596
4597 void
4598 gfc_conv_expr_descriptor (gfc_se * se, gfc_expr * expr, gfc_ss * ss)
4599 {
4600   gfc_loopinfo loop;
4601   gfc_ss *secss;
4602   gfc_ss_info *info;
4603   int need_tmp;
4604   int n;
4605   tree tmp;
4606   tree desc;
4607   stmtblock_t block;
4608   tree start;
4609   tree offset;
4610   int full;
4611   bool subref_array_target = false;
4612
4613   gcc_assert (ss != gfc_ss_terminator);
4614
4615   /* Special case things we know we can pass easily.  */
4616   switch (expr->expr_type)
4617     {
4618     case EXPR_VARIABLE:
4619       /* If we have a linear array section, we can pass it directly.
4620          Otherwise we need to copy it into a temporary.  */
4621
4622       /* Find the SS for the array section.  */
4623       secss = ss;
4624       while (secss != gfc_ss_terminator && secss->type != GFC_SS_SECTION)
4625         secss = secss->next;
4626
4627       gcc_assert (secss != gfc_ss_terminator);
4628       info = &secss->data.info;
4629
4630       /* Get the descriptor for the array.  */
4631       gfc_conv_ss_descriptor (&se->pre, secss, 0);
4632       desc = info->descriptor;
4633
4634       subref_array_target = se->direct_byref && is_subref_array (expr);
4635       need_tmp = gfc_ref_needs_temporary_p (expr->ref)
4636                         && !subref_array_target;
4637
4638       if (need_tmp)
4639         full = 0;
4640       else if (GFC_ARRAY_TYPE_P (TREE_TYPE (desc)))
4641         {
4642           /* Create a new descriptor if the array doesn't have one.  */
4643           full = 0;
4644         }
4645       else if (info->ref->u.ar.type == AR_FULL)
4646         full = 1;
4647       else if (se->direct_byref)
4648         full = 0;
4649       else
4650         full = gfc_full_array_ref_p (info->ref);
4651
4652       if (full)
4653         {
4654           if (se->direct_byref)
4655             {
4656               /* Copy the descriptor for pointer assignments.  */
4657               gfc_add_modify_expr (&se->pre, se->expr, desc);
4658
4659               /* Add any offsets from subreferences.  */
4660               gfc_get_dataptr_offset (&se->pre, se->expr, desc, NULL_TREE,
4661                                       subref_array_target, expr);
4662             }
4663           else if (se->want_pointer)
4664             {
4665               /* We pass full arrays directly.  This means that pointers and
4666                  allocatable arrays should also work.  */
4667               se->expr = build_fold_addr_expr (desc);
4668             }
4669           else
4670             {
4671               se->expr = desc;
4672             }
4673
4674           if (expr->ts.type == BT_CHARACTER)
4675             se->string_length = gfc_get_expr_charlen (expr);
4676
4677           return;
4678         }
4679       break;
4680       
4681     case EXPR_FUNCTION:
4682       /* A transformational function return value will be a temporary
4683          array descriptor.  We still need to go through the scalarizer
4684          to create the descriptor.  Elemental functions ar handled as
4685          arbitrary expressions, i.e. copy to a temporary.  */
4686       secss = ss;
4687       /* Look for the SS for this function.  */
4688       while (secss != gfc_ss_terminator
4689              && (secss->type != GFC_SS_FUNCTION || secss->expr != expr))
4690         secss = secss->next;
4691
4692       if (se->direct_byref)
4693         {
4694           gcc_assert (secss != gfc_ss_terminator);
4695
4696           /* For pointer assignments pass the descriptor directly.  */
4697           se->ss = secss;
4698           se->expr = build_fold_addr_expr (se->expr);
4699           gfc_conv_expr (se, expr);
4700           return;
4701         }
4702
4703       if (secss == gfc_ss_terminator)
4704         {
4705           /* Elemental function.  */
4706           need_tmp = 1;
4707           if (expr->ts.type == BT_CHARACTER
4708                 && expr->ts.cl->length->expr_type != EXPR_CONSTANT)
4709             get_elemental_fcn_charlen (expr, se);
4710
4711           info = NULL;
4712         }
4713       else
4714         {
4715           /* Transformational function.  */
4716           info = &secss->data.info;
4717           need_tmp = 0;
4718         }
4719       break;
4720
4721     case EXPR_ARRAY:
4722       /* Constant array constructors don't need a temporary.  */
4723       if (ss->type == GFC_SS_CONSTRUCTOR
4724           && expr->ts.type != BT_CHARACTER
4725           && gfc_constant_array_constructor_p (expr->value.constructor))
4726         {
4727           need_tmp = 0;
4728           info = &ss->data.info;
4729           secss = ss;
4730         }
4731       else
4732         {
4733           need_tmp = 1;
4734           secss = NULL;
4735           info = NULL;
4736         }
4737       break;
4738
4739     default:
4740       /* Something complicated.  Copy it into a temporary.  */
4741       need_tmp = 1;
4742       secss = NULL;
4743       info = NULL;
4744       break;
4745     }
4746
4747
4748   gfc_init_loopinfo (&loop);
4749
4750   /* Associate the SS with the loop.  */
4751   gfc_add_ss_to_loop (&loop, ss);
4752
4753   /* Tell the scalarizer not to bother creating loop variables, etc.  */
4754   if (!need_tmp)
4755     loop.array_parameter = 1;
4756   else
4757     /* The right-hand side of a pointer assignment mustn't use a temporary.  */
4758     gcc_assert (!se->direct_byref);
4759
4760   /* Setup the scalarizing loops and bounds.  */
4761   gfc_conv_ss_startstride (&loop);
4762
4763   if (need_tmp)
4764     {
4765       /* Tell the scalarizer to make a temporary.  */
4766       loop.temp_ss = gfc_get_ss ();
4767       loop.temp_ss->type = GFC_SS_TEMP;
4768       loop.temp_ss->next = gfc_ss_terminator;
4769
4770       if (expr->ts.type == BT_CHARACTER && !expr->ts.cl->backend_decl)
4771         gfc_conv_string_length (expr->ts.cl, &se->pre);
4772
4773       loop.temp_ss->data.temp.type = gfc_typenode_for_spec (&expr->ts);
4774
4775       if (expr->ts.type == BT_CHARACTER)
4776         loop.temp_ss->string_length = expr->ts.cl->backend_decl;
4777       else
4778         loop.temp_ss->string_length = NULL;
4779
4780       se->string_length = loop.temp_ss->string_length;
4781       loop.temp_ss->data.temp.dimen = loop.dimen;
4782       gfc_add_ss_to_loop (&loop, loop.temp_ss);
4783     }
4784
4785   gfc_conv_loop_setup (&loop);
4786
4787   if (need_tmp)
4788     {
4789       /* Copy into a temporary and pass that.  We don't need to copy the data
4790          back because expressions and vector subscripts must be INTENT_IN.  */
4791       /* TODO: Optimize passing function return values.  */
4792       gfc_se lse;
4793       gfc_se rse;
4794
4795       /* Start the copying loops.  */
4796       gfc_mark_ss_chain_used (loop.temp_ss, 1);
4797       gfc_mark_ss_chain_used (ss, 1);
4798       gfc_start_scalarized_body (&loop, &block);
4799
4800       /* Copy each data element.  */
4801       gfc_init_se (&lse, NULL);
4802       gfc_copy_loopinfo_to_se (&lse, &loop);
4803       gfc_init_se (&rse, NULL);
4804       gfc_copy_loopinfo_to_se (&rse, &loop);
4805
4806       lse.ss = loop.temp_ss;
4807       rse.ss = ss;
4808
4809       gfc_conv_scalarized_array_ref (&lse, NULL);
4810       if (expr->ts.type == BT_CHARACTER)
4811         {
4812           gfc_conv_expr (&rse, expr);
4813           if (POINTER_TYPE_P (TREE_TYPE (rse.expr)))
4814             rse.expr = build_fold_indirect_ref (rse.expr);
4815         }
4816       else
4817         gfc_conv_expr_val (&rse, expr);
4818
4819       gfc_add_block_to_block (&block, &rse.pre);
4820       gfc_add_block_to_block (&block, &lse.pre);
4821
4822       lse.string_length = rse.string_length;
4823       tmp = gfc_trans_scalar_assign (&lse, &rse, expr->ts, true,
4824                                      expr->expr_type == EXPR_VARIABLE);
4825       gfc_add_expr_to_block (&block, tmp);
4826
4827       /* Finish the copying loops.  */
4828       gfc_trans_scalarizing_loops (&loop, &block);
4829
4830       desc = loop.temp_ss->data.info.descriptor;
4831
4832       gcc_assert (is_gimple_lvalue (desc));
4833     }
4834   else if (expr->expr_type == EXPR_FUNCTION)
4835     {
4836       desc = info->descriptor;
4837       se->string_length = ss->string_length;
4838     }
4839   else
4840     {
4841       /* We pass sections without copying to a temporary.  Make a new
4842          descriptor and point it at the section we want.  The loop variable
4843          limits will be the limits of the section.
4844          A function may decide to repack the array to speed up access, but
4845          we're not bothered about that here.  */
4846       int dim, ndim;
4847       tree parm;
4848       tree parmtype;
4849       tree stride;
4850       tree from;
4851       tree to;
4852       tree base;
4853
4854       /* Set the string_length for a character array.  */
4855       if (expr->ts.type == BT_CHARACTER)
4856         se->string_length =  gfc_get_expr_charlen (expr);
4857
4858       desc = info->descriptor;
4859       gcc_assert (secss && secss != gfc_ss_terminator);
4860       if (se->direct_byref)
4861         {
4862           /* For pointer assignments we fill in the destination.  */
4863           parm = se->expr;
4864           parmtype = TREE_TYPE (parm);
4865         }
4866       else
4867         {
4868           /* Otherwise make a new one.  */
4869           parmtype = gfc_get_element_type (TREE_TYPE (desc));
4870           parmtype = gfc_get_array_type_bounds (parmtype, loop.dimen,
4871                                                 loop.from, loop.to, 0,
4872                                                 GFC_ARRAY_UNKNOWN);
4873           parm = gfc_create_var (parmtype, "parm");
4874         }
4875
4876       offset = gfc_index_zero_node;
4877       dim = 0;
4878
4879       /* The following can be somewhat confusing.  We have two
4880          descriptors, a new one and the original array.
4881          {parm, parmtype, dim} refer to the new one.
4882          {desc, type, n, secss, loop} refer to the original, which maybe
4883          a descriptorless array.
4884          The bounds of the scalarization are the bounds of the section.
4885          We don't have to worry about numeric overflows when calculating
4886          the offsets because all elements are within the array data.  */
4887
4888       /* Set the dtype.  */
4889       tmp = gfc_conv_descriptor_dtype (parm);
4890       gfc_add_modify_expr (&loop.pre, tmp, gfc_get_dtype (parmtype));
4891
4892       /* Set offset for assignments to pointer only to zero if it is not
4893          the full array.  */
4894       if (se->direct_byref
4895           && info->ref && info->ref->u.ar.type != AR_FULL)
4896         base = gfc_index_zero_node;
4897       else if (GFC_ARRAY_TYPE_P (TREE_TYPE (desc)))
4898         base = gfc_evaluate_now (gfc_conv_array_offset (desc), &loop.pre);
4899       else
4900         base = NULL_TREE;
4901
4902       ndim = info->ref ? info->ref->u.ar.dimen : info->dimen;
4903       for (n = 0; n < ndim; n++)
4904         {
4905           stride = gfc_conv_array_stride (desc, n);
4906
4907           /* Work out the offset.  */
4908           if (info->ref
4909               && info->ref->u.ar.dimen_type[n] == DIMEN_ELEMENT)
4910             {
4911               gcc_assert (info->subscript[n]
4912                       && info->subscript[n]->type == GFC_SS_SCALAR);
4913               start = info->subscript[n]->data.scalar.expr;
4914             }
4915           else
4916             {
4917               /* Check we haven't somehow got out of sync.  */
4918               gcc_assert (info->dim[dim] == n);
4919
4920               /* Evaluate and remember the start of the section.  */
4921               start = info->start[dim];
4922               stride = gfc_evaluate_now (stride, &loop.pre);
4923             }
4924
4925           tmp = gfc_conv_array_lbound (desc, n);
4926           tmp = fold_build2 (MINUS_EXPR, TREE_TYPE (tmp), start, tmp);
4927
4928           tmp = fold_build2 (MULT_EXPR, TREE_TYPE (tmp), tmp, stride);
4929           offset = fold_build2 (PLUS_EXPR, TREE_TYPE (tmp), offset, tmp);
4930
4931           if (info->ref
4932               && info->ref->u.ar.dimen_type[n] == DIMEN_ELEMENT)
4933             {
4934               /* For elemental dimensions, we only need the offset.  */
4935               continue;
4936             }
4937
4938           /* Vector subscripts need copying and are handled elsewhere.  */
4939           if (info->ref)
4940             gcc_assert (info->ref->u.ar.dimen_type[n] == DIMEN_RANGE);
4941
4942           /* Set the new lower bound.  */
4943           from = loop.from[dim];
4944           to = loop.to[dim];
4945
4946           /* If we have an array section or are assigning make sure that
4947              the lower bound is 1.  References to the full
4948              array should otherwise keep the original bounds.  */
4949           if ((!info->ref
4950                   || info->ref->u.ar.type != AR_FULL)
4951               && !integer_onep (from))
4952             {
4953               tmp = fold_build2 (MINUS_EXPR, gfc_array_index_type,
4954                                  gfc_index_one_node, from);
4955               to = fold_build2 (PLUS_EXPR, gfc_array_index_type, to, tmp);
4956               from = gfc_index_one_node;
4957             }
4958           tmp = gfc_conv_descriptor_lbound (parm, gfc_rank_cst[dim]);
4959           gfc_add_modify_expr (&loop.pre, tmp, from);
4960
4961           /* Set the new upper bound.  */
4962           tmp = gfc_conv_descriptor_ubound (parm, gfc_rank_cst[dim]);
4963           gfc_add_modify_expr (&loop.pre, tmp, to);
4964
4965           /* Multiply the stride by the section stride to get the
4966              total stride.  */
4967           stride = fold_build2 (MULT_EXPR, gfc_array_index_type,
4968                                 stride, info->stride[dim]);
4969
4970           if (se->direct_byref && info->ref && info->ref->u.ar.type != AR_FULL)
4971             {
4972               base = fold_build2 (MINUS_EXPR, TREE_TYPE (base),
4973                                   base, stride);
4974             }
4975           else if (GFC_ARRAY_TYPE_P (TREE_TYPE (desc)))
4976             {
4977               tmp = gfc_conv_array_lbound (desc, n);
4978               tmp = fold_build2 (MINUS_EXPR, TREE_TYPE (base),
4979                                  tmp, loop.from[dim]);
4980               tmp = fold_build2 (MULT_EXPR, TREE_TYPE (base),
4981                                  tmp, gfc_conv_array_stride (desc, n));
4982               base = fold_build2 (PLUS_EXPR, TREE_TYPE (base),
4983                                   tmp, base);
4984             }
4985
4986           /* Store the new stride.  */
4987           tmp = gfc_conv_descriptor_stride (parm, gfc_rank_cst[dim]);
4988           gfc_add_modify_expr (&loop.pre, tmp, stride);
4989
4990           dim++;
4991         }
4992
4993       if (se->data_not_needed)
4994         gfc_conv_descriptor_data_set (&loop.pre, parm, gfc_index_zero_node);
4995       else
4996         /* Point the data pointer at the first element in the section.  */
4997         gfc_get_dataptr_offset (&loop.pre, parm, desc, offset,
4998                                 subref_array_target, expr);
4999
5000       if ((se->direct_byref || GFC_ARRAY_TYPE_P (TREE_TYPE (desc)))
5001           && !se->data_not_needed)
5002         {
5003           /* Set the offset.  */
5004           tmp = gfc_conv_descriptor_offset (parm);
5005           gfc_add_modify_expr (&loop.pre, tmp, base);
5006         }
5007       else
5008         {
5009           /* Only the callee knows what the correct offset it, so just set
5010              it to zero here.  */
5011           tmp = gfc_conv_descriptor_offset (parm);
5012           gfc_add_modify_expr (&loop.pre, tmp, gfc_index_zero_node);
5013         }
5014       desc = parm;
5015     }
5016
5017   if (!se->direct_byref)
5018     {
5019       /* Get a pointer to the new descriptor.  */
5020       if (se->want_pointer)
5021         se->expr = build_fold_addr_expr (desc);
5022       else
5023         se->expr = desc;
5024     }
5025
5026   gfc_add_block_to_block (&se->pre, &loop.pre);
5027   gfc_add_block_to_block (&se->post, &loop.post);
5028
5029   /* Cleanup the scalarizer.  */
5030   gfc_cleanup_loop (&loop);
5031 }
5032
5033
5034 /* Convert an array for passing as an actual parameter.  */
5035 /* TODO: Optimize passing g77 arrays.  */
5036
5037 void
5038 gfc_conv_array_parameter (gfc_se * se, gfc_expr * expr, gfc_ss * ss, int g77)
5039 {
5040   tree ptr;
5041   tree desc;
5042   tree tmp = NULL_TREE;
5043   tree stmt;
5044   tree parent = DECL_CONTEXT (current_function_decl);
5045   bool full_array_var, this_array_result;
5046   gfc_symbol *sym;
5047   stmtblock_t block;
5048
5049   full_array_var = (expr->expr_type == EXPR_VARIABLE
5050                       && expr->ref->u.ar.type == AR_FULL);
5051   sym = full_array_var ? expr->symtree->n.sym : NULL;
5052
5053   if (expr->expr_type == EXPR_ARRAY && expr->ts.type == BT_CHARACTER)
5054     {
5055       get_array_ctor_strlen (&se->pre, expr->value.constructor, &tmp);
5056       expr->ts.cl->backend_decl = tmp;
5057       se->string_length = tmp;
5058     }
5059
5060   /* Is this the result of the enclosing procedure?  */
5061   this_array_result = (full_array_var && sym->attr.flavor == FL_PROCEDURE);
5062   if (this_array_result
5063         && (sym->backend_decl != current_function_decl)
5064         && (sym->backend_decl != parent))
5065     this_array_result = false;
5066
5067   /* Passing address of the array if it is not pointer or assumed-shape.  */
5068   if (full_array_var && g77 && !this_array_result)
5069     {
5070       tmp = gfc_get_symbol_decl (sym);
5071
5072       if (sym->ts.type == BT_CHARACTER)
5073         se->string_length = sym->ts.cl->backend_decl;
5074       if (!sym->attr.pointer && sym->as->type != AS_ASSUMED_SHAPE 
5075           && !sym->attr.allocatable)
5076         {
5077           /* Some variables are declared directly, others are declared as
5078              pointers and allocated on the heap.  */
5079           if (sym->attr.dummy || POINTER_TYPE_P (TREE_TYPE (tmp)))
5080             se->expr = tmp;
5081           else
5082             se->expr = build_fold_addr_expr (tmp);
5083           return;
5084         }
5085       if (sym->attr.allocatable)
5086         {
5087           if (sym->attr.dummy || sym->attr.result)
5088             {
5089               gfc_conv_expr_descriptor (se, expr, ss);
5090               se->expr = gfc_conv_array_data (se->expr);
5091             }
5092           else
5093             se->expr = gfc_conv_array_data (tmp);
5094           return;
5095         }
5096     }
5097
5098   if (this_array_result)
5099     {
5100       /* Result of the enclosing function.  */
5101       gfc_conv_expr_descriptor (se, expr, ss);
5102       se->expr = build_fold_addr_expr (se->expr);
5103
5104       if (g77 && TREE_TYPE (TREE_TYPE (se->expr)) != NULL_TREE
5105               && GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (TREE_TYPE (se->expr))))
5106         se->expr = gfc_conv_array_data (build_fold_indirect_ref (se->expr));
5107
5108       return;
5109     }
5110   else
5111     {
5112       /* Every other type of array.  */
5113       se->want_pointer = 1;
5114       gfc_conv_expr_descriptor (se, expr, ss);
5115     }
5116
5117
5118   /* Deallocate the allocatable components of structures that are
5119      not variable.  */
5120   if (expr->ts.type == BT_DERIVED
5121         && expr->ts.derived->attr.alloc_comp
5122         && expr->expr_type != EXPR_VARIABLE)
5123     {
5124       tmp = build_fold_indirect_ref (se->expr);
5125       tmp = gfc_deallocate_alloc_comp (expr->ts.derived, tmp, expr->rank);
5126       gfc_add_expr_to_block (&se->post, tmp);
5127     }
5128
5129   if (g77)
5130     {
5131       desc = se->expr;
5132       /* Repack the array.  */
5133       ptr = build_call_expr (gfor_fndecl_in_pack, 1, desc);
5134       ptr = gfc_evaluate_now (ptr, &se->pre);
5135       se->expr = ptr;
5136
5137       gfc_start_block (&block);
5138
5139       /* Copy the data back.  */
5140       tmp = build_call_expr (gfor_fndecl_in_unpack, 2, desc, ptr);
5141       gfc_add_expr_to_block (&block, tmp);
5142
5143       /* Free the temporary.  */
5144       tmp = gfc_call_free (convert (pvoid_type_node, ptr));
5145       gfc_add_expr_to_block (&block, tmp);
5146
5147       stmt = gfc_finish_block (&block);
5148
5149       gfc_init_block (&block);
5150       /* Only if it was repacked.  This code needs to be executed before the
5151          loop cleanup code.  */
5152       tmp = build_fold_indirect_ref (desc);
5153       tmp = gfc_conv_array_data (tmp);
5154       tmp = build2 (NE_EXPR, boolean_type_node,
5155                     fold_convert (TREE_TYPE (tmp), ptr), tmp);
5156       tmp = build3_v (COND_EXPR, tmp, stmt, build_empty_stmt ());
5157
5158       gfc_add_expr_to_block (&block, tmp);
5159       gfc_add_block_to_block (&block, &se->post);
5160
5161       gfc_init_block (&se->post);
5162       gfc_add_block_to_block (&se->post, &block);
5163     }
5164 }
5165
5166
5167 /* Generate code to deallocate an array, if it is allocated.  */
5168
5169 tree
5170 gfc_trans_dealloc_allocated (tree descriptor)
5171
5172   tree tmp;
5173   tree var;
5174   stmtblock_t block;
5175
5176   gfc_start_block (&block);
5177
5178   var = gfc_conv_descriptor_data_get (descriptor);
5179   STRIP_NOPS (var);
5180
5181   /* Call array_deallocate with an int * present in the second argument.
5182      Although it is ignored here, it's presence ensures that arrays that
5183      are already deallocated are ignored.  */
5184   tmp = gfc_deallocate_with_status (var, NULL_TREE, true);
5185   gfc_add_expr_to_block (&block, tmp);
5186
5187   /* Zero the data pointer.  */
5188   tmp = build2 (MODIFY_EXPR, void_type_node,
5189                 var, build_int_cst (TREE_TYPE (var), 0));
5190   gfc_add_expr_to_block (&block, tmp);
5191
5192   return gfc_finish_block (&block);
5193 }
5194
5195
5196 /* This helper function calculates the size in words of a full array.  */
5197
5198 static tree
5199 get_full_array_size (stmtblock_t *block, tree decl, int rank)
5200 {
5201   tree idx;
5202   tree nelems;
5203   tree tmp;
5204   idx = gfc_rank_cst[rank - 1];
5205   nelems = gfc_conv_descriptor_ubound (decl, idx);
5206   tmp = gfc_conv_descriptor_lbound (decl, idx);
5207   tmp = build2 (MINUS_EXPR, gfc_array_index_type, nelems, tmp);
5208   tmp = build2 (PLUS_EXPR, gfc_array_index_type,
5209                 tmp, gfc_index_one_node);
5210   tmp = gfc_evaluate_now (tmp, block);
5211
5212   nelems = gfc_conv_descriptor_stride (decl, idx);
5213   tmp = build2 (MULT_EXPR, gfc_array_index_type, nelems, tmp);
5214   return gfc_evaluate_now (tmp, block);
5215 }
5216
5217
5218 /* Allocate dest to the same size as src, and copy src -> dest.  */
5219
5220 tree
5221 gfc_duplicate_allocatable(tree dest, tree src, tree type, int rank)
5222 {
5223   tree tmp;
5224   tree size;
5225   tree nelems;
5226   tree null_cond;
5227   tree null_data;
5228   stmtblock_t block;
5229
5230   /* If the source is null, set the destination to null.  */
5231   gfc_init_block (&block);
5232   gfc_conv_descriptor_data_set (&block, dest, null_pointer_node);
5233   null_data = gfc_finish_block (&block);
5234
5235   gfc_init_block (&block);
5236
5237   nelems = get_full_array_size (&block, src, rank);
5238   size = fold_build2 (MULT_EXPR, gfc_array_index_type, nelems,
5239                       fold_convert (gfc_array_index_type,
5240                                     TYPE_SIZE_UNIT (gfc_get_element_type (type))));
5241
5242   /* Allocate memory to the destination.  */
5243   tmp = gfc_call_malloc (&block, TREE_TYPE (gfc_conv_descriptor_data_get (src)),
5244                          size);
5245   gfc_conv_descriptor_data_set (&block, dest, tmp);
5246
5247   /* We know the temporary and the value will be the same length,
5248      so can use memcpy.  */
5249   tmp = built_in_decls[BUILT_IN_MEMCPY];
5250   tmp = build_call_expr (tmp, 3, gfc_conv_descriptor_data_get (dest),
5251                          gfc_conv_descriptor_data_get (src), size);
5252   gfc_add_expr_to_block (&block, tmp);
5253   tmp = gfc_finish_block (&block);
5254
5255   /* Null the destination if the source is null; otherwise do
5256      the allocate and copy.  */
5257   null_cond = gfc_conv_descriptor_data_get (src);
5258   null_cond = convert (pvoid_type_node, null_cond);
5259   null_cond = build2 (NE_EXPR, boolean_type_node, null_cond,
5260                       null_pointer_node);
5261   return build3_v (COND_EXPR, null_cond, tmp, null_data);
5262 }
5263
5264
5265 /* Recursively traverse an object of derived type, generating code to
5266    deallocate, nullify or copy allocatable components.  This is the work horse
5267    function for the functions named in this enum.  */
5268
5269 enum {DEALLOCATE_ALLOC_COMP = 1, NULLIFY_ALLOC_COMP, COPY_ALLOC_COMP};
5270
5271 static tree
5272 structure_alloc_comps (gfc_symbol * der_type, tree decl,
5273                        tree dest, int rank, int purpose)
5274 {
5275   gfc_component *c;
5276   gfc_loopinfo loop;
5277   stmtblock_t fnblock;
5278   stmtblock_t loopbody;
5279   tree tmp;
5280   tree comp;
5281   tree dcmp;
5282   tree nelems;
5283   tree index;
5284   tree var;
5285   tree cdecl;
5286   tree ctype;
5287   tree vref, dref;
5288   tree null_cond = NULL_TREE;
5289
5290   gfc_init_block (&fnblock);
5291
5292   if (POINTER_TYPE_P (TREE_TYPE (decl)))
5293     decl = build_fold_indirect_ref (decl);
5294
5295   /* If this an array of derived types with allocatable components
5296      build a loop and recursively call this function.  */
5297   if (TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE
5298         || GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (decl)))
5299     {
5300       tmp = gfc_conv_array_data (decl);
5301       var = build_fold_indirect_ref (tmp);
5302         
5303       /* Get the number of elements - 1 and set the counter.  */
5304       if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (decl)))
5305         {
5306           /* Use the descriptor for an allocatable array.  Since this
5307              is a full array reference, we only need the descriptor
5308              information from dimension = rank.  */
5309           tmp = get_full_array_size (&fnblock, decl, rank);
5310           tmp = build2 (MINUS_EXPR, gfc_array_index_type,
5311                         tmp, gfc_index_one_node);
5312
5313           null_cond = gfc_conv_descriptor_data_get (decl);
5314           null_cond = build2 (NE_EXPR, boolean_type_node, null_cond,
5315                               build_int_cst (TREE_TYPE (null_cond), 0));
5316         }
5317       else
5318         {
5319           /*  Otherwise use the TYPE_DOMAIN information.  */
5320           tmp =  array_type_nelts (TREE_TYPE (decl));
5321           tmp = fold_convert (gfc_array_index_type, tmp);
5322         }
5323
5324       /* Remember that this is, in fact, the no. of elements - 1.  */
5325       nelems = gfc_evaluate_now (tmp, &fnblock);
5326       index = gfc_create_var (gfc_array_index_type, "S");
5327
5328       /* Build the body of the loop.  */
5329       gfc_init_block (&loopbody);
5330
5331       vref = gfc_build_array_ref (var, index, NULL);
5332
5333       if (purpose == COPY_ALLOC_COMP)
5334         {
5335           tmp = gfc_duplicate_allocatable (dest, decl, TREE_TYPE(decl), rank);
5336           gfc_add_expr_to_block (&fnblock, tmp);
5337
5338           tmp = build_fold_indirect_ref (gfc_conv_descriptor_data_get (dest));
5339           dref = gfc_build_array_ref (tmp, index, NULL);
5340           tmp = structure_alloc_comps (der_type, vref, dref, rank, purpose);
5341         }
5342       else
5343         tmp = structure_alloc_comps (der_type, vref, NULL_TREE, rank, purpose);
5344
5345       gfc_add_expr_to_block (&loopbody, tmp);
5346
5347       /* Build the loop and return.  */
5348       gfc_init_loopinfo (&loop);
5349       loop.dimen = 1;
5350       loop.from[0] = gfc_index_zero_node;
5351       loop.loopvar[0] = index;
5352       loop.to[0] = nelems;
5353       gfc_trans_scalarizing_loops (&loop, &loopbody);
5354       gfc_add_block_to_block (&fnblock, &loop.pre);
5355
5356       tmp = gfc_finish_block (&fnblock);
5357       if (null_cond != NULL_TREE)
5358         tmp = build3_v (COND_EXPR, null_cond, tmp, build_empty_stmt ());
5359
5360       return tmp;
5361     }
5362
5363   /* Otherwise, act on the components or recursively call self to
5364      act on a chain of components.  */
5365   for (c = der_type->components; c; c = c->next)
5366     {
5367       bool cmp_has_alloc_comps = (c->ts.type == BT_DERIVED)
5368                                     && c->ts.derived->attr.alloc_comp;
5369       cdecl = c->backend_decl;
5370       ctype = TREE_TYPE (cdecl);
5371
5372       switch (purpose)
5373         {
5374         case DEALLOCATE_ALLOC_COMP:
5375           /* Do not deallocate the components of ultimate pointer
5376              components.  */
5377           if (cmp_has_alloc_comps && !c->pointer)
5378             {
5379               comp = build3 (COMPONENT_REF, ctype, decl, cdecl, NULL_TREE);
5380               rank = c->as ? c->as->rank : 0;
5381               tmp = structure_alloc_comps (c->ts.derived, comp, NULL_TREE,
5382                                            rank, purpose);
5383               gfc_add_expr_to_block (&fnblock, tmp);
5384             }
5385
5386           if (c->allocatable)
5387             {
5388               comp = build3 (COMPONENT_REF, ctype, decl, cdecl, NULL_TREE);
5389               tmp = gfc_trans_dealloc_allocated (comp);
5390               gfc_add_expr_to_block (&fnblock, tmp);
5391             }
5392           break;
5393
5394         case NULLIFY_ALLOC_COMP:
5395           if (c->pointer)
5396             continue;
5397           else if (c->allocatable)
5398             {
5399               comp = build3 (COMPONENT_REF, ctype, decl, cdecl, NULL_TREE);
5400               gfc_conv_descriptor_data_set (&fnblock, comp, null_pointer_node);
5401             }
5402           else if (cmp_has_alloc_comps)
5403             {
5404               comp = build3 (COMPONENT_REF, ctype, decl, cdecl, NULL_TREE);
5405               rank = c->as ? c->as->rank : 0;
5406               tmp = structure_alloc_comps (c->ts.derived, comp, NULL_TREE,
5407                                            rank, purpose);
5408               gfc_add_expr_to_block (&fnblock, tmp);
5409             }
5410           break;
5411
5412         case COPY_ALLOC_COMP:
5413           if (c->pointer)
5414             continue;
5415
5416           /* We need source and destination components.  */
5417           comp = build3 (COMPONENT_REF, ctype, decl, cdecl, NULL_TREE);
5418           dcmp = build3 (COMPONENT_REF, ctype, dest, cdecl, NULL_TREE);
5419           dcmp = fold_convert (TREE_TYPE (comp), dcmp);
5420
5421           if (c->allocatable && !cmp_has_alloc_comps)
5422             {
5423               tmp = gfc_duplicate_allocatable(dcmp, comp, ctype, c->as->rank);
5424               gfc_add_expr_to_block (&fnblock, tmp);
5425             }
5426
5427           if (cmp_has_alloc_comps)
5428             {
5429               rank = c->as ? c->as->rank : 0;
5430               tmp = fold_convert (TREE_TYPE (dcmp), comp);
5431               gfc_add_modify_expr (&fnblock, dcmp, tmp);
5432               tmp = structure_alloc_comps (c->ts.derived, comp, dcmp,
5433                                            rank, purpose);
5434               gfc_add_expr_to_block (&fnblock, tmp);
5435             }
5436           break;
5437
5438         default:
5439           gcc_unreachable ();
5440           break;
5441         }
5442     }
5443
5444   return gfc_finish_block (&fnblock);
5445 }
5446
5447 /* Recursively traverse an object of derived type, generating code to
5448    nullify allocatable components.  */
5449
5450 tree
5451 gfc_nullify_alloc_comp (gfc_symbol * der_type, tree decl, int rank)
5452 {
5453   return structure_alloc_comps (der_type, decl, NULL_TREE, rank,
5454                                 NULLIFY_ALLOC_COMP);
5455 }
5456
5457
5458 /* Recursively traverse an object of derived type, generating code to
5459    deallocate allocatable components.  */
5460
5461 tree
5462 gfc_deallocate_alloc_comp (gfc_symbol * der_type, tree decl, int rank)
5463 {
5464   return structure_alloc_comps (der_type, decl, NULL_TREE, rank,
5465                                 DEALLOCATE_ALLOC_COMP);
5466 }
5467
5468
5469 /* Recursively traverse an object of derived type, generating code to
5470    copy its allocatable components.  */
5471
5472 tree
5473 gfc_copy_alloc_comp (gfc_symbol * der_type, tree decl, tree dest, int rank)
5474 {
5475   return structure_alloc_comps (der_type, decl, dest, rank, COPY_ALLOC_COMP);
5476 }
5477
5478
5479 /* NULLIFY an allocatable/pointer array on function entry, free it on exit.
5480    Do likewise, recursively if necessary, with the allocatable components of
5481    derived types.  */
5482
5483 tree
5484 gfc_trans_deferred_array (gfc_symbol * sym, tree body)
5485 {
5486   tree type;
5487   tree tmp;
5488   tree descriptor;
5489   stmtblock_t fnblock;
5490   locus loc;
5491   int rank;
5492   bool sym_has_alloc_comp;
5493
5494   sym_has_alloc_comp = (sym->ts.type == BT_DERIVED)
5495                           && sym->ts.derived->attr.alloc_comp;
5496
5497   /* Make sure the frontend gets these right.  */
5498   if (!(sym->attr.pointer || sym->attr.allocatable || sym_has_alloc_comp))
5499     fatal_error ("Possible frontend bug: Deferred array size without pointer, "
5500                  "allocatable attribute or derived type without allocatable "
5501                  "components.");
5502
5503   gfc_init_block (&fnblock);
5504
5505   gcc_assert (TREE_CODE (sym->backend_decl) == VAR_DECL
5506                 || TREE_CODE (sym->backend_decl) == PARM_DECL);
5507
5508   if (sym->ts.type == BT_CHARACTER
5509       && !INTEGER_CST_P (sym->ts.cl->backend_decl))
5510     {
5511       gfc_conv_string_length (sym->ts.cl, &fnblock);
5512       gfc_trans_vla_type_sizes (sym, &fnblock);
5513     }
5514
5515   /* Dummy and use associated variables don't need anything special.  */
5516   if (sym->attr.dummy || sym->attr.use_assoc)
5517     {
5518       gfc_add_expr_to_block (&fnblock, body);
5519
5520       return gfc_finish_block (&fnblock);
5521     }
5522
5523   gfc_get_backend_locus (&loc);
5524   gfc_set_backend_locus (&sym->declared_at);
5525   descriptor = sym->backend_decl;
5526
5527   /* Although static, derived types with default initializers and
5528      allocatable components must not be nulled wholesale; instead they
5529      are treated component by component.  */
5530   if (TREE_STATIC (descriptor) && !sym_has_alloc_comp)
5531     {
5532       /* SAVEd variables are not freed on exit.  */
5533       gfc_trans_static_array_pointer (sym);
5534       return body;
5535     }
5536
5537   /* Get the descriptor type.  */
5538   type = TREE_TYPE (sym->backend_decl);
5539     
5540   if (sym_has_alloc_comp && !(sym->attr.pointer || sym->attr.allocatable))
5541     {
5542       if (!sym->attr.save)
5543         {
5544           rank = sym->as ? sym->as->rank : 0;
5545           tmp = gfc_nullify_alloc_comp (sym->ts.derived, descriptor, rank);
5546           gfc_add_expr_to_block (&fnblock, tmp);
5547         }
5548     }
5549   else if (!GFC_DESCRIPTOR_TYPE_P (type))
5550     {
5551       /* If the backend_decl is not a descriptor, we must have a pointer
5552          to one.  */
5553       descriptor = build_fold_indirect_ref (sym->backend_decl);
5554       type = TREE_TYPE (descriptor);
5555     }
5556   
5557   /* NULLIFY the data pointer.  */
5558   if (GFC_DESCRIPTOR_TYPE_P (type) && !sym->attr.save)
5559     gfc_conv_descriptor_data_set (&fnblock, descriptor, null_pointer_node);
5560
5561   gfc_add_expr_to_block (&fnblock, body);
5562
5563   gfc_set_backend_locus (&loc);
5564
5565   /* Allocatable arrays need to be freed when they go out of scope.
5566      The allocatable components of pointers must not be touched.  */
5567   if (sym_has_alloc_comp && !(sym->attr.function || sym->attr.result)
5568       && !sym->attr.pointer && !sym->attr.save)
5569     {
5570       int rank;
5571       rank = sym->as ? sym->as->rank : 0;
5572       tmp = gfc_deallocate_alloc_comp (sym->ts.derived, descriptor, rank);
5573       gfc_add_expr_to_block (&fnblock, tmp);
5574     }
5575
5576   if (sym->attr.allocatable && !sym->attr.save)
5577     {
5578       tmp = gfc_trans_dealloc_allocated (sym->backend_decl);
5579       gfc_add_expr_to_block (&fnblock, tmp);
5580     }
5581
5582   return gfc_finish_block (&fnblock);
5583 }
5584
5585 /************ Expression Walking Functions ******************/
5586
5587 /* Walk a variable reference.
5588
5589    Possible extension - multiple component subscripts.
5590     x(:,:) = foo%a(:)%b(:)
5591    Transforms to
5592     forall (i=..., j=...)
5593       x(i,j) = foo%a(j)%b(i)
5594     end forall
5595    This adds a fair amount of complexity because you need to deal with more
5596    than one ref.  Maybe handle in a similar manner to vector subscripts.
5597    Maybe not worth the effort.  */
5598
5599
5600 static gfc_ss *
5601 gfc_walk_variable_expr (gfc_ss * ss, gfc_expr * expr)
5602 {
5603   gfc_ref *ref;
5604   gfc_array_ref *ar;
5605   gfc_ss *newss;
5606   gfc_ss *head;
5607   int n;
5608
5609   for (ref = expr->ref; ref; ref = ref->next)
5610     if (ref->type == REF_ARRAY && ref->u.ar.type != AR_ELEMENT)
5611       break;
5612
5613   for (; ref; ref = ref->next)
5614     {
5615       if (ref->type == REF_SUBSTRING)
5616         {
5617           newss = gfc_get_ss ();
5618           newss->type = GFC_SS_SCALAR;
5619           newss->expr = ref->u.ss.start;
5620           newss->next = ss;
5621           ss = newss;
5622
5623           newss = gfc_get_ss ();
5624           newss->type = GFC_SS_SCALAR;
5625           newss->expr = ref->u.ss.end;
5626           newss->next = ss;
5627           ss = newss;
5628         }
5629
5630       /* We're only interested in array sections from now on.  */
5631       if (ref->type != REF_ARRAY)
5632         continue;
5633
5634       ar = &ref->u.ar;
5635       switch (ar->type)
5636         {
5637         case AR_ELEMENT:
5638           for (n = 0; n < ar->dimen; n++)
5639             {
5640               newss = gfc_get_ss ();
5641               newss->type = GFC_SS_SCALAR;
5642               newss->expr = ar->start[n];
5643               newss->next = ss;
5644               ss = newss;
5645             }
5646           break;
5647
5648         case AR_FULL:
5649           newss = gfc_get_ss ();
5650           newss->type = GFC_SS_SECTION;
5651           newss->expr = expr;
5652           newss->next = ss;
5653           newss->data.info.dimen = ar->as->rank;
5654           newss->data.info.ref = ref;
5655
5656           /* Make sure array is the same as array(:,:), this way
5657              we don't need to special case all the time.  */
5658           ar->dimen = ar->as->rank;
5659           for (n = 0; n < ar->dimen; n++)
5660             {
5661               newss->data.info.dim[n] = n;
5662               ar->dimen_type[n] = DIMEN_RANGE;
5663
5664               gcc_assert (ar->start[n] == NULL);
5665               gcc_assert (ar->end[n] == NULL);
5666               gcc_assert (ar->stride[n] == NULL);
5667             }
5668           ss = newss;
5669           break;
5670
5671         case AR_SECTION:
5672           newss = gfc_get_ss ();
5673           newss->type = GFC_SS_SECTION;
5674           newss->expr = expr;
5675           newss->next = ss;
5676           newss->data.info.dimen = 0;
5677           newss->data.info.ref = ref;
5678
5679           head = newss;
5680
5681           /* We add SS chains for all the subscripts in the section.  */
5682           for (n = 0; n < ar->dimen; n++)
5683             {
5684               gfc_ss *indexss;
5685
5686               switch (ar->dimen_type[n])
5687                 {
5688                 case DIMEN_ELEMENT:
5689                   /* Add SS for elemental (scalar) subscripts.  */
5690                   gcc_assert (ar->start[n]);
5691                   indexss = gfc_get_ss ();
5692                   indexss->type = GFC_SS_SCALAR;
5693                   indexss->expr = ar->start[n];
5694                   indexss->next = gfc_ss_terminator;
5695                   indexss->loop_chain = gfc_ss_terminator;
5696                   newss->data.info.subscript[n] = indexss;
5697                   break;
5698
5699                 case DIMEN_RANGE:
5700                   /* We don't add anything for sections, just remember this
5701                      dimension for later.  */
5702                   newss->data.info.dim[newss->data.info.dimen] = n;
5703                   newss->data.info.dimen++;
5704                   break;
5705
5706                 case DIMEN_VECTOR:
5707                   /* Create a GFC_SS_VECTOR index in which we can store
5708                      the vector's descriptor.  */
5709                   indexss = gfc_get_ss ();
5710                   indexss->type = GFC_SS_VECTOR;
5711                   indexss->expr = ar->start[n];
5712                   indexss->next = gfc_ss_terminator;
5713                   indexss->loop_chain = gfc_ss_terminator;
5714                   newss->data.info.subscript[n] = indexss;
5715                   newss->data.info.dim[newss->data.info.dimen] = n;
5716                   newss->data.info.dimen++;
5717                   break;
5718
5719                 default:
5720                   /* We should know what sort of section it is by now.  */
5721                   gcc_unreachable ();
5722                 }
5723             }
5724           /* We should have at least one non-elemental dimension.  */
5725           gcc_assert (newss->data.info.dimen > 0);
5726           ss = newss;
5727           break;
5728
5729         default:
5730           /* We should know what sort of section it is by now.  */
5731           gcc_unreachable ();
5732         }
5733
5734     }
5735   return ss;
5736 }
5737
5738
5739 /* Walk an expression operator. If only one operand of a binary expression is
5740    scalar, we must also add the scalar term to the SS chain.  */
5741
5742 static gfc_ss *
5743 gfc_walk_op_expr (gfc_ss * ss, gfc_expr * expr)
5744 {
5745   gfc_ss *head;
5746   gfc_ss *head2;
5747   gfc_ss *newss;
5748
5749   head = gfc_walk_subexpr (ss, expr->value.op.op1);
5750   if (expr->value.op.op2 == NULL)
5751     head2 = head;
5752   else
5753     head2 = gfc_walk_subexpr (head, expr->value.op.op2);
5754
5755   /* All operands are scalar.  Pass back and let the caller deal with it.  */
5756   if (head2 == ss)
5757     return head2;
5758
5759   /* All operands require scalarization.  */
5760   if (head != ss && (expr->value.op.op2 == NULL || head2 != head))
5761     return head2;
5762
5763   /* One of the operands needs scalarization, the other is scalar.
5764      Create a gfc_ss for the scalar expression.  */
5765   newss = gfc_get_ss ();
5766   newss->type = GFC_SS_SCALAR;
5767   if (head == ss)
5768     {
5769       /* First operand is scalar.  We build the chain in reverse order, so
5770          add the scarar SS after the second operand.  */
5771       head = head2;
5772       while (head && head->next != ss)
5773         head = head->next;
5774       /* Check we haven't somehow broken the chain.  */
5775       gcc_assert (head);
5776       newss->next = ss;
5777       head->next = newss;
5778       newss->expr = expr->value.op.op1;
5779     }
5780   else                          /* head2 == head */
5781     {
5782       gcc_assert (head2 == head);
5783       /* Second operand is scalar.  */
5784       newss->next = head2;
5785       head2 = newss;
5786       newss->expr = expr->value.op.op2;
5787     }
5788
5789   return head2;
5790 }
5791
5792
5793 /* Reverse a SS chain.  */
5794
5795 gfc_ss *
5796 gfc_reverse_ss (gfc_ss * ss)
5797 {
5798   gfc_ss *next;
5799   gfc_ss *head;
5800
5801   gcc_assert (ss != NULL);
5802
5803   head = gfc_ss_terminator;
5804   while (ss != gfc_ss_terminator)
5805     {
5806       next = ss->next;
5807       /* Check we didn't somehow break the chain.  */
5808       gcc_assert (next != NULL);
5809       ss->next = head;
5810       head = ss;
5811       ss = next;
5812     }
5813
5814   return (head);
5815 }
5816
5817
5818 /* Walk the arguments of an elemental function.  */
5819
5820 gfc_ss *
5821 gfc_walk_elemental_function_args (gfc_ss * ss, gfc_actual_arglist *arg,
5822                                   gfc_ss_type type)
5823 {
5824   int scalar;
5825   gfc_ss *head;
5826   gfc_ss *tail;
5827   gfc_ss *newss;
5828
5829   head = gfc_ss_terminator;
5830   tail = NULL;
5831   scalar = 1;
5832   for (; arg; arg = arg->next)
5833     {
5834       if (!arg->expr)
5835         continue;
5836
5837       newss = gfc_walk_subexpr (head, arg->expr);
5838       if (newss == head)
5839         {
5840           /* Scalar argument.  */
5841           newss = gfc_get_ss ();
5842           newss->type = type;
5843           newss->expr = arg->expr;
5844           newss->next = head;
5845         }
5846       else
5847         scalar = 0;
5848
5849       head = newss;
5850       if (!tail)
5851         {
5852           tail = head;
5853           while (tail->next != gfc_ss_terminator)
5854             tail = tail->next;
5855         }
5856     }
5857
5858   if (scalar)
5859     {
5860       /* If all the arguments are scalar we don't need the argument SS.  */
5861       gfc_free_ss_chain (head);
5862       /* Pass it back.  */
5863       return ss;
5864     }
5865
5866   /* Add it onto the existing chain.  */
5867   tail->next = ss;
5868   return head;
5869 }
5870
5871
5872 /* Walk a function call.  Scalar functions are passed back, and taken out of
5873    scalarization loops.  For elemental functions we walk their arguments.
5874    The result of functions returning arrays is stored in a temporary outside
5875    the loop, so that the function is only called once.  Hence we do not need
5876    to walk their arguments.  */
5877
5878 static gfc_ss *
5879 gfc_walk_function_expr (gfc_ss * ss, gfc_expr * expr)
5880 {
5881   gfc_ss *newss;
5882   gfc_intrinsic_sym *isym;
5883   gfc_symbol *sym;
5884
5885   isym = expr->value.function.isym;
5886
5887   /* Handle intrinsic functions separately.  */
5888   if (isym)
5889     return gfc_walk_intrinsic_function (ss, expr, isym);
5890
5891   sym = expr->value.function.esym;
5892   if (!sym)
5893       sym = expr->symtree->n.sym;
5894
5895   /* A function that returns arrays.  */
5896   if (gfc_return_by_reference (sym) && sym->result->attr.dimension)
5897     {
5898       newss = gfc_get_ss ();
5899       newss->type = GFC_SS_FUNCTION;
5900       newss->expr = expr;
5901       newss->next = ss;
5902       newss->data.info.dimen = expr->rank;
5903       return newss;
5904     }
5905
5906   /* Walk the parameters of an elemental function.  For now we always pass
5907      by reference.  */
5908   if (sym->attr.elemental)
5909     return gfc_walk_elemental_function_args (ss, expr->value.function.actual,
5910                                              GFC_SS_REFERENCE);
5911
5912   /* Scalar functions are OK as these are evaluated outside the scalarization
5913      loop.  Pass back and let the caller deal with it.  */
5914   return ss;
5915 }
5916
5917
5918 /* An array temporary is constructed for array constructors.  */
5919
5920 static gfc_ss *
5921 gfc_walk_array_constructor (gfc_ss * ss, gfc_expr * expr)
5922 {
5923   gfc_ss *newss;
5924   int n;
5925
5926   newss = gfc_get_ss ();
5927   newss->type = GFC_SS_CONSTRUCTOR;
5928   newss->expr = expr;
5929   newss->next = ss;
5930   newss->data.info.dimen = expr->rank;
5931   for (n = 0; n < expr->rank; n++)
5932     newss->data.info.dim[n] = n;
5933
5934   return newss;
5935 }
5936
5937
5938 /* Walk an expression.  Add walked expressions to the head of the SS chain.
5939    A wholly scalar expression will not be added.  */
5940
5941 static gfc_ss *
5942 gfc_walk_subexpr (gfc_ss * ss, gfc_expr * expr)
5943 {
5944   gfc_ss *head;
5945
5946   switch (expr->expr_type)
5947     {
5948     case EXPR_VARIABLE:
5949       head = gfc_walk_variable_expr (ss, expr);
5950       return head;
5951
5952     case EXPR_OP:
5953       head = gfc_walk_op_expr (ss, expr);
5954       return head;
5955
5956     case EXPR_FUNCTION:
5957       head = gfc_walk_function_expr (ss, expr);
5958       return head;
5959
5960     case EXPR_CONSTANT:
5961     case EXPR_NULL:
5962     case EXPR_STRUCTURE:
5963       /* Pass back and let the caller deal with it.  */
5964       break;
5965
5966     case EXPR_ARRAY:
5967       head = gfc_walk_array_constructor (ss, expr);
5968       return head;
5969
5970     case EXPR_SUBSTRING:
5971       /* Pass back and let the caller deal with it.  */
5972       break;
5973
5974     default:
5975       internal_error ("bad expression type during walk (%d)",
5976                       expr->expr_type);
5977     }
5978   return ss;
5979 }
5980
5981
5982 /* Entry point for expression walking.
5983    A return value equal to the passed chain means this is
5984    a scalar expression.  It is up to the caller to take whatever action is
5985    necessary to translate these.  */
5986
5987 gfc_ss *
5988 gfc_walk_expr (gfc_expr * expr)
5989 {
5990   gfc_ss *res;
5991
5992   res = gfc_walk_subexpr (gfc_ss_terminator, expr);
5993   return gfc_reverse_ss (res);
5994 }