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