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