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