OSDN Git Service

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