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