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