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