OSDN Git Service

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