OSDN Git Service

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