OSDN Git Service

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