OSDN Git Service

* vec.h: Comment improvements.
[pf3gnuchains/gcc-fork.git] / gcc / fortran / trans-array.c
1 /* Array translation routines
2    Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc.
3    Contributed by Paul Brook <paul@nowt.org>
4    and Steven Bosscher <s.bosscher@student.tudelft.nl>
5
6 This file is part of GCC.
7
8 GCC is free software; you can redistribute it and/or modify it under
9 the terms of the GNU General Public License as published by the Free
10 Software Foundation; either version 2, or (at your option) any later
11 version.
12
13 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
14 WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
16 for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with GCC; see the file COPYING.  If not, write to the Free
20 Software Foundation, 59 Temple Place - Suite 330, Boston, MA
21 02111-1307, USA.  */
22
23 /* trans-array.c-- Various array related code, including scalarization,
24                    allocation, initialization and other support routines.  */
25
26 /* How the scalarizer works.
27    In gfortran, array expressions use the same core routines as scalar
28    expressions.
29    First, a Scalarization State (SS) chain is built.  This is done by walking
30    the expression tree, and building a linear list of the terms in the
31    expression.  As the tree is walked, scalar subexpressions are translated.
32
33    The scalarization parameters are stored in a gfc_loopinfo structure.
34    First the start and stride of each term is calculated by
35    gfc_conv_ss_startstride.  During this process the expressions for the array
36    descriptors and data pointers are also translated.
37
38    If the expression is an assignment, we must then resolve any dependencies.
39    In fortran all the rhs values of an assignment must be evaluated before
40    any assignments take place.  This can require a temporary array to store the
41    values.  We also require a temporary when we are passing array expressions
42    or vector subecripts as procedure parameters.
43
44    Array sections are passed without copying to a temporary.  These use the
45    scalarizer to determine the shape of the section.  The flag
46    loop->array_parameter tells the scalarizer that the actual values and loop
47    variables will not be required.
48
49    The function gfc_conv_loop_setup generates the scalarization setup code.
50    It determines the range of the scalarizing loop variables.  If a temporary
51    is required, this is created and initialized.  Code for scalar expressions
52    taken outside the loop is also generated at this time.  Next the offset and
53    scaling required to translate from loop variables to array indices for each
54    term is calculated.
55
56    A call to gfc_start_scalarized_body marks the start of the scalarized
57    expression.  This creates a scope and declares the loop variables.  Before
58    calling this gfc_make_ss_chain_used must be used to indicate which terms
59    will be used inside this loop.
60
61    The scalar gfc_conv_* functions are then used to build the main body of the
62    scalarization loop.  Scalarization loop variables and precalculated scalar
63    values are automaticaly substituted.  Note that gfc_advance_se_ss_chain
64    must be used, rather than changing the se->ss directly.
65
66    For assignment expressions requiring a temporary two sub loops are
67    generated.  The first stores the result of the expression in the temporary,
68    the second copies it to the result.  A call to
69    gfc_trans_scalarized_loop_boundary marks the end of the main loop code and
70    the start of the copying loop.  The temporary may be less than full rank.
71
72    Finally gfc_trans_scalarizing_loops is called to generate the implicit do
73    loops.  The loops are added to the pre chain of the loopinfo.  The post
74    chain may still contain cleanup code.
75
76    After the loop code has been added into its parent scope gfc_cleanup_loop
77    is called to free all the SS allocated by the scalarizer.  */
78
79 #include "config.h"
80 #include "system.h"
81 #include "coretypes.h"
82 #include "tree.h"
83 #include "tree-gimple.h"
84 #include <stdio.h>
85 #include "ggc.h"
86 #include "toplev.h"
87 #include "real.h"
88 #include "flags.h"
89 #include <assert.h>
90 #include <gmp.h>
91 #include "gfortran.h"
92 #include "trans.h"
93 #include "trans-stmt.h"
94 #include "trans-types.h"
95 #include "trans-array.h"
96 #include "trans-const.h"
97 #include "dependency.h"
98
99 static gfc_ss *gfc_walk_subexpr (gfc_ss *, gfc_expr *);
100
101 /* The contents of this structure aren't actually used, just the address.  */
102 static gfc_ss gfc_ss_terminator_var;
103 gfc_ss * const gfc_ss_terminator = &gfc_ss_terminator_var;
104
105 unsigned HOST_WIDE_INT gfc_stack_space_left;
106
107
108 /* Returns true if a variable of specified size should go on the stack.  */
109
110 int
111 gfc_can_put_var_on_stack (tree size)
112 {
113   unsigned HOST_WIDE_INT low;
114
115   if (!INTEGER_CST_P (size))
116     return 0;
117
118   if (gfc_option.flag_max_stack_var_size < 0)
119     return 1;
120
121   if (TREE_INT_CST_HIGH (size) != 0)
122     return 0;
123
124   low = TREE_INT_CST_LOW (size);
125   if (low > (unsigned HOST_WIDE_INT) gfc_option.flag_max_stack_var_size)
126     return 0;
127
128 /* TODO: Set a per-function stack size limit.  */
129 #if 0
130   /* We should be a bit more clever with array temps.  */
131   if (gfc_option.flag_max_function_vars_size >= 0)
132     {
133       if (low > gfc_stack_space_left)
134         return 0;
135
136       gfc_stack_space_left -= low;
137     }
138 #endif
139
140   return 1;
141 }
142
143 static tree
144 gfc_array_dataptr_type (tree desc)
145 {
146   return (GFC_TYPE_ARRAY_DATAPTR_TYPE (TREE_TYPE (desc)));
147 }
148
149
150 /* Build expressions to access the members of an array descriptor.
151    It's surprisingly easy to mess up here, so never access
152    an array descriptor by "brute force", always use these
153    functions.  This also avoids problems if we change the format
154    of an array descriptor.
155
156    To understand these magic numbers, look at the comments
157    before gfc_build_array_type() in trans-types.c.
158
159    The code within these defines should be the only code which knows the format
160    of an array descriptor.
161
162    Any code just needing to read obtain the bounds of an array should use
163    gfc_conv_array_* rather than the following functions as these will return
164    know constant values, and work with arrays which do not have descriptors.
165
166    Don't forget to #undef these!  */
167
168 #define DATA_FIELD 0
169 #define OFFSET_FIELD 1
170 #define DTYPE_FIELD 2
171 #define DIMENSION_FIELD 3
172
173 #define STRIDE_SUBFIELD 0
174 #define LBOUND_SUBFIELD 1
175 #define UBOUND_SUBFIELD 2
176
177 tree
178 gfc_conv_descriptor_data (tree desc)
179 {
180   tree field;
181   tree type;
182
183   type = TREE_TYPE (desc);
184   assert (GFC_DESCRIPTOR_TYPE_P (type));
185
186   field = TYPE_FIELDS (type);
187   assert (DATA_FIELD == 0);
188   assert (field != NULL_TREE
189           && TREE_CODE (TREE_TYPE (field)) == POINTER_TYPE
190           && TREE_CODE (TREE_TYPE (TREE_TYPE (field))) == ARRAY_TYPE);
191
192   return build (COMPONENT_REF, TREE_TYPE (field), desc, field, NULL_TREE);
193 }
194
195 tree
196 gfc_conv_descriptor_offset (tree desc)
197 {
198   tree type;
199   tree field;
200
201   type = TREE_TYPE (desc);
202   assert (GFC_DESCRIPTOR_TYPE_P (type));
203
204   field = gfc_advance_chain (TYPE_FIELDS (type), OFFSET_FIELD);
205   assert (field != NULL_TREE && TREE_TYPE (field) == gfc_array_index_type);
206
207   return build (COMPONENT_REF, TREE_TYPE (field), desc, field, NULL_TREE);
208 }
209
210 tree
211 gfc_conv_descriptor_dtype (tree desc)
212 {
213   tree field;
214   tree type;
215
216   type = TREE_TYPE (desc);
217   assert (GFC_DESCRIPTOR_TYPE_P (type));
218
219   field = gfc_advance_chain (TYPE_FIELDS (type), DTYPE_FIELD);
220   assert (field != NULL_TREE && TREE_TYPE (field) == gfc_array_index_type);
221
222   return build (COMPONENT_REF, TREE_TYPE (field), desc, field, NULL_TREE);
223 }
224
225 static tree
226 gfc_conv_descriptor_dimension (tree desc, tree dim)
227 {
228   tree field;
229   tree type;
230   tree tmp;
231
232   type = TREE_TYPE (desc);
233   assert (GFC_DESCRIPTOR_TYPE_P (type));
234
235   field = gfc_advance_chain (TYPE_FIELDS (type), DIMENSION_FIELD);
236   assert (field != NULL_TREE
237           && TREE_CODE (TREE_TYPE (field)) == ARRAY_TYPE
238           && TREE_CODE (TREE_TYPE (TREE_TYPE (field))) == RECORD_TYPE);
239
240   tmp = build (COMPONENT_REF, TREE_TYPE (field), desc, field, NULL_TREE);
241   tmp = gfc_build_array_ref (tmp, dim);
242   return tmp;
243 }
244
245 tree
246 gfc_conv_descriptor_stride (tree desc, tree dim)
247 {
248   tree tmp;
249   tree field;
250
251   tmp = gfc_conv_descriptor_dimension (desc, dim);
252   field = TYPE_FIELDS (TREE_TYPE (tmp));
253   field = gfc_advance_chain (field, STRIDE_SUBFIELD);
254   assert (field != NULL_TREE && TREE_TYPE (field) == gfc_array_index_type);
255
256   tmp = build (COMPONENT_REF, TREE_TYPE (field), tmp, field, NULL_TREE);
257   return tmp;
258 }
259
260 tree
261 gfc_conv_descriptor_lbound (tree desc, tree dim)
262 {
263   tree tmp;
264   tree field;
265
266   tmp = gfc_conv_descriptor_dimension (desc, dim);
267   field = TYPE_FIELDS (TREE_TYPE (tmp));
268   field = gfc_advance_chain (field, LBOUND_SUBFIELD);
269   assert (field != NULL_TREE && TREE_TYPE (field) == gfc_array_index_type);
270
271   tmp = build (COMPONENT_REF, TREE_TYPE (field), tmp, field, NULL_TREE);
272   return tmp;
273 }
274
275 tree
276 gfc_conv_descriptor_ubound (tree desc, tree dim)
277 {
278   tree tmp;
279   tree field;
280
281   tmp = gfc_conv_descriptor_dimension (desc, dim);
282   field = TYPE_FIELDS (TREE_TYPE (tmp));
283   field = gfc_advance_chain (field, UBOUND_SUBFIELD);
284   assert (field != NULL_TREE && TREE_TYPE (field) == gfc_array_index_type);
285
286   tmp = build (COMPONENT_REF, TREE_TYPE (field), tmp, field, NULL_TREE);
287   return tmp;
288 }
289
290
291 /* Build an null array descriptor constructor.  */
292
293 tree
294 gfc_build_null_descriptor (tree type)
295 {
296   tree field;
297   tree tmp;
298
299   assert (GFC_DESCRIPTOR_TYPE_P (type));
300   assert (DATA_FIELD == 0);
301   field = TYPE_FIELDS (type);
302
303   /* Set a NULL data pointer.  */
304   tmp = tree_cons (field, null_pointer_node, NULL_TREE);
305   tmp = build1 (CONSTRUCTOR, type, tmp);
306   TREE_CONSTANT (tmp) = 1;
307   TREE_INVARIANT (tmp) = 1;
308   /* All other fields are ignored.  */
309
310   return tmp;
311 }
312
313
314 /* Cleanup those #defines.  */
315
316 #undef DATA_FIELD
317 #undef OFFSET_FIELD
318 #undef DTYPE_FIELD
319 #undef DIMENSION_FIELD
320 #undef STRIDE_SUBFIELD
321 #undef LBOUND_SUBFIELD
322 #undef UBOUND_SUBFIELD
323
324
325 /* Mark a SS chain as used.  Flags specifies in which loops the SS is used.
326    flags & 1 = Main loop body.
327    flags & 2 = temp copy loop.  */
328
329 void
330 gfc_mark_ss_chain_used (gfc_ss * ss, unsigned flags)
331 {
332   for (; ss != gfc_ss_terminator; ss = ss->next)
333     ss->useflags = flags;
334 }
335
336 static void gfc_free_ss (gfc_ss *);
337
338
339 /* Free a gfc_ss chain.  */
340
341 static void
342 gfc_free_ss_chain (gfc_ss * ss)
343 {
344   gfc_ss *next;
345
346   while (ss != gfc_ss_terminator)
347     {
348       assert (ss != NULL);
349       next = ss->next;
350       gfc_free_ss (ss);
351       ss = next;
352     }
353 }
354
355
356 /* Free a SS.  */
357
358 static void
359 gfc_free_ss (gfc_ss * ss)
360 {
361   int n;
362
363   switch (ss->type)
364     {
365     case GFC_SS_SECTION:
366     case GFC_SS_VECTOR:
367       for (n = 0; n < GFC_MAX_DIMENSIONS; n++)
368         {
369           if (ss->data.info.subscript[n])
370             gfc_free_ss_chain (ss->data.info.subscript[n]);
371         }
372       break;
373
374     default:
375       break;
376     }
377
378   gfc_free (ss);
379 }
380
381
382 /* Free all the SS associated with a loop.  */
383
384 void
385 gfc_cleanup_loop (gfc_loopinfo * loop)
386 {
387   gfc_ss *ss;
388   gfc_ss *next;
389
390   ss = loop->ss;
391   while (ss != gfc_ss_terminator)
392     {
393       assert (ss != NULL);
394       next = ss->loop_chain;
395       gfc_free_ss (ss);
396       ss = next;
397     }
398 }
399
400
401 /* Associate a SS chain with a loop.  */
402
403 void
404 gfc_add_ss_to_loop (gfc_loopinfo * loop, gfc_ss * head)
405 {
406   gfc_ss *ss;
407
408   if (head == gfc_ss_terminator)
409     return;
410
411   ss = head;
412   for (; ss && ss != gfc_ss_terminator; ss = ss->next)
413     {
414       if (ss->next == gfc_ss_terminator)
415         ss->loop_chain = loop->ss;
416       else
417         ss->loop_chain = ss->next;
418     }
419   assert (ss == gfc_ss_terminator);
420   loop->ss = head;
421 }
422
423
424 /* Generate an initializer for a static pointer or allocatable array.  */
425
426 void
427 gfc_trans_static_array_pointer (gfc_symbol * sym)
428 {
429   tree type;
430
431   assert (TREE_STATIC (sym->backend_decl));
432   /* Just zero the data member.  */
433   type = TREE_TYPE (sym->backend_decl);
434   DECL_INITIAL (sym->backend_decl) =gfc_build_null_descriptor (type);
435 }
436
437
438 /* Generate code to allocate an array temporary, or create a variable to
439    hold the data.  If size is NULL zero the descriptor so that so that the
440    callee will allocate the array.  Also generates code to free the array
441    afterwards.  */
442
443 static void
444 gfc_trans_allocate_array_storage (gfc_loopinfo * loop, gfc_ss_info * info,
445                                   tree size, tree nelem)
446 {
447   tree tmp;
448   tree args;
449   tree desc;
450   tree data;
451   bool onstack;
452
453   desc = info->descriptor;
454   data = gfc_conv_descriptor_data (desc);
455   if (size == NULL_TREE)
456     {
457       /* A callee allocated array.  */
458       gfc_add_modify_expr (&loop->pre, data, convert (TREE_TYPE (data), 
459                                                       gfc_index_zero_node));
460       info->data = data;
461       info->offset = gfc_index_zero_node;
462       onstack = FALSE;
463     }
464   else
465     {
466       /* Allocate the temporary.  */
467       onstack = gfc_can_put_var_on_stack (size);
468
469       if (onstack)
470         {
471           /* Make a temporary variable to hold the data.  */
472           tmp = fold (build (MINUS_EXPR, TREE_TYPE (nelem), nelem,
473                              integer_one_node));
474           tmp = build_range_type (gfc_array_index_type, gfc_index_zero_node,
475                                   tmp);
476           tmp = build_array_type (gfc_get_element_type (TREE_TYPE (desc)),
477                                   tmp);
478           tmp = gfc_create_var (tmp, "A");
479           tmp = gfc_build_addr_expr (TREE_TYPE (data), tmp);
480           gfc_add_modify_expr (&loop->pre, data, tmp);
481           info->data = data;
482           info->offset = gfc_index_zero_node;
483
484         }
485       else
486         {
487           /* Allocate memory to hold the data.  */
488           args = gfc_chainon_list (NULL_TREE, size);
489
490           if (gfc_index_integer_kind == 4)
491             tmp = gfor_fndecl_internal_malloc;
492           else if (gfc_index_integer_kind == 8)
493             tmp = gfor_fndecl_internal_malloc64;
494           else
495             abort ();
496           tmp = gfc_build_function_call (tmp, args);
497           tmp = convert (TREE_TYPE (data), tmp);
498           gfc_add_modify_expr (&loop->pre, data, tmp);
499
500           info->data = data;
501           info->offset = gfc_index_zero_node;
502         }
503     }
504
505   /* The offset is zero because we create temporaries with a zero
506      lower bound.  */
507   tmp = gfc_conv_descriptor_offset (desc);
508   gfc_add_modify_expr (&loop->pre, tmp, gfc_index_zero_node);
509
510   if (!onstack)
511     {
512       /* Free the temporary.  */
513       tmp = convert (pvoid_type_node, info->data);
514       tmp = gfc_chainon_list (NULL_TREE, tmp);
515       tmp = gfc_build_function_call (gfor_fndecl_internal_free, tmp);
516       gfc_add_expr_to_block (&loop->post, tmp);
517     }
518 }
519
520
521 /* Generate code to allocate and initialize the descriptor for a temporary
522    array.  This is used for both temporaries needed by the scaparizer, and
523    functions returning arrays.  Adjusts the loop variables to be zero-based,
524    and calculates the loop bounds for callee allocated arrays.
525    Also fills in the descriptor, data and offset fields of info if known.
526    Returns the size of the array, or NULL for a callee allocated array.  */
527
528 tree
529 gfc_trans_allocate_temp_array (gfc_loopinfo * loop, gfc_ss_info * info,
530                                tree eltype, tree string_length)
531 {
532   tree type;
533   tree desc;
534   tree tmp;
535   tree size;
536   tree nelem;
537   int n;
538   int dim;
539
540   assert (info->dimen > 0);
541   /* Set the lower bound to zero.  */
542   for (dim = 0; dim < info->dimen; dim++)
543     {
544       n = loop->order[dim];
545       if (n < loop->temp_dim)
546         assert (integer_zerop (loop->from[n]));
547       else
548         {
549           /* Callee allocated arrays may not have a known bound yet.  */
550           if (loop->to[n])
551               loop->to[n] = fold (build (MINUS_EXPR, gfc_array_index_type,
552                                      loop->to[n], loop->from[n]));
553           loop->from[n] = gfc_index_zero_node;
554         }
555
556       info->delta[dim] = gfc_index_zero_node;
557       info->start[dim] = gfc_index_zero_node;
558       info->stride[dim] = gfc_index_one_node;
559       info->dim[dim] = dim;
560     }
561
562   /* Initialize the descriptor.  */
563   type =
564     gfc_get_array_type_bounds (eltype, info->dimen, loop->from, loop->to, 1);
565   desc = gfc_create_var (type, "atmp");
566   GFC_DECL_PACKED_ARRAY (desc) = 1;
567
568   info->descriptor = desc;
569   size = gfc_index_one_node;
570
571   /* Fill in the array dtype.  */
572   tmp = gfc_conv_descriptor_dtype (desc);
573   gfc_add_modify_expr (&loop->pre, tmp,
574                        GFC_TYPE_ARRAY_DTYPE (TREE_TYPE (desc)));
575
576   /*
577      Fill in the bounds and stride.  This is a packed array, so:
578
579      size = 1;
580      for (n = 0; n < rank; n++)
581        {
582          stride[n] = size
583          delta = ubound[n] + 1 - lbound[n];
584          size = size * delta;
585        }
586      size = size * sizeof(element);
587   */
588
589   for (n = 0; n < info->dimen; n++)
590     {
591       if (loop->to[n] == NULL_TREE)
592         {
593           /* For a callee allocated array express the loop bounds in terms
594              of the descriptor fields.  */
595           tmp = build (MINUS_EXPR, gfc_array_index_type,
596                        gfc_conv_descriptor_ubound (desc, gfc_rank_cst[n]),
597                        gfc_conv_descriptor_lbound (desc, gfc_rank_cst[n]));
598           loop->to[n] = tmp;
599           size = NULL_TREE;
600           continue;
601         }
602         
603       /* Store the stride and bound components in the descriptor.  */
604       tmp = gfc_conv_descriptor_stride (desc, gfc_rank_cst[n]);
605       gfc_add_modify_expr (&loop->pre, tmp, size);
606
607       tmp = gfc_conv_descriptor_lbound (desc, gfc_rank_cst[n]);
608       gfc_add_modify_expr (&loop->pre, tmp, gfc_index_zero_node);
609
610       tmp = gfc_conv_descriptor_ubound (desc, gfc_rank_cst[n]);
611       gfc_add_modify_expr (&loop->pre, tmp, loop->to[n]);
612
613       tmp = fold (build (PLUS_EXPR, gfc_array_index_type,
614                          loop->to[n], gfc_index_one_node));
615
616       size = fold (build (MULT_EXPR, gfc_array_index_type, size, tmp));
617       size = gfc_evaluate_now (size, &loop->pre);
618     }
619
620   /* TODO: Where does the string length go?  */
621   if (string_length)
622     gfc_todo_error ("temporary arrays of strings");
623
624   /* Get the size of the array.  */
625   nelem = size;
626   if (size)
627     size = fold (build (MULT_EXPR, gfc_array_index_type, size,
628                       TYPE_SIZE_UNIT (gfc_get_element_type (type))));
629
630   gfc_trans_allocate_array_storage (loop, info, size, nelem);
631
632   if (info->dimen > loop->temp_dim)
633     loop->temp_dim = info->dimen;
634
635   return size;
636 }
637
638
639 /* Make sure offset is a variable.  */
640
641 static void
642 gfc_put_offset_into_var (stmtblock_t * pblock, tree * poffset,
643                          tree * offsetvar)
644 {
645   /* We should have already created the offset variable.  We cannot
646      create it here because we may be in an inner scope.  */
647   assert (*offsetvar != NULL_TREE);
648   gfc_add_modify_expr (pblock, *offsetvar, *poffset);
649   *poffset = *offsetvar;
650   TREE_USED (*offsetvar) = 1;
651 }
652
653
654 /* Add the contents of an array to the constructor.  */
655
656 static void
657 gfc_trans_array_constructor_subarray (stmtblock_t * pblock,
658                                       tree type ATTRIBUTE_UNUSED,
659                                       tree pointer, gfc_expr * expr,
660                                       tree * poffset, tree * offsetvar)
661 {
662   gfc_se se;
663   gfc_ss *ss;
664   gfc_loopinfo loop;
665   stmtblock_t body;
666   tree tmp;
667
668   /* We need this to be a variable so we can increment it.  */
669   gfc_put_offset_into_var (pblock, poffset, offsetvar);
670
671   gfc_init_se (&se, NULL);
672
673   /* Walk the array expression.  */
674   ss = gfc_walk_expr (expr);
675   assert (ss != gfc_ss_terminator);
676
677   /* Initialize the scalarizer.  */
678   gfc_init_loopinfo (&loop);
679   gfc_add_ss_to_loop (&loop, ss);
680
681   /* Initialize the loop.  */
682   gfc_conv_ss_startstride (&loop);
683   gfc_conv_loop_setup (&loop);
684
685   /* Make the loop body.  */
686   gfc_mark_ss_chain_used (ss, 1);
687   gfc_start_scalarized_body (&loop, &body);
688   gfc_copy_loopinfo_to_se (&se, &loop);
689   se.ss = ss;
690
691   gfc_conv_expr (&se, expr);
692   gfc_add_block_to_block (&body, &se.pre);
693
694   /* Store the value.  */
695   tmp = gfc_build_indirect_ref (pointer);
696   tmp = gfc_build_array_ref (tmp, *poffset);
697   gfc_add_modify_expr (&body, tmp, se.expr);
698
699   /* Increment the offset.  */
700   tmp = build (PLUS_EXPR, gfc_array_index_type, *poffset, gfc_index_one_node);
701   gfc_add_modify_expr (&body, *poffset, tmp);
702
703   /* Finish the loop.  */
704   gfc_add_block_to_block (&body, &se.post);
705   assert (se.ss == gfc_ss_terminator);
706   gfc_trans_scalarizing_loops (&loop, &body);
707   gfc_add_block_to_block (&loop.pre, &loop.post);
708   tmp = gfc_finish_block (&loop.pre);
709   gfc_add_expr_to_block (pblock, tmp);
710
711   gfc_cleanup_loop (&loop);
712 }
713
714
715 /* Assign the values to the elements of an array constructor.  */
716
717 static void
718 gfc_trans_array_constructor_value (stmtblock_t * pblock, tree type,
719                                    tree pointer, gfc_constructor * c,
720                                    tree * poffset, tree * offsetvar)
721 {
722   tree tmp;
723   tree ref;
724   stmtblock_t body;
725   tree loopbody;
726   gfc_se se;
727
728   for (; c; c = c->next)
729     {
730       /* If this is an iterator or an array, the offset must be a variable.  */
731       if ((c->iterator || c->expr->rank > 0) && INTEGER_CST_P (*poffset))
732         gfc_put_offset_into_var (pblock, poffset, offsetvar);
733
734       gfc_start_block (&body);
735
736       if (c->expr->expr_type == EXPR_ARRAY)
737         {
738           /* Array constructors can be nested.  */
739           gfc_trans_array_constructor_value (&body, type, pointer,
740                                              c->expr->value.constructor,
741                                              poffset, offsetvar);
742         }
743       else if (c->expr->rank > 0)
744         {
745           gfc_trans_array_constructor_subarray (&body, type, pointer,
746                                                 c->expr, poffset, offsetvar);
747         }
748       else
749         {
750           /* This code really upsets the gimplifier so don't bother for now.  */
751           gfc_constructor *p;
752           HOST_WIDE_INT n;
753           HOST_WIDE_INT size;
754
755           p = c;
756           n = 0;
757           while (p && !(p->iterator || p->expr->expr_type != EXPR_CONSTANT))
758             {
759               p = p->next;
760               n++;
761             }
762           if (n < 4)
763             {
764               /* Scalar values.  */
765               gfc_init_se (&se, NULL);
766               gfc_conv_expr (&se, c->expr);
767               gfc_add_block_to_block (&body, &se.pre);
768
769               ref = gfc_build_indirect_ref (pointer);
770               ref = gfc_build_array_ref (ref, *poffset);
771               gfc_add_modify_expr (&body, ref,
772                                    fold_convert (TREE_TYPE (ref), se.expr));
773               gfc_add_block_to_block (&body, &se.post);
774
775               *poffset = fold (build (PLUS_EXPR, gfc_array_index_type,
776                                       *poffset, gfc_index_one_node));
777             }
778           else
779             {
780               /* Collect multiple scalar constants into a constructor.  */
781               tree list;
782               tree init;
783               tree bound;
784               tree tmptype;
785
786               p = c;
787               list = NULL_TREE;
788               /* Count the number of consecutive scalar constants.  */
789               while (p && !(p->iterator
790                             || p->expr->expr_type != EXPR_CONSTANT))
791                 {
792                   gfc_init_se (&se, NULL);
793                   gfc_conv_constant (&se, p->expr);
794                   list = tree_cons (NULL_TREE, se.expr, list);
795                   c = p;
796                   p = p->next;
797                 }
798
799               bound = build_int_2 (n - 1, 0);
800               /* Create an array type to hold them.  */
801               tmptype = build_range_type (gfc_array_index_type,
802                                           gfc_index_zero_node, bound);
803               tmptype = build_array_type (type, tmptype);
804
805               init = build1 (CONSTRUCTOR, tmptype, nreverse (list));
806               TREE_CONSTANT (init) = 1;
807               TREE_INVARIANT (init) = 1;
808               TREE_STATIC (init) = 1;
809               /* Create a static variable to hold the data.  */
810               tmp = gfc_create_var (tmptype, "data");
811               TREE_STATIC (tmp) = 1;
812               TREE_CONSTANT (tmp) = 1;
813               TREE_INVARIANT (tmp) = 1;
814               DECL_INITIAL (tmp) = init;
815               init = tmp;
816
817               /* Use BUILTIN_MEMCPY to assign the values.  */
818               tmp = gfc_build_indirect_ref (pointer);
819               tmp = gfc_build_array_ref (tmp, *poffset);
820               tmp = gfc_build_addr_expr (NULL, tmp);
821               init = gfc_build_addr_expr (NULL, init);
822
823               size = TREE_INT_CST_LOW (TYPE_SIZE_UNIT (type));
824               bound = build_int_2 (n * size, 0);
825               tmp = gfc_chainon_list (NULL_TREE, tmp);
826               tmp = gfc_chainon_list (tmp, init);
827               tmp = gfc_chainon_list (tmp, bound);
828               tmp = gfc_build_function_call (built_in_decls[BUILT_IN_MEMCPY],
829                                              tmp);
830               gfc_add_expr_to_block (&body, tmp);
831
832               *poffset = fold (build (PLUS_EXPR, gfc_array_index_type,
833                                       *poffset, bound));
834             }
835           if (!INTEGER_CST_P (*poffset))
836             {
837               gfc_add_modify_expr (&body, *offsetvar, *poffset);
838               *poffset = *offsetvar;
839             }
840         }
841
842       /* The frontend should already have done any expansions.  */
843       if (c->iterator)
844         {
845           tree end;
846           tree step;
847           tree loopvar;
848           tree exit_label;
849
850           loopbody = gfc_finish_block (&body);
851
852           gfc_init_se (&se, NULL);
853           gfc_conv_expr (&se, c->iterator->var);
854           gfc_add_block_to_block (pblock, &se.pre);
855           loopvar = se.expr;
856
857           /* Initialize the loop.  */
858           gfc_init_se (&se, NULL);
859           gfc_conv_expr_val (&se, c->iterator->start);
860           gfc_add_block_to_block (pblock, &se.pre);
861           gfc_add_modify_expr (pblock, loopvar, se.expr);
862
863           gfc_init_se (&se, NULL);
864           gfc_conv_expr_val (&se, c->iterator->end);
865           gfc_add_block_to_block (pblock, &se.pre);
866           end = gfc_evaluate_now (se.expr, pblock);
867
868           gfc_init_se (&se, NULL);
869           gfc_conv_expr_val (&se, c->iterator->step);
870           gfc_add_block_to_block (pblock, &se.pre);
871           step = gfc_evaluate_now (se.expr, pblock);
872
873           /* Generate the loop body.  */
874           exit_label = gfc_build_label_decl (NULL_TREE);
875           gfc_start_block (&body);
876
877           /* Generate the exit condition.  */
878           end = build (GT_EXPR, boolean_type_node, loopvar, end);
879           tmp = build1_v (GOTO_EXPR, exit_label);
880           TREE_USED (exit_label) = 1;
881           tmp = build_v (COND_EXPR, end, tmp, build_empty_stmt ());
882           gfc_add_expr_to_block (&body, tmp);
883
884           /* The main loop body.  */
885           gfc_add_expr_to_block (&body, loopbody);
886
887           /* Increment the loop variable.  */
888           tmp = build (PLUS_EXPR, TREE_TYPE (loopvar), loopvar, step);
889           gfc_add_modify_expr (&body, loopvar, tmp);
890
891           /* Finish the loop.  */
892           tmp = gfc_finish_block (&body);
893           tmp = build_v (LOOP_EXPR, tmp);
894           gfc_add_expr_to_block (pblock, tmp);
895
896           /* Add the exit label.  */
897           tmp = build1_v (LABEL_EXPR, exit_label);
898           gfc_add_expr_to_block (pblock, tmp);
899         }
900       else
901         {
902           /* Pass the code as is.  */
903           tmp = gfc_finish_block (&body);
904           gfc_add_expr_to_block (pblock, tmp);
905         }
906     }
907 }
908
909
910 /* Get the size of an expression.  Returns -1 if the size isn't constant.
911    Implied do loops with non-constant bounds are tricky because we must only
912    evaluate the bounds once.  */
913
914 static void
915 gfc_get_array_cons_size (mpz_t * size, gfc_constructor * c)
916 {
917   gfc_iterator *i;
918   mpz_t val;
919   mpz_t len;
920
921   mpz_set_ui (*size, 0);
922   mpz_init (len);
923   mpz_init (val);
924
925   for (; c; c = c->next)
926     {
927       if (c->expr->expr_type == EXPR_ARRAY)
928         {
929           /* A nested array constructor.  */
930           gfc_get_array_cons_size (&len, c->expr->value.constructor);
931           if (mpz_sgn (len) < 0)
932             {
933               mpz_set (*size, len);
934               mpz_clear (len);
935               mpz_clear (val);
936               return;
937             }
938         }
939       else
940         {
941           if (c->expr->rank > 0)
942             {
943               mpz_set_si (*size, -1);
944               mpz_clear (len);
945               mpz_clear (val);
946               return;
947             }
948           mpz_set_ui (len, 1);
949         }
950
951       if (c->iterator)
952         {
953           i = c->iterator;
954
955           if (i->start->expr_type != EXPR_CONSTANT
956               || i->end->expr_type != EXPR_CONSTANT
957               || i->step->expr_type != EXPR_CONSTANT)
958             {
959               mpz_set_si (*size, -1);
960               mpz_clear (len);
961               mpz_clear (val);
962               return;
963             }
964
965           mpz_add (val, i->end->value.integer, i->start->value.integer);
966           mpz_tdiv_q (val, val, i->step->value.integer);
967           mpz_add_ui (val, val, 1);
968           mpz_mul (len, len, val);
969         }
970       mpz_add (*size, *size, len);
971     }
972   mpz_clear (len);
973   mpz_clear (val);
974 }
975
976
977 /* Array constructors are handled by constructing a temporary, then using that
978    within the scalarization loop.  This is not optimal, but seems by far the
979    simplest method.  */
980
981 static void
982 gfc_trans_array_constructor (gfc_loopinfo * loop, gfc_ss * ss)
983 {
984   tree offset;
985   tree offsetvar;
986   tree desc;
987   tree size;
988   tree type;
989
990   if (ss->expr->ts.type == BT_CHARACTER)
991     gfc_todo_error ("Character string array constructors");
992   type = gfc_typenode_for_spec (&ss->expr->ts);
993   ss->data.info.dimen = loop->dimen;
994   size =
995     gfc_trans_allocate_temp_array (loop, &ss->data.info, type, NULL_TREE);
996
997   desc = ss->data.info.descriptor;
998   offset = gfc_index_zero_node;
999   offsetvar = gfc_create_var_np (gfc_array_index_type, "offset");
1000   TREE_USED (offsetvar) = 0;
1001   gfc_trans_array_constructor_value (&loop->pre, type,
1002                                      ss->data.info.data,
1003                                      ss->expr->value.constructor, &offset,
1004                                      &offsetvar);
1005
1006   if (TREE_USED (offsetvar))
1007     pushdecl (offsetvar);
1008   else
1009     assert (INTEGER_CST_P (offset));
1010 #if 0
1011   /* Disable bound checking for now because it's probably broken.  */
1012   if (flag_bounds_check)
1013     {
1014       abort ();
1015     }
1016 #endif
1017 }
1018
1019
1020 /* Add the pre and post chains for all the scalar expressions in a SS chain
1021    to loop.  This is called after the loop parameters have been calculated,
1022    but before the actual scalarizing loops.  */
1023
1024 static void
1025 gfc_add_loop_ss_code (gfc_loopinfo * loop, gfc_ss * ss, bool subscript)
1026 {
1027   gfc_se se;
1028   int n;
1029
1030   /* TODO: This can generate bad code if there are ordering dependencies.
1031      eg. a callee allocated function and an unknown size constructor.  */
1032   assert (ss != NULL);
1033
1034   for (; ss != gfc_ss_terminator; ss = ss->loop_chain)
1035     {
1036       assert (ss);
1037
1038       switch (ss->type)
1039         {
1040         case GFC_SS_SCALAR:
1041           /* Scalar expression.  Evaluate this now.  This includes elemental
1042              dimension indices, but not array section bounds.  */
1043           gfc_init_se (&se, NULL);
1044           gfc_conv_expr (&se, ss->expr);
1045           gfc_add_block_to_block (&loop->pre, &se.pre);
1046
1047           if (ss->expr->ts.type != BT_CHARACTER)
1048             {
1049               /* Move the evaluation of scalar expressions outside the
1050                  scalarization loop.  */
1051               if (subscript)
1052                 se.expr = convert(gfc_array_index_type, se.expr);
1053               se.expr = gfc_evaluate_now (se.expr, &loop->pre);
1054               gfc_add_block_to_block (&loop->pre, &se.post);
1055             }
1056           else
1057             gfc_add_block_to_block (&loop->post, &se.post);
1058
1059           ss->data.scalar.expr = se.expr;
1060           ss->data.scalar.string_length = se.string_length;
1061           break;
1062
1063         case GFC_SS_REFERENCE:
1064           /* Scalar reference.  Evaluate this now.  */
1065           gfc_init_se (&se, NULL);
1066           gfc_conv_expr_reference (&se, ss->expr);
1067           gfc_add_block_to_block (&loop->pre, &se.pre);
1068           gfc_add_block_to_block (&loop->post, &se.post);
1069
1070           ss->data.scalar.expr = gfc_evaluate_now (se.expr, &loop->pre);
1071           ss->data.scalar.string_length = se.string_length;
1072           break;
1073
1074         case GFC_SS_SECTION:
1075         case GFC_SS_VECTOR:
1076           /* Scalarized expression.  Evaluate any scalar subscripts.  */
1077           for (n = 0; n < GFC_MAX_DIMENSIONS; n++)
1078             {
1079               /* Add the expressions for scalar subscripts.  */
1080               if (ss->data.info.subscript[n])
1081                 gfc_add_loop_ss_code (loop, ss->data.info.subscript[n], true);
1082             }
1083           break;
1084
1085         case GFC_SS_INTRINSIC:
1086           gfc_add_intrinsic_ss_code (loop, ss);
1087           break;
1088
1089         case GFC_SS_FUNCTION:
1090           /* Array function return value.  We call the function and save its
1091              result in a temporary for use inside the loop.  */
1092           gfc_init_se (&se, NULL);
1093           se.loop = loop;
1094           se.ss = ss;
1095           gfc_conv_expr (&se, ss->expr);
1096           gfc_add_block_to_block (&loop->pre, &se.pre);
1097           gfc_add_block_to_block (&loop->post, &se.post);
1098           break;
1099
1100         case GFC_SS_CONSTRUCTOR:
1101           gfc_trans_array_constructor (loop, ss);
1102           break;
1103
1104         case GFC_SS_TEMP:
1105         case GFC_SS_COMPONENT:
1106           /* Do nothing.  These are handled elsewhere.  */
1107           break;
1108
1109         default:
1110           abort ();
1111         }
1112     }
1113 }
1114
1115
1116 /* Translate expressions for the descriptor and data pointer of a SS.  */
1117 /*GCC ARRAYS*/
1118
1119 static void
1120 gfc_conv_ss_descriptor (stmtblock_t * block, gfc_ss * ss, int base)
1121 {
1122   gfc_se se;
1123   tree tmp;
1124
1125   /* Get the descriptor for the array to be scalarized.  */
1126   assert (ss->expr->expr_type == EXPR_VARIABLE);
1127   gfc_init_se (&se, NULL);
1128   se.descriptor_only = 1;
1129   gfc_conv_expr_lhs (&se, ss->expr);
1130   gfc_add_block_to_block (block, &se.pre);
1131   ss->data.info.descriptor = se.expr;
1132
1133   if (base)
1134     {
1135       /* Also the data pointer.  */
1136       tmp = gfc_conv_array_data (se.expr);
1137       /* If this is a variable or address of a variable we use it directly.
1138          Otherwise we must evaluate it now to to avoid break dependency
1139          analysis by pulling the expressions for elemental array indices
1140          inside the loop.  */
1141       if (!(DECL_P (tmp)
1142             || (TREE_CODE (tmp) == ADDR_EXPR
1143                 && DECL_P (TREE_OPERAND (tmp, 0)))))
1144         tmp = gfc_evaluate_now (tmp, block);
1145       ss->data.info.data = tmp;
1146
1147       tmp = gfc_conv_array_offset (se.expr);
1148       ss->data.info.offset = gfc_evaluate_now (tmp, block);
1149     }
1150 }
1151
1152
1153 /* Initialise a gfc_loopinfo structure.  */
1154
1155 void
1156 gfc_init_loopinfo (gfc_loopinfo * loop)
1157 {
1158   int n;
1159
1160   memset (loop, 0, sizeof (gfc_loopinfo));
1161   gfc_init_block (&loop->pre);
1162   gfc_init_block (&loop->post);
1163
1164   /* Initially scalarize in order.  */
1165   for (n = 0; n < GFC_MAX_DIMENSIONS; n++)
1166     loop->order[n] = n;
1167
1168   loop->ss = gfc_ss_terminator;
1169 }
1170
1171
1172 /* Copies the loop variable info to a gfc_se sructure. Does not copy the SS
1173    chain.  */
1174
1175 void
1176 gfc_copy_loopinfo_to_se (gfc_se * se, gfc_loopinfo * loop)
1177 {
1178   se->loop = loop;
1179 }
1180
1181
1182 /* Return an expression for the data pointer of an array.  */
1183
1184 tree
1185 gfc_conv_array_data (tree descriptor)
1186 {
1187   tree type;
1188
1189   type = TREE_TYPE (descriptor);
1190   if (GFC_ARRAY_TYPE_P (type))
1191     {
1192       if (TREE_CODE (type) == POINTER_TYPE)
1193         return descriptor;
1194       else
1195         {
1196           /* Descriptorless arrays.  */
1197           return gfc_build_addr_expr (NULL, descriptor);
1198         }
1199     }
1200   else
1201     return gfc_conv_descriptor_data (descriptor);
1202 }
1203
1204
1205 /* Return an expression for the base offset of an array.  */
1206
1207 tree
1208 gfc_conv_array_offset (tree descriptor)
1209 {
1210   tree type;
1211
1212   type = TREE_TYPE (descriptor);
1213   if (GFC_ARRAY_TYPE_P (type))
1214     return GFC_TYPE_ARRAY_OFFSET (type);
1215   else
1216     return gfc_conv_descriptor_offset (descriptor);
1217 }
1218
1219
1220 /* Get an expression for the array stride.  */
1221
1222 tree
1223 gfc_conv_array_stride (tree descriptor, int dim)
1224 {
1225   tree tmp;
1226   tree type;
1227
1228   type = TREE_TYPE (descriptor);
1229
1230   /* For descriptorless arrays use the array size.  */
1231   tmp = GFC_TYPE_ARRAY_STRIDE (type, dim);
1232   if (tmp != NULL_TREE)
1233     return tmp;
1234
1235   tmp = gfc_conv_descriptor_stride (descriptor, gfc_rank_cst[dim]);
1236   return tmp;
1237 }
1238
1239
1240 /* Like gfc_conv_array_stride, but for the lower bound.  */
1241
1242 tree
1243 gfc_conv_array_lbound (tree descriptor, int dim)
1244 {
1245   tree tmp;
1246   tree type;
1247
1248   type = TREE_TYPE (descriptor);
1249
1250   tmp = GFC_TYPE_ARRAY_LBOUND (type, dim);
1251   if (tmp != NULL_TREE)
1252     return tmp;
1253
1254   tmp = gfc_conv_descriptor_lbound (descriptor, gfc_rank_cst[dim]);
1255   return tmp;
1256 }
1257
1258
1259 /* Like gfc_conv_array_stride, but for the upper bound.  */
1260
1261 tree
1262 gfc_conv_array_ubound (tree descriptor, int dim)
1263 {
1264   tree tmp;
1265   tree type;
1266
1267   type = TREE_TYPE (descriptor);
1268
1269   tmp = GFC_TYPE_ARRAY_UBOUND (type, dim);
1270   if (tmp != NULL_TREE)
1271     return tmp;
1272
1273   /* This should only ever happen when passing an assumed shape array
1274      as an actual parameter.  The value will never be used.  */
1275   if (GFC_ARRAY_TYPE_P (TREE_TYPE (descriptor)))
1276     return gfc_index_zero_node;
1277
1278   tmp = gfc_conv_descriptor_ubound (descriptor, gfc_rank_cst[dim]);
1279   return tmp;
1280 }
1281
1282
1283 /* Translate an array reference.  The descriptor should be in se->expr.
1284    Do not use this function, it wil be removed soon.  */
1285 /*GCC ARRAYS*/
1286
1287 static void
1288 gfc_conv_array_index_ref (gfc_se * se, tree pointer, tree * indices,
1289                          tree offset, int dimen)
1290 {
1291   tree array;
1292   tree tmp;
1293   tree index;
1294   int n;
1295
1296   array = gfc_build_indirect_ref (pointer);
1297
1298   index = offset;
1299   for (n = 0; n < dimen; n++)
1300     {
1301       /* index = index + stride[n]*indices[n] */
1302       tmp = gfc_conv_array_stride (se->expr, n);
1303       tmp = fold (build (MULT_EXPR, gfc_array_index_type, indices[n], tmp));
1304
1305       index = fold (build (PLUS_EXPR, gfc_array_index_type, index, tmp));
1306     }
1307
1308   /* Result = data[index].  */
1309   tmp = gfc_build_array_ref (array, index);
1310
1311   /* Check we've used the correct number of dimensions.  */
1312   assert (TREE_CODE (TREE_TYPE (tmp)) != ARRAY_TYPE);
1313
1314   se->expr = tmp;
1315 }
1316
1317
1318 /* Generate code to perform an array index bound check.  */
1319
1320 static tree
1321 gfc_trans_array_bound_check (gfc_se * se, tree descriptor, tree index, int n)
1322 {
1323   tree cond;
1324   tree fault;
1325   tree tmp;
1326
1327   if (!flag_bounds_check)
1328     return index;
1329
1330   index = gfc_evaluate_now (index, &se->pre);
1331   /* Check lower bound.  */
1332   tmp = gfc_conv_array_lbound (descriptor, n);
1333   fault = fold (build (LT_EXPR, boolean_type_node, index, tmp));
1334   /* Check upper bound.  */
1335   tmp = gfc_conv_array_ubound (descriptor, n);
1336   cond = fold (build (GT_EXPR, boolean_type_node, index, tmp));
1337   fault = fold (build (TRUTH_OR_EXPR, boolean_type_node, fault, cond));
1338
1339   gfc_trans_runtime_check (fault, gfc_strconst_fault, &se->pre);
1340
1341   return index;
1342 }
1343
1344
1345 /* A reference to an array vector subscript.  Uses recursion to handle nested
1346    vector subscripts.  */
1347
1348 static tree
1349 gfc_conv_vector_array_index (gfc_se * se, tree index, gfc_ss * ss)
1350 {
1351   tree descsave;
1352   tree indices[GFC_MAX_DIMENSIONS];
1353   gfc_array_ref *ar;
1354   gfc_ss_info *info;
1355   int n;
1356
1357   assert (ss && ss->type == GFC_SS_VECTOR);
1358
1359   /* Save the descriptor.  */
1360   descsave = se->expr;
1361   info = &ss->data.info;
1362   se->expr = info->descriptor;
1363
1364   ar = &info->ref->u.ar;
1365   for (n = 0; n < ar->dimen; n++)
1366     {
1367       switch (ar->dimen_type[n])
1368         {
1369         case DIMEN_ELEMENT:
1370           assert (info->subscript[n] != gfc_ss_terminator
1371                   && info->subscript[n]->type == GFC_SS_SCALAR);
1372           indices[n] = info->subscript[n]->data.scalar.expr;
1373           break;
1374
1375         case DIMEN_RANGE:
1376           indices[n] = index;
1377           break;
1378
1379         case DIMEN_VECTOR:
1380           index = gfc_conv_vector_array_index (se, index, info->subscript[n]);
1381
1382           indices[n] =
1383             gfc_trans_array_bound_check (se, info->descriptor, index, n);
1384           break;
1385
1386         default:
1387           abort ();
1388         }
1389     }
1390   /* Get the index from the vector.  */
1391   gfc_conv_array_index_ref (se, info->data, indices, info->offset, ar->dimen);
1392   index = se->expr;
1393   /* Put the descriptor back.  */
1394   se->expr = descsave;
1395
1396   return index;
1397 }
1398
1399
1400 /* Return the offset for an index.  Performs bound checking for elemental
1401    dimensions.  Single element references are processed seperately.  */
1402
1403 static tree
1404 gfc_conv_array_index_offset (gfc_se * se, gfc_ss_info * info, int dim, int i,
1405                              gfc_array_ref * ar, tree stride)
1406 {
1407   tree index;
1408
1409   /* Get the index into the array for this dimension.  */
1410   if (ar)
1411     {
1412       assert (ar->type != AR_ELEMENT);
1413       if (ar->dimen_type[dim] == DIMEN_ELEMENT)
1414         {
1415           assert (i == -1);
1416           /* Elemental dimension.  */
1417           assert (info->subscript[dim]
1418                   && info->subscript[dim]->type == GFC_SS_SCALAR);
1419           /* We've already translated this value outside the loop.  */
1420           index = info->subscript[dim]->data.scalar.expr;
1421
1422           index =
1423             gfc_trans_array_bound_check (se, info->descriptor, index, dim);
1424         }
1425       else
1426         {
1427           /* Scalarized dimension.  */
1428           assert (info && se->loop);
1429
1430           /* Multiply the loop variable by the stride and dela.  */
1431           index = se->loop->loopvar[i];
1432           index = fold (build (MULT_EXPR, gfc_array_index_type, index,
1433                                info->stride[i]));
1434           index = fold (build (PLUS_EXPR, gfc_array_index_type, index,
1435                                info->delta[i]));
1436
1437           if (ar->dimen_type[dim] == DIMEN_VECTOR)
1438             {
1439               /* Handle vector subscripts.  */
1440               index = gfc_conv_vector_array_index (se, index,
1441                                                    info->subscript[dim]);
1442               index =
1443                 gfc_trans_array_bound_check (se, info->descriptor, index,
1444                                              dim);
1445             }
1446           else
1447             assert (ar->dimen_type[dim] == DIMEN_RANGE);
1448         }
1449     }
1450   else
1451     {
1452       /* Temporary array or derived type component.  */
1453       assert (se->loop);
1454       index = se->loop->loopvar[se->loop->order[i]];
1455       if (!integer_zerop (info->delta[i]))
1456         index = fold (build (PLUS_EXPR, gfc_array_index_type, index,
1457                              info->delta[i]));
1458     }
1459
1460   /* Multiply by the stride.  */
1461   index = fold (build (MULT_EXPR, gfc_array_index_type, index, stride));
1462
1463   return index;
1464 }
1465
1466
1467 /* Build a scalarized reference to an array.  */
1468
1469 static void
1470 gfc_conv_scalarized_array_ref (gfc_se * se, gfc_array_ref * ar)
1471 {
1472   gfc_ss_info *info;
1473   tree index;
1474   tree tmp;
1475   int n;
1476
1477   info = &se->ss->data.info;
1478   if (ar)
1479     n = se->loop->order[0];
1480   else
1481     n = 0;
1482
1483   index = gfc_conv_array_index_offset (se, info, info->dim[n], n, ar,
1484                                        info->stride0);
1485   /* Add the offset for this dimension to the stored offset for all other
1486      dimensions.  */
1487   index = fold (build (PLUS_EXPR, gfc_array_index_type, index, info->offset));
1488
1489   tmp = gfc_build_indirect_ref (info->data);
1490   se->expr = gfc_build_array_ref (tmp, index);
1491 }
1492
1493
1494 /* Translate access of temporary array.  */
1495
1496 void
1497 gfc_conv_tmp_array_ref (gfc_se * se)
1498 {
1499   tree desc;
1500
1501   desc = se->ss->data.info.descriptor;
1502   /* TODO: We need the string length for string variables.  */
1503
1504   gfc_conv_scalarized_array_ref (se, NULL);
1505 }
1506
1507
1508 /* Build an array reference.  se->expr already holds the array descriptor.
1509    This should be either a variable, indirect variable reference or component
1510    reference.  For arrays which do not have a descriptor, se->expr will be
1511    the data pointer.
1512    a(i, j, k) = base[offset + i * stride[0] + j * stride[1] + k * stride[2]]*/
1513
1514 void
1515 gfc_conv_array_ref (gfc_se * se, gfc_array_ref * ar)
1516 {
1517   int n;
1518   tree index;
1519   tree tmp;
1520   tree stride;
1521   tree fault;
1522   gfc_se indexse;
1523
1524   /* Handle scalarized references seperately.  */
1525   if (ar->type != AR_ELEMENT)
1526     {
1527       gfc_conv_scalarized_array_ref (se, ar);
1528       return;
1529     }
1530
1531   index = gfc_index_zero_node;
1532
1533   fault = gfc_index_zero_node;
1534
1535   /* Calculate the offsets from all the dimensions.  */
1536   for (n = 0; n < ar->dimen; n++)
1537     {
1538       /* Calculate the index for this demension.  */
1539       gfc_init_se (&indexse, NULL);
1540       gfc_conv_expr_type (&indexse, ar->start[n], gfc_array_index_type);
1541       gfc_add_block_to_block (&se->pre, &indexse.pre);
1542
1543       if (flag_bounds_check)
1544         {
1545           /* Check array bounds.  */
1546           tree cond;
1547
1548           indexse.expr = gfc_evaluate_now (indexse.expr, &se->pre);
1549
1550           tmp = gfc_conv_array_lbound (se->expr, n);
1551           cond = fold (build (LT_EXPR, boolean_type_node, indexse.expr, tmp));
1552           fault =
1553             fold (build (TRUTH_OR_EXPR, boolean_type_node, fault, cond));
1554
1555           tmp = gfc_conv_array_ubound (se->expr, n);
1556           cond = fold (build (GT_EXPR, boolean_type_node, indexse.expr, tmp));
1557           fault =
1558             fold (build (TRUTH_OR_EXPR, boolean_type_node, fault, cond));
1559         }
1560
1561       /* Multiply the index by the stride.  */
1562       stride = gfc_conv_array_stride (se->expr, n);
1563       tmp = fold (build (MULT_EXPR, gfc_array_index_type, indexse.expr,
1564                          stride));
1565
1566       /* And add it to the total.  */
1567       index = fold (build (PLUS_EXPR, gfc_array_index_type, index, tmp));
1568     }
1569
1570   if (flag_bounds_check)
1571     gfc_trans_runtime_check (fault, gfc_strconst_fault, &se->pre);
1572
1573   tmp = gfc_conv_array_offset (se->expr);
1574   if (!integer_zerop (tmp))
1575     index = fold (build (PLUS_EXPR, gfc_array_index_type, index, tmp));
1576       
1577   /* Access the calculated element.  */
1578   tmp = gfc_conv_array_data (se->expr);
1579   tmp = gfc_build_indirect_ref (tmp);
1580   se->expr = gfc_build_array_ref (tmp, index);
1581 }
1582
1583
1584 /* Generate the code to be executed immediately before entering a
1585    scalarization loop.  */
1586
1587 static void
1588 gfc_trans_preloop_setup (gfc_loopinfo * loop, int dim, int flag,
1589                          stmtblock_t * pblock)
1590 {
1591   tree index;
1592   tree stride;
1593   gfc_ss_info *info;
1594   gfc_ss *ss;
1595   gfc_se se;
1596   int i;
1597
1598   /* This code will be executed before entering the scalarization loop
1599      for this dimension.  */
1600   for (ss = loop->ss; ss != gfc_ss_terminator; ss = ss->loop_chain)
1601     {
1602       if ((ss->useflags & flag) == 0)
1603         continue;
1604
1605       if (ss->type != GFC_SS_SECTION
1606           && ss->type != GFC_SS_FUNCTION && ss->type != GFC_SS_CONSTRUCTOR
1607           && ss->type != GFC_SS_COMPONENT)
1608         continue;
1609
1610       info = &ss->data.info;
1611
1612       if (dim >= info->dimen)
1613         continue;
1614
1615       if (dim == info->dimen - 1)
1616         {
1617           /* For the outermost loop calculate the offset due to any
1618              elemental dimensions.  It will have been initialized with the
1619              base offset of the array.  */
1620           if (info->ref)
1621             {
1622               for (i = 0; i < info->ref->u.ar.dimen; i++)
1623                 {
1624                   if (info->ref->u.ar.dimen_type[i] != DIMEN_ELEMENT)
1625                     continue;
1626
1627                   gfc_init_se (&se, NULL);
1628                   se.loop = loop;
1629                   se.expr = info->descriptor;
1630                   stride = gfc_conv_array_stride (info->descriptor, i);
1631                   index = gfc_conv_array_index_offset (&se, info, i, -1,
1632                                                        &info->ref->u.ar,
1633                                                        stride);
1634                   gfc_add_block_to_block (pblock, &se.pre);
1635
1636                   info->offset = fold (build (PLUS_EXPR, gfc_array_index_type,
1637                                               info->offset, index));
1638                   info->offset = gfc_evaluate_now (info->offset, pblock);
1639                 }
1640
1641               i = loop->order[0];
1642               stride = gfc_conv_array_stride (info->descriptor, info->dim[i]);
1643             }
1644           else
1645             stride = gfc_conv_array_stride (info->descriptor, 0);
1646
1647           /* Calculate the stride of the innermost loop.  Hopefully this will
1648              allow the backend optimizers to do their stuff more effectively.
1649            */
1650           info->stride0 = gfc_evaluate_now (stride, pblock);
1651         }
1652       else
1653         {
1654           /* Add the offset for the previous loop dimension.  */
1655           gfc_array_ref *ar;
1656
1657           if (info->ref)
1658             {
1659               ar = &info->ref->u.ar;
1660               i = loop->order[dim + 1];
1661             }
1662           else
1663             {
1664               ar = NULL;
1665               i = dim + 1;
1666             }
1667
1668           gfc_init_se (&se, NULL);
1669           se.loop = loop;
1670           se.expr = info->descriptor;
1671           stride = gfc_conv_array_stride (info->descriptor, info->dim[i]);
1672           index = gfc_conv_array_index_offset (&se, info, info->dim[i], i,
1673                                                ar, stride);
1674           gfc_add_block_to_block (pblock, &se.pre);
1675           info->offset = fold (build (PLUS_EXPR, gfc_array_index_type,
1676                                       info->offset, index));
1677           info->offset = gfc_evaluate_now (info->offset, pblock);
1678         }
1679
1680       /* Remeber this offset for the second loop.  */
1681       if (dim == loop->temp_dim - 1)
1682         info->saved_offset = info->offset;
1683     }
1684 }
1685
1686
1687 /* Start a scalarized expression.  Creates a scope and declares loop
1688    variables.  */
1689
1690 void
1691 gfc_start_scalarized_body (gfc_loopinfo * loop, stmtblock_t * pbody)
1692 {
1693   int dim;
1694   int n;
1695   int flags;
1696
1697   assert (!loop->array_parameter);
1698
1699   for (dim = loop->dimen - 1; dim >= 0; dim--)
1700     {
1701       n = loop->order[dim];
1702
1703       gfc_start_block (&loop->code[n]);
1704
1705       /* Create the loop variable.  */
1706       loop->loopvar[n] = gfc_create_var (gfc_array_index_type, "S");
1707
1708       if (dim < loop->temp_dim)
1709         flags = 3;
1710       else
1711         flags = 1;
1712       /* Calculate values that will be constant within this loop.  */
1713       gfc_trans_preloop_setup (loop, dim, flags, &loop->code[n]);
1714     }
1715   gfc_start_block (pbody);
1716 }
1717
1718
1719 /* Generates the actual loop code for a scalarization loop.  */
1720
1721 static void
1722 gfc_trans_scalarized_loop_end (gfc_loopinfo * loop, int n,
1723                                stmtblock_t * pbody)
1724 {
1725   stmtblock_t block;
1726   tree cond;
1727   tree tmp;
1728   tree loopbody;
1729   tree exit_label;
1730
1731   loopbody = gfc_finish_block (pbody);
1732
1733   /* Initialize the loopvar.  */
1734   gfc_add_modify_expr (&loop->code[n], loop->loopvar[n], loop->from[n]);
1735
1736   exit_label = gfc_build_label_decl (NULL_TREE);
1737
1738   /* Generate the loop body.  */
1739   gfc_init_block (&block);
1740
1741   /* The exit condition.  */
1742   cond = build (GT_EXPR, boolean_type_node, loop->loopvar[n], loop->to[n]);
1743   tmp = build1_v (GOTO_EXPR, exit_label);
1744   TREE_USED (exit_label) = 1;
1745   tmp = build_v (COND_EXPR, cond, tmp, build_empty_stmt ());
1746   gfc_add_expr_to_block (&block, tmp);
1747
1748   /* The main body.  */
1749   gfc_add_expr_to_block (&block, loopbody);
1750
1751   /* Increment the loopvar.  */
1752   tmp = build (PLUS_EXPR, gfc_array_index_type,
1753                loop->loopvar[n], gfc_index_one_node);
1754   gfc_add_modify_expr (&block, loop->loopvar[n], tmp);
1755
1756   /* Build the loop.  */
1757   tmp = gfc_finish_block (&block);
1758   tmp = build_v (LOOP_EXPR, tmp);
1759   gfc_add_expr_to_block (&loop->code[n], tmp);
1760
1761   /* Add the exit label.  */
1762   tmp = build1_v (LABEL_EXPR, exit_label);
1763   gfc_add_expr_to_block (&loop->code[n], tmp);
1764 }
1765
1766
1767 /* Finishes and generates the loops for a scalarized expression.  */
1768
1769 void
1770 gfc_trans_scalarizing_loops (gfc_loopinfo * loop, stmtblock_t * body)
1771 {
1772   int dim;
1773   int n;
1774   gfc_ss *ss;
1775   stmtblock_t *pblock;
1776   tree tmp;
1777
1778   pblock = body;
1779   /* Generate the loops.  */
1780   for (dim = 0; dim < loop->dimen; dim++)
1781     {
1782       n = loop->order[dim];
1783       gfc_trans_scalarized_loop_end (loop, n, pblock);
1784       loop->loopvar[n] = NULL_TREE;
1785       pblock = &loop->code[n];
1786     }
1787
1788   tmp = gfc_finish_block (pblock);
1789   gfc_add_expr_to_block (&loop->pre, tmp);
1790
1791   /* Clear all the used flags.  */
1792   for (ss = loop->ss; ss; ss = ss->loop_chain)
1793     ss->useflags = 0;
1794 }
1795
1796
1797 /* Finish the main body of a scalarized expression, and start the secondary
1798    copying body.  */
1799
1800 void
1801 gfc_trans_scalarized_loop_boundary (gfc_loopinfo * loop, stmtblock_t * body)
1802 {
1803   int dim;
1804   int n;
1805   stmtblock_t *pblock;
1806   gfc_ss *ss;
1807
1808   pblock = body;
1809   /* We finish as many loops as are used by the temporary.  */
1810   for (dim = 0; dim < loop->temp_dim - 1; dim++)
1811     {
1812       n = loop->order[dim];
1813       gfc_trans_scalarized_loop_end (loop, n, pblock);
1814       loop->loopvar[n] = NULL_TREE;
1815       pblock = &loop->code[n];
1816     }
1817
1818   /* We don't want to finish the outermost loop entirely.  */
1819   n = loop->order[loop->temp_dim - 1];
1820   gfc_trans_scalarized_loop_end (loop, n, pblock);
1821
1822   /* Restore the initial offsets.  */
1823   for (ss = loop->ss; ss != gfc_ss_terminator; ss = ss->loop_chain)
1824     {
1825       if ((ss->useflags & 2) == 0)
1826         continue;
1827
1828       if (ss->type != GFC_SS_SECTION
1829           && ss->type != GFC_SS_FUNCTION && ss->type != GFC_SS_CONSTRUCTOR
1830           && ss->type != GFC_SS_COMPONENT)
1831         continue;
1832
1833       ss->data.info.offset = ss->data.info.saved_offset;
1834     }
1835
1836   /* Restart all the inner loops we just finished.  */
1837   for (dim = loop->temp_dim - 2; dim >= 0; dim--)
1838     {
1839       n = loop->order[dim];
1840
1841       gfc_start_block (&loop->code[n]);
1842
1843       loop->loopvar[n] = gfc_create_var (gfc_array_index_type, "Q");
1844
1845       gfc_trans_preloop_setup (loop, dim, 2, &loop->code[n]);
1846     }
1847
1848   /* Start a block for the secondary copying code.  */
1849   gfc_start_block (body);
1850 }
1851
1852
1853 /* Calculate the upper bound of an array section.  */
1854
1855 static tree
1856 gfc_conv_section_upper_bound (gfc_ss * ss, int n, stmtblock_t * pblock)
1857 {
1858   int dim;
1859   gfc_ss *vecss;
1860   gfc_expr *end;
1861   tree desc;
1862   tree bound;
1863   gfc_se se;
1864
1865   assert (ss->type == GFC_SS_SECTION);
1866
1867   /* For vector array subscripts we want the size of the vector.  */
1868   dim = ss->data.info.dim[n];
1869   vecss = ss;
1870   while (vecss->data.info.ref->u.ar.dimen_type[dim] == DIMEN_VECTOR)
1871     {
1872       vecss = vecss->data.info.subscript[dim];
1873       assert (vecss && vecss->type == GFC_SS_VECTOR);
1874       dim = vecss->data.info.dim[0];
1875     }
1876
1877   assert (vecss->data.info.ref->u.ar.dimen_type[dim] == DIMEN_RANGE);
1878   end = vecss->data.info.ref->u.ar.end[dim];
1879   desc = vecss->data.info.descriptor;
1880
1881   if (end)
1882     {
1883       /* The upper bound was specified.  */
1884       gfc_init_se (&se, NULL);
1885       gfc_conv_expr_type (&se, end, gfc_array_index_type);
1886       gfc_add_block_to_block (pblock, &se.pre);
1887       bound = se.expr;
1888     }
1889   else
1890     {
1891       /* No upper bound was specified, so use the bound of the array. */
1892       bound = gfc_conv_array_ubound (desc, dim);
1893     }
1894
1895   return bound;
1896 }
1897
1898
1899 /* Calculate the lower bound of an array section.  */
1900
1901 static void
1902 gfc_conv_section_startstride (gfc_loopinfo * loop, gfc_ss * ss, int n)
1903 {
1904   gfc_expr *start;
1905   gfc_expr *stride;
1906   gfc_ss *vecss;
1907   tree desc;
1908   gfc_se se;
1909   gfc_ss_info *info;
1910   int dim;
1911
1912   info = &ss->data.info;
1913
1914   dim = info->dim[n];
1915
1916   /* For vector array subscripts we want the size of the vector.  */
1917   vecss = ss;
1918   while (vecss->data.info.ref->u.ar.dimen_type[dim] == DIMEN_VECTOR)
1919     {
1920       vecss = vecss->data.info.subscript[dim];
1921       assert (vecss && vecss->type == GFC_SS_VECTOR);
1922       /* Get the descriptors for the vector subscripts as well.  */
1923       if (!vecss->data.info.descriptor)
1924         gfc_conv_ss_descriptor (&loop->pre, vecss, !loop->array_parameter);
1925       dim = vecss->data.info.dim[0];
1926     }
1927
1928   assert (vecss->data.info.ref->u.ar.dimen_type[dim] == DIMEN_RANGE);
1929   start = vecss->data.info.ref->u.ar.start[dim];
1930   stride = vecss->data.info.ref->u.ar.stride[dim];
1931   desc = vecss->data.info.descriptor;
1932
1933   /* Calculate the start of the range.  For vector subscripts this will
1934      be the range of the vector.  */
1935   if (start)
1936     {
1937       /* Specified section start.  */
1938       gfc_init_se (&se, NULL);
1939       gfc_conv_expr_type (&se, start, gfc_array_index_type);
1940       gfc_add_block_to_block (&loop->pre, &se.pre);
1941       info->start[n] = se.expr;
1942     }
1943   else
1944     {
1945       /* No lower bound specified so use the bound of the array.  */
1946       info->start[n] = gfc_conv_array_lbound (desc, dim);
1947     }
1948   info->start[n] = gfc_evaluate_now (info->start[n], &loop->pre);
1949
1950   /* Calculate the stride.  */
1951   if (stride == NULL)
1952     info->stride[n] = gfc_index_one_node;
1953   else
1954     {
1955       gfc_init_se (&se, NULL);
1956       gfc_conv_expr_type (&se, stride, gfc_array_index_type);
1957       gfc_add_block_to_block (&loop->pre, &se.pre);
1958       info->stride[n] = gfc_evaluate_now (se.expr, &loop->pre);
1959     }
1960 }
1961
1962
1963 /* Calculates the range start and stride for a SS chain.  Also gets the
1964    descriptor and data pointer.  The range of vector subscripts is the size
1965    of the vector.  Array bounds are also checked.  */
1966
1967 void
1968 gfc_conv_ss_startstride (gfc_loopinfo * loop)
1969 {
1970   int n;
1971   tree tmp;
1972   gfc_ss *ss;
1973   gfc_ss *vecss;
1974   tree desc;
1975
1976   loop->dimen = 0;
1977   /* Determine the rank of the loop.  */
1978   for (ss = loop->ss;
1979        ss != gfc_ss_terminator && loop->dimen == 0; ss = ss->loop_chain)
1980     {
1981       switch (ss->type)
1982         {
1983         case GFC_SS_SECTION:
1984         case GFC_SS_CONSTRUCTOR:
1985         case GFC_SS_FUNCTION:
1986         case GFC_SS_COMPONENT:
1987           loop->dimen = ss->data.info.dimen;
1988           break;
1989
1990         default:
1991           break;
1992         }
1993     }
1994
1995   if (loop->dimen == 0)
1996     gfc_todo_error ("Unable to determine rank of expression");
1997
1998
1999   /* Loop over all the SS in the chain.  */
2000   for (ss = loop->ss; ss != gfc_ss_terminator; ss = ss->loop_chain)
2001     {
2002       if (ss->expr && ss->expr->shape && !ss->shape)
2003         ss->shape = ss->expr->shape;
2004
2005       switch (ss->type)
2006         {
2007         case GFC_SS_SECTION:
2008           /* Get the descriptor for the array.  */
2009           gfc_conv_ss_descriptor (&loop->pre, ss, !loop->array_parameter);
2010
2011           for (n = 0; n < ss->data.info.dimen; n++)
2012             gfc_conv_section_startstride (loop, ss, n);
2013           break;
2014
2015         case GFC_SS_CONSTRUCTOR:
2016         case GFC_SS_FUNCTION:
2017           for (n = 0; n < ss->data.info.dimen; n++)
2018             {
2019               ss->data.info.start[n] = gfc_index_zero_node;
2020               ss->data.info.stride[n] = gfc_index_one_node;
2021             }
2022           break;
2023
2024         default:
2025           break;
2026         }
2027     }
2028
2029   /* The rest is just runtime bound checking.  */
2030   if (flag_bounds_check)
2031     {
2032       stmtblock_t block;
2033       tree fault;
2034       tree bound;
2035       tree end;
2036       tree size[GFC_MAX_DIMENSIONS];
2037       gfc_ss_info *info;
2038       int dim;
2039
2040       gfc_start_block (&block);
2041
2042       fault = integer_zero_node;
2043       for (n = 0; n < loop->dimen; n++)
2044         size[n] = NULL_TREE;
2045
2046       for (ss = loop->ss; ss != gfc_ss_terminator; ss = ss->loop_chain)
2047         {
2048           if (ss->type != GFC_SS_SECTION)
2049             continue;
2050
2051           /* TODO: range checking for mapped dimensions.  */
2052           info = &ss->data.info;
2053
2054           /* This only checks scalarized dimensions, elemental dimensions are
2055              checked later.  */
2056           for (n = 0; n < loop->dimen; n++)
2057             {
2058               dim = info->dim[n];
2059               vecss = ss;
2060               while (vecss->data.info.ref->u.ar.dimen_type[dim]
2061                      == DIMEN_VECTOR)
2062                 {
2063                   vecss = vecss->data.info.subscript[dim];
2064                   assert (vecss && vecss->type == GFC_SS_VECTOR);
2065                   dim = vecss->data.info.dim[0];
2066                 }
2067               assert (vecss->data.info.ref->u.ar.dimen_type[dim]
2068                       == DIMEN_RANGE);
2069               desc = vecss->data.info.descriptor;
2070
2071               /* Check lower bound.  */
2072               bound = gfc_conv_array_lbound (desc, dim);
2073               tmp = info->start[n];
2074               tmp = fold (build (LT_EXPR, boolean_type_node, tmp, bound));
2075               fault = fold (build (TRUTH_OR_EXPR, boolean_type_node, fault,
2076                                    tmp));
2077
2078               /* Check the upper bound.  */
2079               bound = gfc_conv_array_ubound (desc, dim);
2080               end = gfc_conv_section_upper_bound (ss, n, &block);
2081               tmp = fold (build (GT_EXPR, boolean_type_node, end, bound));
2082               fault = fold (build (TRUTH_OR_EXPR, boolean_type_node, fault,
2083                                    tmp));
2084
2085               /* Check the section sizes match.  */
2086               tmp = fold (build (MINUS_EXPR, gfc_array_index_type, end,
2087                                  info->start[n]));
2088               tmp = fold (build (FLOOR_DIV_EXPR, gfc_array_index_type, tmp,
2089                                  info->stride[n]));
2090               /* We remember the size of the first section, and check all the
2091                  others against this.  */
2092               if (size[n])
2093                 {
2094                   tmp =
2095                     fold (build (NE_EXPR, boolean_type_node, tmp, size[n]));
2096                   fault =
2097                     build (TRUTH_OR_EXPR, boolean_type_node, fault, tmp);
2098                 }
2099               else
2100                 size[n] = gfc_evaluate_now (tmp, &block);
2101             }
2102         }
2103       gfc_trans_runtime_check (fault, gfc_strconst_bounds, &block);
2104
2105       tmp = gfc_finish_block (&block);
2106       gfc_add_expr_to_block (&loop->pre, tmp);
2107     }
2108 }
2109
2110
2111 /* Return true if the two SS could be aliased, ie. both point to the same data
2112    object.  */
2113 /* TODO: resolve aliases based on frontend expressions.  */
2114
2115 static int
2116 gfc_could_be_alias (gfc_ss * lss, gfc_ss * rss)
2117 {
2118   gfc_ref *lref;
2119   gfc_ref *rref;
2120   gfc_symbol *lsym;
2121   gfc_symbol *rsym;
2122
2123   lsym = lss->expr->symtree->n.sym;
2124   rsym = rss->expr->symtree->n.sym;
2125   if (gfc_symbols_could_alias (lsym, rsym))
2126     return 1;
2127
2128   if (rsym->ts.type != BT_DERIVED
2129       && lsym->ts.type != BT_DERIVED)
2130     return 0;
2131
2132   /* For derived types we must check all the component types.  We can ignore
2133      array references as these will have the same base type as the previous
2134      component ref.  */
2135   for (lref = lss->expr->ref; lref != lss->data.info.ref; lref = lref->next)
2136     {
2137       if (lref->type != REF_COMPONENT)
2138         continue;
2139
2140       if (gfc_symbols_could_alias (lref->u.c.sym, rsym))
2141         return 1;
2142
2143       for (rref = rss->expr->ref; rref != rss->data.info.ref;
2144            rref = rref->next)
2145         {
2146           if (rref->type != REF_COMPONENT)
2147             continue;
2148
2149           if (gfc_symbols_could_alias (lref->u.c.sym, rref->u.c.sym))
2150             return 1;
2151         }
2152     }
2153
2154   for (rref = rss->expr->ref; rref != rss->data.info.ref; rref = rref->next)
2155     {
2156       if (rref->type != REF_COMPONENT)
2157         break;
2158
2159       if (gfc_symbols_could_alias (rref->u.c.sym, lsym))
2160         return 1;
2161     }
2162
2163   return 0;
2164 }
2165
2166
2167 /* Resolve array data dependencies.  Creates a temporary if required.  */
2168 /* TODO: Calc dependencies with gfc_expr rather than gfc_ss, and move to
2169    dependency.c.  */
2170
2171 void
2172 gfc_conv_resolve_dependencies (gfc_loopinfo * loop, gfc_ss * dest,
2173                                gfc_ss * rss)
2174 {
2175   gfc_ss *ss;
2176   gfc_ref *lref;
2177   gfc_ref *rref;
2178   gfc_ref *aref;
2179   int nDepend = 0;
2180   int temp_dim = 0;
2181
2182   loop->temp_ss = NULL;
2183   aref = dest->data.info.ref;
2184   temp_dim = 0;
2185
2186   for (ss = rss; ss != gfc_ss_terminator; ss = ss->next)
2187     {
2188       if (ss->type != GFC_SS_SECTION)
2189         continue;
2190
2191       if (gfc_could_be_alias (dest, ss))
2192         {
2193           nDepend = 1;
2194           break;
2195         }
2196
2197       if (dest->expr->symtree->n.sym == ss->expr->symtree->n.sym)
2198         {
2199           lref = dest->expr->ref;
2200           rref = ss->expr->ref;
2201
2202           nDepend = gfc_dep_resolver (lref, rref);
2203 #if 0
2204           /* TODO : loop shifting.  */
2205           if (nDepend == 1)
2206             {
2207               /* Mark the dimensions for LOOP SHIFTING */
2208               for (n = 0; n < loop->dimen; n++)
2209                 {
2210                   int dim = dest->data.info.dim[n];
2211
2212                   if (lref->u.ar.dimen_type[dim] == DIMEN_VECTOR)
2213                     depends[n] = 2;
2214                   else if (! gfc_is_same_range (&lref->u.ar,
2215                                                 &rref->u.ar, dim, 0))
2216                     depends[n] = 1;
2217                  }
2218
2219               /* Put all the dimensions with dependencies in the
2220                  innermost loops.  */
2221               dim = 0;
2222               for (n = 0; n < loop->dimen; n++)
2223                 {
2224                   assert (loop->order[n] == n);
2225                   if (depends[n])
2226                   loop->order[dim++] = n;
2227                 }
2228               temp_dim = dim;
2229               for (n = 0; n < loop->dimen; n++)
2230                 {
2231                   if (! depends[n])
2232                   loop->order[dim++] = n;
2233                 }
2234
2235               assert (dim == loop->dimen);
2236               break;
2237             }
2238 #endif
2239         }
2240     }
2241
2242   if (nDepend == 1)
2243     {
2244       loop->temp_ss = gfc_get_ss ();
2245       loop->temp_ss->type = GFC_SS_TEMP;
2246       loop->temp_ss->data.temp.type =
2247         gfc_get_element_type (TREE_TYPE (dest->data.info.descriptor));
2248       loop->temp_ss->data.temp.string_length = NULL_TREE;
2249       loop->temp_ss->data.temp.dimen = loop->dimen;
2250       loop->temp_ss->next = gfc_ss_terminator;
2251       gfc_add_ss_to_loop (loop, loop->temp_ss);
2252     }
2253   else
2254     loop->temp_ss = NULL;
2255 }
2256
2257
2258 /* Initialise the scalarization loop.  Creates the loop variables.  Determines
2259    the range of the loop variables.  Creates a temporary if required.
2260    Calculates how to transform from loop variables to array indices for each
2261    expression.  Also generates code for scalar expressions which have been
2262    moved outside the loop. */
2263
2264 void
2265 gfc_conv_loop_setup (gfc_loopinfo * loop)
2266 {
2267   int n;
2268   int dim;
2269   gfc_ss_info *info;
2270   gfc_ss_info *specinfo;
2271   gfc_ss *ss;
2272   tree tmp;
2273   tree len;
2274   gfc_ss *loopspec[GFC_MAX_DIMENSIONS];
2275   mpz_t *cshape;
2276   mpz_t i;
2277
2278   mpz_init (i);
2279   for (n = 0; n < loop->dimen; n++)
2280     {
2281       loopspec[n] = NULL;
2282       /* We use one SS term, and use that to determine the bounds of the
2283          loop for this dimension.  We try to pick the simplest term.  */
2284       for (ss = loop->ss; ss != gfc_ss_terminator; ss = ss->loop_chain)
2285         {
2286           if (ss->shape)
2287             {
2288               /* The frontend has worked out the size for us.  */
2289               loopspec[n] = ss;
2290               continue;
2291             }
2292
2293           if (ss->type == GFC_SS_CONSTRUCTOR)
2294             {
2295               /* An unknown size constructor will always be rank one.
2296                  Higher rank constructors will wither have known shape,
2297                  or still be wrapped in a call to reshape.  */
2298               assert (loop->dimen == 1);
2299               /* Try to figure out the size of the constructor.  */
2300               /* TODO: avoid this by making the frontend set the shape.  */
2301               gfc_get_array_cons_size (&i, ss->expr->value.constructor);
2302               /* A negative value means we failed. */
2303               if (mpz_sgn (i) > 0)
2304                 {
2305                   mpz_sub_ui (i, i, 1);
2306                   loop->to[n] =
2307                     gfc_conv_mpz_to_tree (i, gfc_index_integer_kind);
2308                   loopspec[n] = ss;
2309                 }
2310               continue;
2311             }
2312
2313           /* TODO: Pick the best bound if we have a choice between a
2314              function and something else.  */
2315           if (ss->type == GFC_SS_FUNCTION)
2316             {
2317               loopspec[n] = ss;
2318               continue;
2319             }
2320
2321           if (ss->type != GFC_SS_SECTION)
2322             continue;
2323
2324           if (loopspec[n])
2325             specinfo = &loopspec[n]->data.info;
2326           else
2327             specinfo = NULL;
2328           info = &ss->data.info;
2329
2330           /* Criteria for choosing a loop specifier (most important first):
2331              stride of one
2332              known stride
2333              known lower bound
2334              known upper bound
2335            */
2336           if (!specinfo)
2337             loopspec[n] = ss;
2338           /* TODO: Is != contructor correct?  */
2339           else if (loopspec[n]->type != GFC_SS_CONSTRUCTOR)
2340             {
2341               if (integer_onep (info->stride[n])
2342                   && !integer_onep (specinfo->stride[n]))
2343                 loopspec[n] = ss;
2344               else if (INTEGER_CST_P (info->stride[n])
2345                        && !INTEGER_CST_P (specinfo->stride[n]))
2346                 loopspec[n] = ss;
2347               else if (INTEGER_CST_P (info->start[n])
2348                        && !INTEGER_CST_P (specinfo->start[n]))
2349                 loopspec[n] = ss;
2350               /* We don't work out the upper bound.
2351                  else if (INTEGER_CST_P (info->finish[n])
2352                  && ! INTEGER_CST_P (specinfo->finish[n]))
2353                  loopspec[n] = ss; */
2354             }
2355         }
2356
2357       if (!loopspec[n])
2358         gfc_todo_error ("Unable to find scalarization loop specifier");
2359
2360       info = &loopspec[n]->data.info;
2361
2362       /* Set the extents of this range.  */
2363       cshape = loopspec[n]->shape;
2364       if (cshape && INTEGER_CST_P (info->start[n])
2365           && INTEGER_CST_P (info->stride[n]))
2366         {
2367           loop->from[n] = info->start[n];
2368           mpz_set (i, cshape[n]);
2369           mpz_sub_ui (i, i, 1);
2370           /* To = from + (size - 1) * stride.  */
2371           tmp = gfc_conv_mpz_to_tree (i, gfc_index_integer_kind);
2372           if (!integer_onep (info->stride[n]))
2373             {
2374               tmp = fold (build (MULT_EXPR, gfc_array_index_type,
2375                                  tmp, info->stride[n]));
2376             }
2377           loop->to[n] = fold (build (PLUS_EXPR, gfc_array_index_type,
2378                               loop->from[n], tmp));
2379         }
2380       else
2381         {
2382           loop->from[n] = info->start[n];
2383           switch (loopspec[n]->type)
2384             {
2385             case GFC_SS_CONSTRUCTOR:
2386               assert (info->dimen == 1);
2387               assert (loop->to[n]);
2388               break;
2389
2390             case GFC_SS_SECTION:
2391               loop->to[n] = gfc_conv_section_upper_bound (loopspec[n], n,
2392                                                           &loop->pre);
2393               break;
2394
2395             case GFC_SS_FUNCTION:
2396               /* The loop bound will be set when we generate the call.  */
2397               assert (loop->to[n] == NULL_TREE);
2398               break;
2399
2400             default:
2401               abort ();
2402             }
2403         }
2404
2405       /* Transform everything so we have a simple incrementing variable.  */
2406       if (integer_onep (info->stride[n]))
2407         info->delta[n] = gfc_index_zero_node;
2408       else
2409         {
2410           /* Set the delta for this section.  */
2411           info->delta[n] = gfc_evaluate_now (loop->from[n], &loop->pre);
2412           /* Number of iterations is (end - start + step) / step.
2413              with start = 0, this simplifies to
2414              last = end / step;
2415              for (i = 0; i<=last; i++){...};  */
2416           tmp = fold (build (MINUS_EXPR, gfc_array_index_type, loop->to[n],
2417                              loop->from[n]));
2418           tmp = fold (build (TRUNC_DIV_EXPR, gfc_array_index_type, tmp,
2419                              info->stride[n]));
2420           loop->to[n] = gfc_evaluate_now (tmp, &loop->pre);
2421           /* Make the loop variable start at 0.  */
2422           loop->from[n] = gfc_index_zero_node;
2423         }
2424     }
2425
2426   /* Add all the scalar code that can be taken out of the loops.
2427      This may include calculating the loop bounds, so do it before
2428      allocating the temporary.  */
2429   gfc_add_loop_ss_code (loop, loop->ss, false);
2430
2431   /* If we want a temporary then create it.  */
2432   if (loop->temp_ss != NULL)
2433     {
2434       assert (loop->temp_ss->type == GFC_SS_TEMP);
2435       tmp = loop->temp_ss->data.temp.type;
2436       len = loop->temp_ss->data.temp.string_length;
2437       n = loop->temp_ss->data.temp.dimen;
2438       memset (&loop->temp_ss->data.info, 0, sizeof (gfc_ss_info));
2439       loop->temp_ss->type = GFC_SS_SECTION;
2440       loop->temp_ss->data.info.dimen = n;
2441       gfc_trans_allocate_temp_array (loop, &loop->temp_ss->data.info,
2442                                      tmp, len);
2443     }
2444
2445   for (n = 0; n < loop->temp_dim; n++)
2446     loopspec[loop->order[n]] = NULL;
2447
2448   mpz_clear (i);
2449
2450   /* For array parameters we don't have loop variables, so don't calculate the
2451      translations.  */
2452   if (loop->array_parameter)
2453     return;
2454
2455   /* Calculate the translation from loop variables to array indices.  */
2456   for (ss = loop->ss; ss != gfc_ss_terminator; ss = ss->loop_chain)
2457     {
2458       if (ss->type != GFC_SS_SECTION && ss->type != GFC_SS_COMPONENT)
2459         continue;
2460
2461       info = &ss->data.info;
2462
2463       for (n = 0; n < info->dimen; n++)
2464         {
2465           dim = info->dim[n];
2466
2467           /* If we are specifying the range the delta is already set.  */
2468           if (loopspec[n] != ss)
2469             {
2470               /* Calculate the offset relative to the loop variable.
2471                  First multiply by the stride.  */
2472               tmp = fold (build (MULT_EXPR, gfc_array_index_type,
2473                                  loop->from[n], info->stride[n]));
2474
2475               /* Then subtract this from our starting value.  */
2476               tmp = fold (build (MINUS_EXPR, gfc_array_index_type,
2477                                  info->start[n], tmp));
2478
2479               info->delta[n] = gfc_evaluate_now (tmp, &loop->pre);
2480             }
2481         }
2482     }
2483 }
2484
2485
2486 /* Fills in an array descriptor, and returns the size of the array.  The size
2487    will be a simple_val, ie a variable or a constant.  Also calculates the
2488    offset of the base.  Returns the size of the arrary.
2489    {
2490     stride = 1;
2491     offset = 0;
2492     for (n = 0; n < rank; n++)
2493       {
2494         a.lbound[n] = specified_lower_bound;
2495         offset = offset + a.lbond[n] * stride;
2496         size = 1 - lbound;
2497         a.ubound[n] = specified_upper_bound;
2498         a.stride[n] = stride;
2499         size = ubound + size; //size = ubound + 1 - lbound
2500         stride = stride * size;
2501       }
2502     return (stride);
2503    }  */
2504 /*GCC ARRAYS*/
2505
2506 static tree
2507 gfc_array_init_size (tree descriptor, int rank, tree * poffset,
2508                      gfc_expr ** lower, gfc_expr ** upper,
2509                      stmtblock_t * pblock)
2510 {
2511   tree type;
2512   tree tmp;
2513   tree size;
2514   tree offset;
2515   tree stride;
2516   gfc_expr *ubound;
2517   gfc_se se;
2518   int n;
2519
2520   type = TREE_TYPE (descriptor);
2521
2522   stride = gfc_index_one_node;
2523   offset = gfc_index_zero_node;
2524
2525   /* Set the dtype.  */
2526   tmp = gfc_conv_descriptor_dtype (descriptor);
2527   gfc_add_modify_expr (pblock, tmp,
2528                        GFC_TYPE_ARRAY_DTYPE (TREE_TYPE (descriptor)));
2529
2530   for (n = 0; n < rank; n++)
2531     {
2532       /* We have 3 possibilities for determining the size of the array:
2533          lower == NULL    => lbound = 1, ubound = upper[n]
2534          upper[n] = NULL  => lbound = 1, ubound = lower[n]
2535          upper[n] != NULL => lbound = lower[n], ubound = upper[n]  */
2536       ubound = upper[n];
2537
2538       /* Set lower bound.  */
2539       gfc_init_se (&se, NULL);
2540       if (lower == NULL)
2541         se.expr = gfc_index_one_node;
2542       else
2543         {
2544           assert (lower[n]);
2545           if (ubound)
2546             {
2547               gfc_conv_expr_type (&se, lower[n], gfc_array_index_type);
2548               gfc_add_block_to_block (pblock, &se.pre);
2549             }
2550           else
2551             {
2552               se.expr = gfc_index_one_node;
2553               ubound = lower[n];
2554             }
2555         }
2556       tmp = gfc_conv_descriptor_lbound (descriptor, gfc_rank_cst[n]);
2557       gfc_add_modify_expr (pblock, tmp, se.expr);
2558
2559       /* Work out the offset for this component.  */
2560       tmp = fold (build (MULT_EXPR, gfc_array_index_type, se.expr, stride));
2561       offset = fold (build (MINUS_EXPR, gfc_array_index_type, offset, tmp));
2562
2563       /* Start the calculation for the size of this dimension.  */
2564       size = build (MINUS_EXPR, gfc_array_index_type,
2565                     gfc_index_one_node, se.expr);
2566
2567       /* Set upper bound.  */
2568       gfc_init_se (&se, NULL);
2569       assert (ubound);
2570       gfc_conv_expr_type (&se, ubound, gfc_array_index_type);
2571       gfc_add_block_to_block (pblock, &se.pre);
2572
2573       tmp = gfc_conv_descriptor_ubound (descriptor, gfc_rank_cst[n]);
2574       gfc_add_modify_expr (pblock, tmp, se.expr);
2575
2576       /* Store the stride.  */
2577       tmp = gfc_conv_descriptor_stride (descriptor, gfc_rank_cst[n]);
2578       gfc_add_modify_expr (pblock, tmp, stride);
2579
2580       /* Calculate the size of this dimension.  */
2581       size = fold (build (PLUS_EXPR, gfc_array_index_type, se.expr, size));
2582
2583       /* Multiply the stride by the number of elements in this dimension.  */
2584       stride = fold (build (MULT_EXPR, gfc_array_index_type, stride, size));
2585       stride = gfc_evaluate_now (stride, pblock);
2586     }
2587
2588   /* The stride is the number of elements in the array, so multiply by the
2589      size of an element to get the total size.  */
2590   tmp = TYPE_SIZE_UNIT (gfc_get_element_type (type));
2591   size = fold (build (MULT_EXPR, gfc_array_index_type, stride, tmp));
2592
2593   if (poffset != NULL)
2594     {
2595       offset = gfc_evaluate_now (offset, pblock);
2596       *poffset = offset;
2597     }
2598
2599   size = gfc_evaluate_now (size, pblock);
2600   return size;
2601 }
2602
2603
2604 /* Initialises the descriptor and generates a call to _gfor_allocate.  Does
2605    the work for an ALLOCATE statement.  */
2606 /*GCC ARRAYS*/
2607
2608 void
2609 gfc_array_allocate (gfc_se * se, gfc_ref * ref, tree pstat)
2610 {
2611   tree tmp;
2612   tree pointer;
2613   tree allocate;
2614   tree offset;
2615   tree size;
2616   gfc_expr **lower;
2617   gfc_expr **upper;
2618
2619   /* Figure out the size of the array.  */
2620   switch (ref->u.ar.type)
2621     {
2622     case AR_ELEMENT:
2623       lower = NULL;
2624       upper = ref->u.ar.start;
2625       break;
2626
2627     case AR_FULL:
2628       assert (ref->u.ar.as->type == AS_EXPLICIT);
2629
2630       lower = ref->u.ar.as->lower;
2631       upper = ref->u.ar.as->upper;
2632       break;
2633
2634     case AR_SECTION:
2635       lower = ref->u.ar.start;
2636       upper = ref->u.ar.end;
2637       break;
2638
2639     default:
2640       abort ();
2641       break;
2642     }
2643
2644   size = gfc_array_init_size (se->expr, ref->u.ar.as->rank, &offset,
2645                               lower, upper, &se->pre);
2646
2647   /* Allocate memory to store the data.  */
2648   tmp = gfc_conv_descriptor_data (se->expr);
2649   pointer = gfc_build_addr_expr (NULL, tmp);
2650   pointer = gfc_evaluate_now (pointer, &se->pre);
2651
2652   if (gfc_array_index_type == gfc_int4_type_node)
2653     allocate = gfor_fndecl_allocate;
2654   else if (gfc_array_index_type == gfc_int8_type_node)
2655     allocate = gfor_fndecl_allocate64;
2656   else
2657     abort ();
2658
2659   tmp = gfc_chainon_list (NULL_TREE, pointer);
2660   tmp = gfc_chainon_list (tmp, size);
2661   tmp = gfc_chainon_list (tmp, pstat);
2662   tmp = gfc_build_function_call (allocate, tmp);
2663   gfc_add_expr_to_block (&se->pre, tmp);
2664
2665   pointer = gfc_conv_descriptor_data (se->expr);
2666   
2667   tmp = gfc_conv_descriptor_offset (se->expr);
2668   gfc_add_modify_expr (&se->pre, tmp, offset);
2669 }
2670
2671
2672 /* Deallocate an array variable.  Also used when an allocated variable goes
2673    out of scope.  */
2674 /*GCC ARRAYS*/
2675
2676 tree
2677 gfc_array_deallocate (tree descriptor)
2678 {
2679   tree var;
2680   tree tmp;
2681   stmtblock_t block;
2682
2683   gfc_start_block (&block);
2684   /* Get a pointer to the data.  */
2685   tmp = gfc_conv_descriptor_data (descriptor);
2686   tmp = gfc_build_addr_expr (NULL, tmp);
2687   var = gfc_create_var (TREE_TYPE (tmp), "ptr");
2688   gfc_add_modify_expr (&block, var, tmp);
2689
2690   /* Parameter is the address of the data component.  */
2691   tmp = gfc_chainon_list (NULL_TREE, var);
2692   tmp = gfc_chainon_list (tmp, integer_zero_node);
2693   tmp = gfc_build_function_call (gfor_fndecl_deallocate, tmp);
2694   gfc_add_expr_to_block (&block, tmp);
2695
2696   return gfc_finish_block (&block);
2697 }
2698
2699
2700 /* Create an array constructor from an initialization expression.
2701    We assume the frontend already did any expansions and conversions.  */
2702
2703 tree
2704 gfc_conv_array_initializer (tree type, gfc_expr * expr)
2705 {
2706   gfc_constructor *c;
2707   tree list;
2708   tree tmp;
2709   mpz_t maxval;
2710   gfc_se se;
2711   HOST_WIDE_INT hi;
2712   unsigned HOST_WIDE_INT lo;
2713   tree index, range;
2714
2715   list = NULL_TREE;
2716   switch (expr->expr_type)
2717     {
2718     case EXPR_CONSTANT:
2719     case EXPR_STRUCTURE:
2720       /* A single scalar or derived type value.  Create an array with all
2721          elements equal to that value.  */
2722       gfc_init_se (&se, NULL);
2723       
2724       if (expr->expr_type == EXPR_CONSTANT)
2725         gfc_conv_constant (&se, expr);
2726       else
2727         gfc_conv_structure (&se, expr, 1);
2728
2729       tmp = TYPE_MAX_VALUE (TYPE_DOMAIN (type));
2730       assert (tmp && INTEGER_CST_P (tmp));
2731       hi = TREE_INT_CST_HIGH (tmp);
2732       lo = TREE_INT_CST_LOW (tmp);
2733       lo++;
2734       if (lo == 0)
2735         hi++;
2736       /* This will probably eat buckets of memory for large arrays.  */
2737       while (hi != 0 || lo != 0)
2738         {
2739           list = tree_cons (NULL_TREE, se.expr, list);
2740           if (lo == 0)
2741             hi--;
2742           lo--;
2743         }
2744       break;
2745
2746     case EXPR_ARRAY:
2747       /* Create a list of all the elements.  */
2748       for (c = expr->value.constructor; c; c = c->next)
2749         {
2750           if (c->iterator)
2751             {
2752               /* Problems occur when we get something like
2753                  integer :: a(lots) = (/(i, i=1,lots)/)  */
2754               /* TODO: Unexpanded array initializers.  */
2755               internal_error
2756                 ("Possible frontend bug: array constructor not expanded");
2757             }
2758           if (mpz_cmp_si (c->n.offset, 0) != 0)
2759             index = gfc_conv_mpz_to_tree (c->n.offset, gfc_index_integer_kind);
2760           else
2761             index = NULL_TREE;
2762           mpz_init (maxval);
2763           if (mpz_cmp_si (c->repeat, 0) != 0)
2764             {
2765               tree tmp1, tmp2;
2766
2767               mpz_set (maxval, c->repeat);
2768               mpz_add (maxval, c->n.offset, maxval);
2769               mpz_sub_ui (maxval, maxval, 1);
2770               tmp2 = gfc_conv_mpz_to_tree (maxval, gfc_index_integer_kind);
2771               if (mpz_cmp_si (c->n.offset, 0) != 0)
2772                 {
2773                   mpz_add_ui (maxval, c->n.offset, 1);
2774                   tmp1 = gfc_conv_mpz_to_tree (maxval, gfc_index_integer_kind);
2775                 }
2776               else
2777                 tmp1 = gfc_conv_mpz_to_tree (c->n.offset, gfc_index_integer_kind);
2778
2779               range = build (RANGE_EXPR, integer_type_node, tmp1, tmp2);
2780             }
2781           else
2782             range = NULL;
2783           mpz_clear (maxval);
2784
2785           gfc_init_se (&se, NULL);
2786           switch (c->expr->expr_type)
2787             {
2788             case EXPR_CONSTANT:
2789               gfc_conv_constant (&se, c->expr);
2790               if (range == NULL_TREE)
2791                 list = tree_cons (index, se.expr, list);
2792               else
2793                 {
2794                   if (index != NULL_TREE)
2795                     list = tree_cons (index, se.expr, list);
2796                   list = tree_cons (range, se.expr, list);
2797                 }
2798               break;
2799
2800             case EXPR_STRUCTURE:
2801               gfc_conv_structure (&se, c->expr, 1);
2802               list = tree_cons (index, se.expr, list);
2803               break;
2804
2805             default:
2806               abort();
2807             }
2808         }
2809       /* We created the list in reverse order.  */
2810       list = nreverse (list);
2811       break;
2812
2813     default:
2814       abort();
2815     }
2816
2817   /* Create a constructor from the list of elements.  */
2818   tmp = build1 (CONSTRUCTOR, type, list);
2819   TREE_CONSTANT (tmp) = 1;
2820   TREE_INVARIANT (tmp) = 1;
2821   return tmp;
2822 }
2823
2824
2825 /* Generate code to evaluate non-constant array bounds.  Sets *poffset and
2826    returns the size (in elements) of the array.  */
2827
2828 static tree
2829 gfc_trans_array_bounds (tree type, gfc_symbol * sym, tree * poffset,
2830                         stmtblock_t * pblock)
2831 {
2832   gfc_array_spec *as;
2833   tree size;
2834   tree stride;
2835   tree offset;
2836   tree ubound;
2837   tree lbound;
2838   tree tmp;
2839   gfc_se se;
2840
2841   int dim;
2842
2843   as = sym->as;
2844
2845   size = gfc_index_one_node;
2846   offset = gfc_index_zero_node;
2847   for (dim = 0; dim < as->rank; dim++)
2848     {
2849       /* Evaluate non-constant array bound expressions.  */
2850       lbound = GFC_TYPE_ARRAY_LBOUND (type, dim);
2851       if (as->lower[dim] && !INTEGER_CST_P (lbound))
2852         {
2853           gfc_init_se (&se, NULL);
2854           gfc_conv_expr_type (&se, as->lower[dim], gfc_array_index_type);
2855           gfc_add_block_to_block (pblock, &se.pre);
2856           gfc_add_modify_expr (pblock, lbound, se.expr);
2857         }
2858       ubound = GFC_TYPE_ARRAY_UBOUND (type, dim);
2859       if (as->upper[dim] && !INTEGER_CST_P (ubound))
2860         {
2861           gfc_init_se (&se, NULL);
2862           gfc_conv_expr_type (&se, as->upper[dim], gfc_array_index_type);
2863           gfc_add_block_to_block (pblock, &se.pre);
2864           gfc_add_modify_expr (pblock, ubound, se.expr);
2865         }
2866       /* The offset of this dimension.  offset = offset - lbound * stride. */
2867       tmp = fold (build (MULT_EXPR, gfc_array_index_type, lbound, size));
2868       offset = fold (build (MINUS_EXPR, gfc_array_index_type, offset, tmp));
2869
2870       /* The size of this dimension, and the stride of the next.  */
2871       if (dim + 1 < as->rank)
2872         stride = GFC_TYPE_ARRAY_STRIDE (type, dim + 1);
2873       else
2874         stride = NULL_TREE;
2875
2876       if (ubound != NULL_TREE && !(stride && INTEGER_CST_P (stride)))
2877         {
2878           /* Calculate stride = size * (ubound + 1 - lbound).  */
2879           tmp = fold (build (MINUS_EXPR, gfc_array_index_type,
2880                              gfc_index_one_node, lbound));
2881           tmp = fold (build (PLUS_EXPR, gfc_array_index_type, ubound, tmp));
2882           tmp = fold (build (MULT_EXPR, gfc_array_index_type, size, tmp));
2883           if (stride)
2884             gfc_add_modify_expr (pblock, stride, tmp);
2885           else
2886             stride = gfc_evaluate_now (tmp, pblock);
2887         }
2888
2889       size = stride;
2890     }
2891
2892   *poffset = offset;
2893   return size;
2894 }
2895
2896
2897 /* Generate code to initialize/allocate an array variable.  */
2898
2899 tree
2900 gfc_trans_auto_array_allocation (tree decl, gfc_symbol * sym, tree fnbody)
2901 {
2902   stmtblock_t block;
2903   tree type;
2904   tree tmp;
2905   tree fndecl;
2906   tree size;
2907   tree offset;
2908   bool onstack;
2909
2910   assert (!(sym->attr.pointer || sym->attr.allocatable));
2911
2912   /* Do nothing for USEd variables.  */
2913   if (sym->attr.use_assoc)
2914     return fnbody;
2915
2916   type = TREE_TYPE (decl);
2917   assert (GFC_ARRAY_TYPE_P (type));
2918   onstack = TREE_CODE (type) != POINTER_TYPE;
2919
2920   gfc_start_block (&block);
2921
2922   /* Evaluate character string length.  */
2923   if (sym->ts.type == BT_CHARACTER
2924       && onstack && !INTEGER_CST_P (sym->ts.cl->backend_decl))
2925     {
2926       gfc_trans_init_string_length (sym->ts.cl, &block);
2927
2928       /* Emit a DECL_EXPR for this variable, which will cause the
2929          gimplifier to allocate stoage, and all that good stuff.  */
2930       tmp = build (DECL_EXPR, TREE_TYPE (decl), decl);
2931       gfc_add_expr_to_block (&block, tmp);
2932     }
2933
2934   if (onstack)
2935     {
2936       gfc_add_expr_to_block (&block, fnbody);
2937       return gfc_finish_block (&block);
2938     }
2939
2940   type = TREE_TYPE (type);
2941
2942   assert (!sym->attr.use_assoc);
2943   assert (!TREE_STATIC (decl));
2944   assert (!sym->module[0]);
2945
2946   if (sym->ts.type == BT_CHARACTER
2947       && !INTEGER_CST_P (sym->ts.cl->backend_decl))
2948     gfc_trans_init_string_length (sym->ts.cl, &block);
2949
2950   size = gfc_trans_array_bounds (type, sym, &offset, &block);
2951
2952   /* The size is the number of elements in the array, so multiply by the
2953      size of an element to get the total size.  */
2954   tmp = TYPE_SIZE_UNIT (gfc_get_element_type (type));
2955   size = fold (build (MULT_EXPR, gfc_array_index_type, size, tmp));
2956
2957   /* Allocate memory to hold the data.  */
2958   tmp = gfc_chainon_list (NULL_TREE, size);
2959
2960   if (gfc_index_integer_kind == 4)
2961     fndecl = gfor_fndecl_internal_malloc;
2962   else if (gfc_index_integer_kind == 8)
2963     fndecl = gfor_fndecl_internal_malloc64;
2964   else
2965     abort ();
2966   tmp = gfc_build_function_call (fndecl, tmp);
2967   tmp = fold (convert (TREE_TYPE (decl), tmp));
2968   gfc_add_modify_expr (&block, decl, tmp);
2969
2970   /* Set offset of the array.  */
2971   if (TREE_CODE (GFC_TYPE_ARRAY_OFFSET (type)) == VAR_DECL)
2972     gfc_add_modify_expr (&block, GFC_TYPE_ARRAY_OFFSET (type), offset);
2973
2974
2975   /* Automatic arrays should not have initializers.  */
2976   assert (!sym->value);
2977
2978   gfc_add_expr_to_block (&block, fnbody);
2979
2980   /* Free the temporary.  */
2981   tmp = convert (pvoid_type_node, decl);
2982   tmp = gfc_chainon_list (NULL_TREE, tmp);
2983   tmp = gfc_build_function_call (gfor_fndecl_internal_free, tmp);
2984   gfc_add_expr_to_block (&block, tmp);
2985
2986   return gfc_finish_block (&block);
2987 }
2988
2989
2990 /* Generate entry and exit code for g77 calling convention arrays.  */
2991
2992 tree
2993 gfc_trans_g77_array (gfc_symbol * sym, tree body)
2994 {
2995   tree parm;
2996   tree type;
2997   locus loc;
2998   tree offset;
2999   tree tmp;
3000   stmtblock_t block;
3001
3002   gfc_get_backend_locus (&loc);
3003   gfc_set_backend_locus (&sym->declared_at);
3004
3005   /* Descriptor type.  */
3006   parm = sym->backend_decl;
3007   type = TREE_TYPE (parm);
3008   assert (GFC_ARRAY_TYPE_P (type));
3009
3010   gfc_start_block (&block);
3011
3012   if (sym->ts.type == BT_CHARACTER
3013       && TREE_CODE (sym->ts.cl->backend_decl) == VAR_DECL)
3014     gfc_trans_init_string_length (sym->ts.cl, &block);
3015
3016   /* Evaluate the bounds of the array.  */
3017   gfc_trans_array_bounds (type, sym, &offset, &block);
3018
3019   /* Set the offset.  */
3020   if (TREE_CODE (GFC_TYPE_ARRAY_OFFSET (type)) == VAR_DECL)
3021     gfc_add_modify_expr (&block, GFC_TYPE_ARRAY_OFFSET (type), offset);
3022
3023   /* Set the pointer itself if we aren't using the parameter dirtectly.  */
3024   if (TREE_CODE (parm) != PARM_DECL)
3025     {
3026       tmp = convert (TREE_TYPE (parm), GFC_DECL_SAVED_DESCRIPTOR (parm));
3027       gfc_add_modify_expr (&block, parm, tmp);
3028     }
3029   tmp = gfc_finish_block (&block);
3030
3031   gfc_set_backend_locus (&loc);
3032
3033   gfc_start_block (&block);
3034   /* Add the initialization code to the start of the function.  */
3035   gfc_add_expr_to_block (&block, tmp);
3036   gfc_add_expr_to_block (&block, body);
3037
3038   return gfc_finish_block (&block);
3039 }
3040
3041
3042 /* Modify the descriptor of an array parameter so that it has the
3043    correct lower bound.  Also move the upper bound accordingly.
3044    If the array is not packed, it will be copied into a temporary.
3045    For each dimension we set the new lower and upper bounds.  Then we copy the
3046    stride and calculate the offset for this dimension.  We also work out
3047    what the stride of a packed array would be, and see it the two match.
3048    If the array need repacking, we set the stride to the values we just
3049    calculated, recalculate the offset and copy the array data.
3050    Code is also added to copy the data back at the end of the function.
3051    */
3052
3053 tree
3054 gfc_trans_dummy_array_bias (gfc_symbol * sym, tree tmpdesc, tree body)
3055 {
3056   tree size;
3057   tree type;
3058   tree offset;
3059   locus loc;
3060   stmtblock_t block;
3061   stmtblock_t cleanup;
3062   tree lbound;
3063   tree ubound;
3064   tree dubound;
3065   tree dlbound;
3066   tree dumdesc;
3067   tree tmp;
3068   tree stmt;
3069   tree stride;
3070   tree stmt_packed;
3071   tree stmt_unpacked;
3072   tree partial;
3073   gfc_se se;
3074   int n;
3075   int checkparm;
3076   int no_repack;
3077
3078   /* Do nothing for pointer and allocatable arrays.  */
3079   if (sym->attr.pointer || sym->attr.allocatable)
3080     return body;
3081
3082   if (sym->attr.dummy && gfc_is_nodesc_array (sym))
3083     return gfc_trans_g77_array (sym, body);
3084
3085   gfc_get_backend_locus (&loc);
3086   gfc_set_backend_locus (&sym->declared_at);
3087
3088   /* Descriptor type.  */
3089   type = TREE_TYPE (tmpdesc);
3090   assert (GFC_ARRAY_TYPE_P (type));
3091   dumdesc = GFC_DECL_SAVED_DESCRIPTOR (tmpdesc);
3092   dumdesc = gfc_build_indirect_ref (dumdesc);
3093   gfc_start_block (&block);
3094
3095   if (sym->ts.type == BT_CHARACTER
3096       && TREE_CODE (sym->ts.cl->backend_decl) == VAR_DECL)
3097     gfc_trans_init_string_length (sym->ts.cl, &block);
3098
3099   checkparm = (sym->as->type == AS_EXPLICIT && flag_bounds_check);
3100
3101   no_repack = !(GFC_DECL_PACKED_ARRAY (tmpdesc)
3102                 || GFC_DECL_PARTIAL_PACKED_ARRAY (tmpdesc));
3103
3104   if (GFC_DECL_PARTIAL_PACKED_ARRAY (tmpdesc))
3105     {
3106       /* For non-constant shape arrays we only check if the first dimension
3107          is contiguous.  Repacking higher dimensions wouldn't gain us
3108          anything as we still don't know the array stride.  */
3109       partial = gfc_create_var (boolean_type_node, "partial");
3110       TREE_USED (partial) = 1;
3111       tmp = gfc_conv_descriptor_stride (dumdesc, gfc_rank_cst[0]);
3112       tmp = fold (build (EQ_EXPR, boolean_type_node, tmp, integer_one_node));
3113       gfc_add_modify_expr (&block, partial, tmp);
3114     }
3115   else
3116     {
3117       partial = NULL_TREE;
3118     }
3119
3120   /* The naming of stmt_unpacked and stmt_packed may be counter-intuitive
3121      here, however I think it does the right thing.  */
3122   if (no_repack)
3123     {
3124       /* Set the first stride.  */
3125       stride = gfc_conv_descriptor_stride (dumdesc, gfc_rank_cst[0]);
3126       stride = gfc_evaluate_now (stride, &block);
3127
3128       tmp = build (EQ_EXPR, boolean_type_node, stride, integer_zero_node);
3129       tmp = build (COND_EXPR, gfc_array_index_type, tmp,
3130                    gfc_index_one_node, stride);
3131       stride = GFC_TYPE_ARRAY_STRIDE (type, 0);
3132       gfc_add_modify_expr (&block, stride, tmp);
3133
3134       /* Allow the user to disable array repacking.  */
3135       stmt_unpacked = NULL_TREE;
3136     }
3137   else
3138     {
3139       assert (integer_onep (GFC_TYPE_ARRAY_STRIDE (type, 0)));
3140       /* A library call to repack the array if neccessary.  */
3141       tmp = GFC_DECL_SAVED_DESCRIPTOR (tmpdesc);
3142       tmp = gfc_chainon_list (NULL_TREE, tmp);
3143       stmt_unpacked = gfc_build_function_call (gfor_fndecl_in_pack, tmp);
3144
3145       stride = gfc_index_one_node;
3146     }
3147
3148   /* This is for the case where the array data is used directly without
3149      calling the repack function.  */
3150   if (no_repack || partial != NULL_TREE)
3151     stmt_packed = gfc_conv_descriptor_data (dumdesc);
3152   else
3153     stmt_packed = NULL_TREE;
3154
3155   /* Assign the data pointer.  */
3156   if (stmt_packed != NULL_TREE && stmt_unpacked != NULL_TREE)
3157     {
3158       /* Don't repack unknown shape arrays when the first stride is 1.  */
3159       tmp = build (COND_EXPR, TREE_TYPE (stmt_packed), partial,
3160                    stmt_packed, stmt_unpacked);
3161     }
3162   else
3163     tmp = stmt_packed != NULL_TREE ? stmt_packed : stmt_unpacked;
3164   gfc_add_modify_expr (&block, tmpdesc, fold_convert (type, tmp));
3165
3166   offset = gfc_index_zero_node;
3167   size = gfc_index_one_node;
3168
3169   /* Evaluate the bounds of the array.  */
3170   for (n = 0; n < sym->as->rank; n++)
3171     {
3172       if (checkparm || !sym->as->upper[n])
3173         {
3174           /* Get the bounds of the actual parameter.  */
3175           dubound = gfc_conv_descriptor_ubound (dumdesc, gfc_rank_cst[n]);
3176           dlbound = gfc_conv_descriptor_lbound (dumdesc, gfc_rank_cst[n]);
3177         }
3178       else
3179         {
3180           dubound = NULL_TREE;
3181           dlbound = NULL_TREE;
3182         }
3183
3184       lbound = GFC_TYPE_ARRAY_LBOUND (type, n);
3185       if (!INTEGER_CST_P (lbound))
3186         {
3187           gfc_init_se (&se, NULL);
3188           gfc_conv_expr_type (&se, sym->as->upper[n],
3189                               gfc_array_index_type);
3190           gfc_add_block_to_block (&block, &se.pre);
3191           gfc_add_modify_expr (&block, lbound, se.expr);
3192         }
3193
3194       ubound = GFC_TYPE_ARRAY_UBOUND (type, n);
3195       /* Set the desired upper bound.  */
3196       if (sym->as->upper[n])
3197         {
3198           /* We know what we want the upper bound to be.  */
3199           if (!INTEGER_CST_P (ubound))
3200             {
3201               gfc_init_se (&se, NULL);
3202               gfc_conv_expr_type (&se, sym->as->upper[n],
3203                                   gfc_array_index_type);
3204               gfc_add_block_to_block (&block, &se.pre);
3205               gfc_add_modify_expr (&block, ubound, se.expr);
3206             }
3207
3208           /* Check the sizes match.  */
3209           if (checkparm)
3210             {
3211               /* Check (ubound(a) - lbound(a) == ubound(b) - lbound(b)).  */
3212
3213               tmp = fold (build (MINUS_EXPR, gfc_array_index_type, ubound,
3214                                  lbound));
3215               stride = build (MINUS_EXPR, gfc_array_index_type, dubound,
3216                             dlbound);
3217               tmp = fold (build (NE_EXPR, gfc_array_index_type, tmp, stride));
3218               gfc_trans_runtime_check (tmp, gfc_strconst_bounds, &block);
3219             }
3220         }
3221       else
3222         {
3223           /* For assumed shape arrays move the upper bound by the same amount
3224              as the lower bound.  */
3225           tmp = build (MINUS_EXPR, gfc_array_index_type, dubound, dlbound);
3226           tmp = fold (build (PLUS_EXPR, gfc_array_index_type, tmp, lbound));
3227           gfc_add_modify_expr (&block, ubound, tmp);
3228         }
3229       /* The offset of this dimension.  offset = offset - lbound * stride. */
3230       tmp = fold (build (MULT_EXPR, gfc_array_index_type, lbound, stride));
3231       offset = fold (build (MINUS_EXPR, gfc_array_index_type, offset, tmp));
3232
3233       /* The size of this dimension, and the stride of the next.  */
3234       if (n + 1 < sym->as->rank)
3235         {
3236           stride = GFC_TYPE_ARRAY_STRIDE (type, n + 1);
3237
3238           if (no_repack || partial != NULL_TREE)
3239             {
3240               stmt_unpacked =
3241                 gfc_conv_descriptor_stride (dumdesc, gfc_rank_cst[n+1]);
3242             }
3243
3244           /* Figure out the stride if not a known constant.  */
3245           if (!INTEGER_CST_P (stride))
3246             {
3247               if (no_repack)
3248                 stmt_packed = NULL_TREE;
3249               else
3250                 {
3251                   /* Calculate stride = size * (ubound + 1 - lbound).  */
3252                   tmp = fold (build (MINUS_EXPR, gfc_array_index_type,
3253                                      gfc_index_one_node, lbound));
3254                   tmp = fold (build (PLUS_EXPR, gfc_array_index_type,
3255                                      ubound, tmp));
3256                   size = fold (build (MULT_EXPR, gfc_array_index_type,
3257                                       size, tmp));
3258                   stmt_packed = size;
3259                 }
3260
3261               /* Assign the stride.  */
3262               if (stmt_packed != NULL_TREE && stmt_unpacked != NULL_TREE)
3263                 {
3264                   tmp = build (COND_EXPR, gfc_array_index_type, partial,
3265                                stmt_unpacked, stmt_packed);
3266                 }
3267               else
3268                 tmp = (stmt_packed != NULL_TREE) ? stmt_packed : stmt_unpacked;
3269               gfc_add_modify_expr (&block, stride, tmp);
3270             }
3271         }
3272     }
3273
3274   /* Set the offset.  */
3275   if (TREE_CODE (GFC_TYPE_ARRAY_OFFSET (type)) == VAR_DECL)
3276     gfc_add_modify_expr (&block, GFC_TYPE_ARRAY_OFFSET (type), offset);
3277
3278   stmt = gfc_finish_block (&block);
3279
3280   gfc_start_block (&block);
3281
3282   /* Only do the entry/initialization code if the arg is present.  */
3283   dumdesc = GFC_DECL_SAVED_DESCRIPTOR (tmpdesc);
3284   if (sym->attr.optional)
3285     {
3286       tmp = gfc_conv_expr_present (sym);
3287       stmt = build_v (COND_EXPR, tmp, stmt, build_empty_stmt ());
3288     }
3289   gfc_add_expr_to_block (&block, stmt);
3290
3291   /* Add the main function body.  */
3292   gfc_add_expr_to_block (&block, body);
3293
3294   /* Cleanup code.  */
3295   if (!no_repack)
3296     {
3297       gfc_start_block (&cleanup);
3298       
3299       if (sym->attr.intent != INTENT_IN)
3300         {
3301           /* Copy the data back.  */
3302           tmp = gfc_chainon_list (NULL_TREE, dumdesc);
3303           tmp = gfc_chainon_list (tmp, tmpdesc);
3304           tmp = gfc_build_function_call (gfor_fndecl_in_unpack, tmp);
3305           gfc_add_expr_to_block (&cleanup, tmp);
3306         }
3307
3308       /* Free the temporary.  */
3309       tmp = gfc_chainon_list (NULL_TREE, tmpdesc);
3310       tmp = gfc_build_function_call (gfor_fndecl_internal_free, tmp);
3311       gfc_add_expr_to_block (&cleanup, tmp);
3312
3313       stmt = gfc_finish_block (&cleanup);
3314         
3315       /* Only do the cleanup if the array was repacked.  */
3316       tmp = gfc_build_indirect_ref (dumdesc);
3317       tmp = gfc_conv_descriptor_data (tmp);
3318       tmp = build (NE_EXPR, boolean_type_node, tmp, tmpdesc);
3319       stmt = build_v (COND_EXPR, tmp, stmt, build_empty_stmt ());
3320
3321       if (sym->attr.optional)
3322         {
3323           tmp = gfc_conv_expr_present (sym);
3324           stmt = build_v (COND_EXPR, tmp, stmt, build_empty_stmt ());
3325         }
3326       gfc_add_expr_to_block (&block, stmt);
3327     }
3328   /* We don't need to free any memory allocated by internal_pack as it will
3329      be freed at the end of the function by pop_context.  */
3330   return gfc_finish_block (&block);
3331 }
3332
3333
3334 /* Convert an array for passing as an actual parameter.  Expressions and
3335    vector subscripts are evaluated and stored in a temporary, which is then
3336    passed.  For whole arrays the descriptor is passed.  For array sections
3337    a modified copy of the descriptor is passed, but using the original data.
3338    Also used for array pointer assignments by setting se->direct_byref.  */
3339
3340 void
3341 gfc_conv_expr_descriptor (gfc_se * se, gfc_expr * expr, gfc_ss * ss)
3342 {
3343   gfc_loopinfo loop;
3344   gfc_ss *secss;
3345   gfc_ss_info *info;
3346   int need_tmp;
3347   int n;
3348   tree tmp;
3349   tree desc;
3350   stmtblock_t block;
3351   tree start;
3352   tree offset;
3353   int full;
3354   gfc_ss *vss;
3355
3356   assert (ss != gfc_ss_terminator);
3357
3358   /* TODO: Pass constant array constructors without a temporary.  */
3359   /* Special case things we know we can pass easily.  */
3360   switch (expr->expr_type)
3361     {
3362     case EXPR_VARIABLE:
3363       /* If we have a linear array section, we can pass it directly.
3364          Otherwise we need to copy it into a temporary.  */
3365
3366       /* Find the SS for the array section.  */
3367       secss = ss;
3368       while (secss != gfc_ss_terminator && secss->type != GFC_SS_SECTION)
3369         secss = secss->next;
3370
3371       assert (secss != gfc_ss_terminator);
3372
3373       need_tmp = 0;
3374       for (n = 0; n < secss->data.info.dimen; n++)
3375         {
3376           vss = secss->data.info.subscript[secss->data.info.dim[n]];
3377           if (vss && vss->type == GFC_SS_VECTOR)
3378             need_tmp = 1;
3379         }
3380
3381       info = &secss->data.info;
3382
3383       /* Get the descriptor for the array.  */
3384       gfc_conv_ss_descriptor (&se->pre, secss, 0);
3385       desc = info->descriptor;
3386       if (GFC_ARRAY_TYPE_P (TREE_TYPE (desc)))
3387         {
3388           /* Create a new descriptor if the array doesn't have one.  */
3389           full = 0;
3390         }
3391       else if (info->ref->u.ar.type == AR_FULL)
3392         full = 1;
3393       else if (se->direct_byref)
3394         full = 0;
3395       else
3396         {
3397           assert (info->ref->u.ar.type == AR_SECTION);
3398
3399           full = 1;
3400           for (n = 0; n < info->ref->u.ar.dimen; n++)
3401             {
3402               /* Detect passing the full array as a section.  This could do
3403                  even more checking, but it doesn't seem worth it.  */
3404               if (info->ref->u.ar.start[n]
3405                   || info->ref->u.ar.end[n]
3406                   || (info->ref->u.ar.stride[n]
3407                       && !gfc_expr_is_one (info->ref->u.ar.stride[n], 0)))
3408                 {
3409                   full = 0;
3410                   break;
3411                 }
3412             }
3413         }
3414       if (full)
3415         {
3416           if (se->direct_byref)
3417             {
3418               /* Copy the descriptor for pointer assignments.  */
3419               gfc_add_modify_expr (&se->pre, se->expr, desc);
3420             }
3421           else if (se->want_pointer)
3422             {
3423               /* We pass full arrays directly.  This means that pointers and
3424                  allocatable arrays should also work.  */
3425               se->expr = gfc_build_addr_expr (NULL_TREE, desc);
3426             }
3427           else
3428             {
3429               se->expr = desc;
3430             }
3431           if (expr->ts.type == BT_CHARACTER)
3432             se->string_length = expr->symtree->n.sym->ts.cl->backend_decl;
3433           return;
3434         }
3435       break;
3436       
3437     case EXPR_FUNCTION:
3438       /* A transformational function return value will be a temporary
3439          array descriptor.  We still need to go through the scalarizer
3440          to create the descriptor.  Elemental functions ar handled as
3441          arbitary expressions, ie. copy to a temporary.  */
3442       secss = ss;
3443       /* Look for the SS for this function.  */
3444       while (secss != gfc_ss_terminator
3445              && (secss->type != GFC_SS_FUNCTION || secss->expr != expr))
3446         secss = secss->next;
3447
3448       if (se->direct_byref)
3449         {
3450           assert (secss != gfc_ss_terminator);
3451
3452           /* For pointer assignments pass the descriptor directly.  */
3453           se->ss = secss;
3454           se->expr = gfc_build_addr_expr (NULL, se->expr);
3455           gfc_conv_expr (se, expr);
3456           return;
3457         }
3458
3459       if (secss == gfc_ss_terminator)
3460         {
3461           /* Elemental function.  */
3462           need_tmp = 1;
3463           info = NULL;
3464         }
3465       else
3466         {
3467           /* Transformational function.  */
3468           info = &secss->data.info;
3469           need_tmp = 0;
3470         }
3471       break;
3472
3473     default:
3474       /* Something complicated.  Copy it into a temporary.  */
3475       need_tmp = 1;
3476       secss = NULL;
3477       info = NULL;
3478       break;
3479     }
3480
3481
3482   gfc_init_loopinfo (&loop);
3483
3484   /* Associate the SS with the loop.  */
3485   gfc_add_ss_to_loop (&loop, ss);
3486
3487   /* Tell the scalarizer not to bother creating loop variables, etc.  */
3488   if (!need_tmp)
3489     loop.array_parameter = 1;
3490   else
3491     assert (se->want_pointer && !se->direct_byref);
3492
3493   /* Setup the scalarizing loops and bounds.  */
3494   gfc_conv_ss_startstride (&loop);
3495
3496   if (need_tmp)
3497     {
3498       /* Tell the scalarizer to make a temporary.  */
3499       loop.temp_ss = gfc_get_ss ();
3500       loop.temp_ss->type = GFC_SS_TEMP;
3501       loop.temp_ss->next = gfc_ss_terminator;
3502       loop.temp_ss->data.temp.type = gfc_typenode_for_spec (&expr->ts);
3503       /* Which can hold our string, if present.  */
3504       if (expr->ts.type == BT_CHARACTER)
3505         se->string_length = loop.temp_ss->data.temp.string_length
3506           = TYPE_SIZE_UNIT (loop.temp_ss->data.temp.type);
3507       else
3508         loop.temp_ss->data.temp.string_length = NULL;
3509       loop.temp_ss->data.temp.dimen = loop.dimen;
3510       gfc_add_ss_to_loop (&loop, loop.temp_ss);
3511     }
3512
3513   gfc_conv_loop_setup (&loop);
3514
3515   if (need_tmp)
3516     {
3517       /* Copy into a temporary and pass that.  We don't need to copy the data
3518          back because expressions and vector subscripts must be INTENT_IN.  */
3519       /* TODO: Optimize passing function return values.  */
3520       gfc_se lse;
3521       gfc_se rse;
3522
3523       /* Start the copying loops.  */
3524       gfc_mark_ss_chain_used (loop.temp_ss, 1);
3525       gfc_mark_ss_chain_used (ss, 1);
3526       gfc_start_scalarized_body (&loop, &block);
3527
3528       /* Copy each data element.  */
3529       gfc_init_se (&lse, NULL);
3530       gfc_copy_loopinfo_to_se (&lse, &loop);
3531       gfc_init_se (&rse, NULL);
3532       gfc_copy_loopinfo_to_se (&rse, &loop);
3533
3534       lse.ss = loop.temp_ss;
3535       rse.ss = ss;
3536
3537       gfc_conv_scalarized_array_ref (&lse, NULL);
3538       gfc_conv_expr_val (&rse, expr);
3539
3540       gfc_add_block_to_block (&block, &rse.pre);
3541       gfc_add_block_to_block (&block, &lse.pre);
3542
3543       gfc_add_modify_expr (&block, lse.expr, rse.expr);
3544
3545       /* Finish the copying loops.  */
3546       gfc_trans_scalarizing_loops (&loop, &block);
3547
3548       /* Set the first stride component to zero to indicate a temporary.  */
3549       desc = loop.temp_ss->data.info.descriptor;
3550       tmp = gfc_conv_descriptor_stride (desc, gfc_rank_cst[0]);
3551       gfc_add_modify_expr (&loop.pre, tmp, gfc_index_zero_node);
3552
3553       assert (is_gimple_lvalue (desc));
3554       se->expr = gfc_build_addr_expr (NULL, desc);
3555     }
3556   else if (expr->expr_type == EXPR_FUNCTION)
3557     {
3558       desc = info->descriptor;
3559
3560       if (se->want_pointer)
3561         se->expr = gfc_build_addr_expr (NULL_TREE, desc);
3562       else
3563         se->expr = desc;
3564
3565       if (expr->ts.type == BT_CHARACTER)
3566         se->string_length = expr->symtree->n.sym->ts.cl->backend_decl;
3567     }
3568   else
3569     {
3570       /* We pass sections without copying to a temporary.  Make a new
3571          descriptor and point it at the section we want.  The loop variable
3572          limits will be the limits of the section.
3573          A function may decide to repack the array to speed up access, but
3574          we're not bothered about that here.  */
3575       int dim;
3576       tree parm;
3577       tree parmtype;
3578       tree stride;
3579       tree from;
3580       tree to;
3581       tree base;
3582
3583       /* Set the string_length for a character array.  */
3584       if (expr->ts.type == BT_CHARACTER)
3585         se->string_length = expr->symtree->n.sym->ts.cl->backend_decl;
3586
3587       desc = info->descriptor;
3588       assert (secss && secss != gfc_ss_terminator);
3589       if (se->direct_byref)
3590         {
3591           /* For pointer assignments we fill in the destination.  */
3592           parm = se->expr;
3593           parmtype = TREE_TYPE (parm);
3594         }
3595       else
3596         {
3597           /* Otherwise make a new one.  */
3598           parmtype = gfc_get_element_type (TREE_TYPE (desc));
3599           parmtype = gfc_get_array_type_bounds (parmtype, loop.dimen,
3600                                                 loop.from, loop.to, 0);
3601           parm = gfc_create_var (parmtype, "parm");
3602         }
3603
3604       offset = gfc_index_zero_node;
3605       dim = 0;
3606
3607       /* The following can be somewhat confusing.  We have two
3608          descriptors, a new one and the original array.
3609          {parm, parmtype, dim} refer to the new one.
3610          {desc, type, n, secss, loop} refer to the original, which maybe
3611          a descriptorless array.
3612          The bounds of the scaralization are the bounds of the section.
3613          We don't have to worry about numeric overflows when calculating
3614          the offsets because all elements are within the array data.  */
3615
3616       /* Set the dtype.  */
3617       tmp = gfc_conv_descriptor_dtype (parm);
3618       gfc_add_modify_expr (&loop.pre, tmp, GFC_TYPE_ARRAY_DTYPE (parmtype));
3619
3620       if (se->direct_byref)
3621         base = gfc_index_zero_node;
3622       else
3623         base = NULL_TREE;
3624
3625       for (n = 0; n < info->ref->u.ar.dimen; n++)
3626         {
3627           stride = gfc_conv_array_stride (desc, n);
3628
3629           /* Work out the offset.  */
3630           if (info->ref->u.ar.dimen_type[n] == DIMEN_ELEMENT)
3631             {
3632               assert (info->subscript[n]
3633                       && info->subscript[n]->type == GFC_SS_SCALAR);
3634               start = info->subscript[n]->data.scalar.expr;
3635             }
3636           else
3637             {
3638               /* Check we haven't somehow got out of sync.  */
3639               assert (info->dim[dim] == n);
3640
3641               /* Evaluate and remember the start of the section.  */
3642               start = info->start[dim];
3643               stride = gfc_evaluate_now (stride, &loop.pre);
3644             }
3645
3646           tmp = gfc_conv_array_lbound (desc, n);
3647           tmp = fold (build (MINUS_EXPR, TREE_TYPE (tmp), start, tmp));
3648
3649           tmp = fold (build (MULT_EXPR, TREE_TYPE (tmp), tmp, stride));
3650           offset = fold (build (PLUS_EXPR, TREE_TYPE (tmp), offset, tmp));
3651
3652           if (info->ref->u.ar.dimen_type[n] == DIMEN_ELEMENT)
3653             {
3654               /* For elemental dimensions, we only need the offset.  */
3655               continue;
3656             }
3657
3658           /* Vector subscripts need copying and are handled elsewhere.  */
3659           assert (info->ref->u.ar.dimen_type[n] == DIMEN_RANGE);
3660
3661           /* Set the new lower bound.  */
3662           from = loop.from[dim];
3663           to = loop.to[dim];
3664           if (!integer_onep (from))
3665             {
3666               /* Make sure the new section starts at 1.  */
3667               tmp = fold (build (MINUS_EXPR, gfc_array_index_type,
3668                                  gfc_index_one_node, from));
3669               to = fold (build (PLUS_EXPR, gfc_array_index_type, to, tmp));
3670               from = gfc_index_one_node;
3671             }
3672           tmp = gfc_conv_descriptor_lbound (parm, gfc_rank_cst[dim]);
3673           gfc_add_modify_expr (&loop.pre, tmp, from);
3674
3675           /* Set the new upper bound.  */
3676           tmp = gfc_conv_descriptor_ubound (parm, gfc_rank_cst[dim]);
3677           gfc_add_modify_expr (&loop.pre, tmp, to);
3678
3679           /* Multiply the stride by the section stride to get the
3680              total stride.  */
3681           stride = fold (build (MULT_EXPR, gfc_array_index_type, stride,
3682                                 info->stride[dim]));
3683
3684           if (se->direct_byref)
3685             {
3686               base = fold (build (MINUS_EXPR, TREE_TYPE (base),
3687                                   base, stride));
3688             }
3689
3690           /* Store the new stride.  */
3691           tmp = gfc_conv_descriptor_stride (parm, gfc_rank_cst[dim]);
3692           gfc_add_modify_expr (&loop.pre, tmp, stride);
3693
3694           dim++;
3695         }
3696
3697       /* Point the data pointer at the first element in the section.  */
3698       tmp = gfc_conv_array_data (desc);
3699       tmp = gfc_build_indirect_ref (tmp);
3700       tmp = gfc_build_array_ref (tmp, offset);
3701       offset = gfc_build_addr_expr (gfc_array_dataptr_type (desc), tmp);
3702
3703       tmp = gfc_conv_descriptor_data (parm);
3704       gfc_add_modify_expr (&loop.pre, tmp,
3705                            fold_convert (TREE_TYPE (tmp), offset));
3706
3707       if (se->direct_byref)
3708         {
3709           /* Set the offset.  */
3710           tmp = gfc_conv_descriptor_offset (parm);
3711           gfc_add_modify_expr (&loop.pre, tmp, base);
3712         }
3713       else
3714         {
3715           /* Only the callee knows what the correct offset it, so just set
3716              it to zero here.  */
3717           tmp = gfc_conv_descriptor_offset (parm);
3718           gfc_add_modify_expr (&loop.pre, tmp, gfc_index_zero_node);
3719         }
3720
3721       if (!se->direct_byref)
3722         {
3723           /* Get a pointer to the new descriptor.  */
3724           if (se->want_pointer)
3725             se->expr = gfc_build_addr_expr (NULL, parm);
3726           else
3727             se->expr = parm;
3728         }
3729     }
3730
3731   gfc_add_block_to_block (&se->pre, &loop.pre);
3732   gfc_add_block_to_block (&se->post, &loop.post);
3733
3734   /* Cleanup the scalarizer.  */
3735   gfc_cleanup_loop (&loop);
3736 }
3737
3738
3739 /* Convert an array for passing as an actual parameter.  */
3740 /* TODO: Optimize passing g77 arrays.  */
3741
3742 void
3743 gfc_conv_array_parameter (gfc_se * se, gfc_expr * expr, gfc_ss * ss, int g77)
3744 {
3745   tree ptr;
3746   tree desc;
3747   tree tmp;
3748   tree stmt;
3749   gfc_symbol *sym;
3750   stmtblock_t block;
3751
3752   /* Passing address of the array if it is not pointer or assumed-shape.  */
3753   if (expr->expr_type == EXPR_VARIABLE
3754        && expr->ref->u.ar.type == AR_FULL && g77)
3755     {
3756       sym = expr->symtree->n.sym;
3757       tmp = gfc_get_symbol_decl (sym);
3758       if (sym->ts.type == BT_CHARACTER)
3759         se->string_length = sym->ts.cl->backend_decl;
3760       if (!sym->attr.pointer && sym->as->type != AS_ASSUMED_SHAPE 
3761           && !sym->attr.allocatable)
3762         {
3763           if (!sym->attr.dummy)
3764             se->expr = gfc_build_addr_expr (NULL, tmp);
3765           else
3766             se->expr = tmp;  
3767           return;
3768         }
3769       if (sym->attr.allocatable)
3770         {
3771           se->expr = gfc_conv_array_data (tmp);
3772           return;
3773         }
3774     }
3775
3776   se->want_pointer = 1;
3777   gfc_conv_expr_descriptor (se, expr, ss);
3778
3779   if (g77)
3780     {
3781       desc = se->expr;
3782       /* Repack the array.  */
3783       tmp = gfc_chainon_list (NULL_TREE, desc);
3784       ptr = gfc_build_function_call (gfor_fndecl_in_pack, tmp);
3785       ptr = gfc_evaluate_now (ptr, &se->pre);
3786       se->expr = ptr;
3787
3788       gfc_start_block (&block);
3789
3790       /* Copy the data back.  */
3791       tmp = gfc_chainon_list (NULL_TREE, desc);
3792       tmp = gfc_chainon_list (tmp, ptr);
3793       tmp = gfc_build_function_call (gfor_fndecl_in_unpack, tmp);
3794       gfc_add_expr_to_block (&block, tmp);
3795
3796       /* Free the temporary.  */
3797       tmp = convert (pvoid_type_node, ptr);
3798       tmp = gfc_chainon_list (NULL_TREE, tmp);
3799       tmp = gfc_build_function_call (gfor_fndecl_internal_free, tmp);
3800       gfc_add_expr_to_block (&block, tmp);
3801
3802       stmt = gfc_finish_block (&block);
3803
3804       gfc_init_block (&block);
3805       /* Only if it was repacked.  This code needs to be executed before the
3806          loop cleanup code.  */
3807       tmp = gfc_build_indirect_ref (desc);
3808       tmp = gfc_conv_array_data (tmp);
3809       tmp = build (NE_EXPR, boolean_type_node, ptr, tmp);
3810       tmp = build_v (COND_EXPR, tmp, stmt, build_empty_stmt ());
3811
3812       gfc_add_expr_to_block (&block, tmp);
3813       gfc_add_block_to_block (&block, &se->post);
3814
3815       gfc_init_block (&se->post);
3816       gfc_add_block_to_block (&se->post, &block);
3817     }
3818 }
3819
3820
3821 /* NULLIFY an allocated/pointer array on function entry, free it on exit.  */
3822
3823 tree
3824 gfc_trans_deferred_array (gfc_symbol * sym, tree body)
3825 {
3826   tree type;
3827   tree tmp;
3828   tree descriptor;
3829   tree deallocate;
3830   stmtblock_t block;
3831   stmtblock_t fnblock;
3832   locus loc;
3833
3834   /* Make sure the frontend gets these right.  */
3835   if (!(sym->attr.pointer || sym->attr.allocatable))
3836     fatal_error
3837       ("Possible frontend bug: Deferred array size without pointer or allocatable attribute.");
3838
3839   gfc_init_block (&fnblock);
3840
3841   assert (TREE_CODE (sym->backend_decl) == VAR_DECL);
3842   if (sym->ts.type == BT_CHARACTER
3843       && !INTEGER_CST_P (sym->ts.cl->backend_decl))
3844     gfc_trans_init_string_length (sym->ts.cl, &fnblock);
3845
3846   /* Parameter variables don't need anything special.  */
3847   if (sym->attr.dummy)
3848     {
3849       gfc_add_expr_to_block (&fnblock, body);
3850
3851       return gfc_finish_block (&fnblock);
3852     }
3853
3854   gfc_get_backend_locus (&loc);
3855   gfc_set_backend_locus (&sym->declared_at);
3856   descriptor = sym->backend_decl;
3857
3858   if (TREE_STATIC (descriptor))
3859     {
3860       /* SAVEd variables are not freed on exit.  */
3861       gfc_trans_static_array_pointer (sym);
3862       return body;
3863     }
3864
3865   /* Get the descriptor type.  */
3866   type = TREE_TYPE (sym->backend_decl);
3867   assert (GFC_DESCRIPTOR_TYPE_P (type));
3868
3869   /* NULLIFY the data pointer.  */
3870   tmp = gfc_conv_descriptor_data (descriptor);
3871   gfc_add_modify_expr (&fnblock, tmp,
3872                        convert (TREE_TYPE (tmp), integer_zero_node));
3873
3874   gfc_add_expr_to_block (&fnblock, body);
3875
3876   gfc_set_backend_locus (&loc);
3877   /* Allocatable arrays need to be freed when they go out of scope.  */
3878   if (sym->attr.allocatable)
3879     {
3880       gfc_start_block (&block);
3881
3882       /* Deallocate if still allocated at the end of the procedure.  */
3883       deallocate = gfc_array_deallocate (descriptor);
3884
3885       tmp = gfc_conv_descriptor_data (descriptor);
3886       tmp = build (NE_EXPR, boolean_type_node, tmp, integer_zero_node);
3887       tmp = build_v (COND_EXPR, tmp, deallocate, build_empty_stmt ());
3888       gfc_add_expr_to_block (&block, tmp);
3889
3890       tmp = gfc_finish_block (&block);
3891       gfc_add_expr_to_block (&fnblock, tmp);
3892     }
3893
3894   return gfc_finish_block (&fnblock);
3895 }
3896
3897 /************ Expression Walking Functions ******************/
3898
3899 /* Walk a variable reference.
3900
3901    Possible extension - multiple component subscripts.
3902     x(:,:) = foo%a(:)%b(:)
3903    Transforms to
3904     forall (i=..., j=...)
3905       x(i,j) = foo%a(j)%b(i)
3906     end forall
3907    This adds a fair amout of complexity because you need to deal with more
3908    than one ref.  Maybe handle in a similar manner to vector subscripts.
3909    Maybe not worth the effort.  */
3910
3911
3912 static gfc_ss *
3913 gfc_walk_variable_expr (gfc_ss * ss, gfc_expr * expr)
3914 {
3915   gfc_ref *ref;
3916   gfc_array_ref *ar;
3917   gfc_ss *newss;
3918   gfc_ss *head;
3919   int n;
3920
3921   for (ref = expr->ref; ref; ref = ref->next)
3922     {
3923       /* We're only interested in array sections.  */
3924       if (ref->type != REF_ARRAY)
3925         continue;
3926
3927       ar = &ref->u.ar;
3928       switch (ar->type)
3929         {
3930         case AR_ELEMENT:
3931           /* TODO: Take elemental array references out of scalarization
3932              loop.  */
3933           break;
3934
3935         case AR_FULL:
3936           newss = gfc_get_ss ();
3937           newss->type = GFC_SS_SECTION;
3938           newss->expr = expr;
3939           newss->next = ss;
3940           newss->data.info.dimen = ar->as->rank;
3941           newss->data.info.ref = ref;
3942
3943           /* Make sure array is the same as array(:,:), this way
3944              we don't need to special case all the time.  */
3945           ar->dimen = ar->as->rank;
3946           for (n = 0; n < ar->dimen; n++)
3947             {
3948               newss->data.info.dim[n] = n;
3949               ar->dimen_type[n] = DIMEN_RANGE;
3950
3951               assert (ar->start[n] == NULL);
3952               assert (ar->end[n] == NULL);
3953               assert (ar->stride[n] == NULL);
3954             }
3955           return newss;
3956
3957         case AR_SECTION:
3958           newss = gfc_get_ss ();
3959           newss->type = GFC_SS_SECTION;
3960           newss->expr = expr;
3961           newss->next = ss;
3962           newss->data.info.dimen = 0;
3963           newss->data.info.ref = ref;
3964
3965           head = newss;
3966
3967           /* We add SS chains for all the subscripts in the section.  */
3968           for (n = 0; n < ar->dimen; n++)
3969             {
3970               gfc_ss *indexss;
3971
3972               switch (ar->dimen_type[n])
3973                 {
3974                 case DIMEN_ELEMENT:
3975                   /* Add SS for elemental (scalar) subscripts.  */
3976                   assert (ar->start[n]);
3977                   indexss = gfc_get_ss ();
3978                   indexss->type = GFC_SS_SCALAR;
3979                   indexss->expr = ar->start[n];
3980                   indexss->next = gfc_ss_terminator;
3981                   indexss->loop_chain = gfc_ss_terminator;
3982                   newss->data.info.subscript[n] = indexss;
3983                   break;
3984
3985                 case DIMEN_RANGE:
3986                   /* We don't add anything for sections, just remember this
3987                      dimension for later.  */
3988                   newss->data.info.dim[newss->data.info.dimen] = n;
3989                   newss->data.info.dimen++;
3990                   break;
3991
3992                 case DIMEN_VECTOR:
3993                   /* Get a SS for the vector.  This will not be added to the
3994                      chain directly.  */
3995                   indexss = gfc_walk_expr (ar->start[n]);
3996                   if (indexss == gfc_ss_terminator)
3997                     internal_error ("scalar vector subscript???");
3998
3999                   /* We currently only handle really simple vector
4000                      subscripts.  */
4001                   if (indexss->next != gfc_ss_terminator)
4002                     gfc_todo_error ("vector subscript expressions");
4003                   indexss->loop_chain = gfc_ss_terminator;
4004
4005                   /* Mark this as a vector subscript.  We don't add this
4006                      directly into the chain, but as a subscript of the
4007                      existing SS for this term.  */
4008                   indexss->type = GFC_SS_VECTOR;
4009                   newss->data.info.subscript[n] = indexss;
4010                   /* Also remember this dimension.  */
4011                   newss->data.info.dim[newss->data.info.dimen] = n;
4012                   newss->data.info.dimen++;
4013                   break;
4014
4015                 default:
4016                   /* We should know what sort of section it is by now.  */
4017                   abort ();
4018                 }
4019             }
4020           /* We should have at least one non-elemental dimension.  */
4021           assert (newss->data.info.dimen > 0);
4022           return head;
4023           break;
4024
4025         default:
4026           /* We should know what sort of section it is by now.  */
4027           abort ();
4028         }
4029
4030     }
4031   return ss;
4032 }
4033
4034
4035 /* Walk an expression operator. If only one operand of a binary expression is
4036    scalar, we must also add the scalar term to the SS chain.  */
4037
4038 static gfc_ss *
4039 gfc_walk_op_expr (gfc_ss * ss, gfc_expr * expr)
4040 {
4041   gfc_ss *head;
4042   gfc_ss *head2;
4043   gfc_ss *newss;
4044
4045   head = gfc_walk_subexpr (ss, expr->op1);
4046   if (expr->op2 == NULL)
4047     head2 = head;
4048   else
4049     head2 = gfc_walk_subexpr (head, expr->op2);
4050
4051   /* All operands are scalar.  Pass back and let the caller deal with it.  */
4052   if (head2 == ss)
4053     return head2;
4054
4055   /* All operands require scalarization. */
4056   if (head != ss && (expr->op2 == NULL || head2 != head))
4057     return head2;
4058
4059   /* One of the operands needs scalarization, the other is scalar.
4060      Create a gfc_ss for the scalar expression.  */
4061   newss = gfc_get_ss ();
4062   newss->type = GFC_SS_SCALAR;
4063   if (head == ss)
4064     {
4065       /* First operand is scalar.  We build the chain in reverse order, so
4066          add the scarar SS after the second operand.  */
4067       head = head2;
4068       while (head && head->next != ss)
4069         head = head->next;
4070       /* Check we haven't somehow broken the chain.  */
4071       assert (head);
4072       newss->next = ss;
4073       head->next = newss;
4074       newss->expr = expr->op1;
4075     }
4076   else                          /* head2 == head */
4077     {
4078       assert (head2 == head);
4079       /* Second operand is scalar.  */
4080       newss->next = head2;
4081       head2 = newss;
4082       newss->expr = expr->op2;
4083     }
4084
4085   return head2;
4086 }
4087
4088
4089 /* Reverse a SS chain.  */
4090
4091 static gfc_ss *
4092 gfc_reverse_ss (gfc_ss * ss)
4093 {
4094   gfc_ss *next;
4095   gfc_ss *head;
4096
4097   assert (ss != NULL);
4098
4099   head = gfc_ss_terminator;
4100   while (ss != gfc_ss_terminator)
4101     {
4102       next = ss->next;
4103       assert (next != NULL);    /* Check we didn't somehow break the chain.  */
4104       ss->next = head;
4105       head = ss;
4106       ss = next;
4107     }
4108
4109   return (head);
4110 }
4111
4112
4113 /* Walk the arguments of an elemental function.  */
4114
4115 gfc_ss *
4116 gfc_walk_elemental_function_args (gfc_ss * ss, gfc_expr * expr,
4117                                   gfc_ss_type type)
4118 {
4119   gfc_actual_arglist *arg;
4120   int scalar;
4121   gfc_ss *head;
4122   gfc_ss *tail;
4123   gfc_ss *newss;
4124
4125   head = gfc_ss_terminator;
4126   tail = NULL;
4127   scalar = 1;
4128   for (arg = expr->value.function.actual; arg; arg = arg->next)
4129     {
4130       if (!arg->expr)
4131         continue;
4132
4133       newss = gfc_walk_subexpr (head, arg->expr);
4134       if (newss == head)
4135         {
4136           /* Scalar argumet.  */
4137           newss = gfc_get_ss ();
4138           newss->type = type;
4139           newss->expr = arg->expr;
4140           newss->next = head;
4141         }
4142       else
4143         scalar = 0;
4144
4145       head = newss;
4146       if (!tail)
4147         {
4148           tail = head;
4149           while (tail->next != gfc_ss_terminator)
4150             tail = tail->next;
4151         }
4152     }
4153
4154   if (scalar)
4155     {
4156       /* If all the arguments are scalar we don't need the argument SS.  */
4157       gfc_free_ss_chain (head);
4158       /* Pass it back.  */
4159       return ss;
4160     }
4161
4162   /* Add it onto the existing chain.  */
4163   tail->next = ss;
4164   return head;
4165 }
4166
4167
4168 /* Walk a function call.  Scalar functions are passed back, and taken out of
4169    scalarization loops.  For elemental functions we walk their arguments.
4170    The result of functions returning arrays is stored in a temporary outside
4171    the loop, so that the function is only called once.  Hence we do not need
4172    to walk their arguments.  */
4173
4174 static gfc_ss *
4175 gfc_walk_function_expr (gfc_ss * ss, gfc_expr * expr)
4176 {
4177   gfc_ss *newss;
4178   gfc_intrinsic_sym *isym;
4179   gfc_symbol *sym;
4180
4181   isym = expr->value.function.isym;
4182
4183   /* Handle intrinsic functions separately.  */
4184   if (isym)
4185     return gfc_walk_intrinsic_function (ss, expr, isym);
4186
4187   sym = expr->value.function.esym;
4188   if (!sym)
4189       sym = expr->symtree->n.sym;
4190
4191   /* A function that returns arrays.  */
4192   if (gfc_return_by_reference (sym) && sym->result->attr.dimension)
4193     {
4194       newss = gfc_get_ss ();
4195       newss->type = GFC_SS_FUNCTION;
4196       newss->expr = expr;
4197       newss->next = ss;
4198       newss->data.info.dimen = expr->rank;
4199       return newss;
4200     }
4201
4202   /* Walk the parameters of an elemental function.  For now we always pass
4203      by reference.  */
4204   if (sym->attr.elemental)
4205     return gfc_walk_elemental_function_args (ss, expr, GFC_SS_REFERENCE);
4206
4207   /* Scalar functions are OK as these are evaluated outside the scalarisation
4208      loop.  Pass back and let the caller deal with it.  */
4209   return ss;
4210 }
4211
4212
4213 /* An array temporary is constructed for array constructors.  */
4214
4215 static gfc_ss *
4216 gfc_walk_array_constructor (gfc_ss * ss, gfc_expr * expr)
4217 {
4218   gfc_ss *newss;
4219   int n;
4220
4221   newss = gfc_get_ss ();
4222   newss->type = GFC_SS_CONSTRUCTOR;
4223   newss->expr = expr;
4224   newss->next = ss;
4225   newss->data.info.dimen = expr->rank;
4226   for (n = 0; n < expr->rank; n++)
4227     newss->data.info.dim[n] = n;
4228
4229   return newss;
4230 }
4231
4232
4233 /* Walk an expresson.  Add walked expressions to the head of the SS chain.
4234    A wholy scalar expression will not be added.  */
4235
4236 static gfc_ss *
4237 gfc_walk_subexpr (gfc_ss * ss, gfc_expr * expr)
4238 {
4239   gfc_ss *head;
4240
4241   switch (expr->expr_type)
4242     {
4243     case EXPR_VARIABLE:
4244       head = gfc_walk_variable_expr (ss, expr);
4245       return head;
4246
4247     case EXPR_OP:
4248       head = gfc_walk_op_expr (ss, expr);
4249       return head;
4250
4251     case EXPR_FUNCTION:
4252       head = gfc_walk_function_expr (ss, expr);
4253       return head;
4254
4255     case EXPR_CONSTANT:
4256     case EXPR_NULL:
4257     case EXPR_STRUCTURE:
4258       /* Pass back and let the caller deal with it.  */
4259       break;
4260
4261     case EXPR_ARRAY:
4262       head = gfc_walk_array_constructor (ss, expr);
4263       return head;
4264
4265     case EXPR_SUBSTRING:
4266       /* Pass back and let the caller deal with it.  */
4267       break;
4268
4269     default:
4270       internal_error ("bad expression type during walk (%d)",
4271                       expr->expr_type);
4272     }
4273   return ss;
4274 }
4275
4276
4277 /* Entry point for expression walking.
4278    A return value equal to the passed chain means this is
4279    a scalar expression.  It is up to the caller to take whatever action is
4280    neccessary to translate these.  */
4281
4282 gfc_ss *
4283 gfc_walk_expr (gfc_expr * expr)
4284 {
4285   gfc_ss *res;
4286
4287   res = gfc_walk_subexpr (gfc_ss_terminator, expr);
4288   return gfc_reverse_ss (res);
4289 }
4290