1 /* Array translation routines
2 Copyright (C) 2002-2022 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 3, 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 COPYING3. If not see
20 <http://www.gnu.org/licenses/>. */
21
22 /* trans-array.cc-- Various array related code, including scalarization,
23 allocation, initialization and other support routines. */
24
25 /* How the scalarizer works.
26 In gfortran, array expressions use the same core routines as scalar
27 expressions.
28 First, a Scalarization State (SS) chain is built. This is done by walking
29 the expression tree, and building a linear list of the terms in the
30 expression. As the tree is walked, scalar subexpressions are translated.
31
32 The scalarization parameters are stored in a gfc_loopinfo structure.
33 First the start and stride of each term is calculated by
34 gfc_conv_ss_startstride. During this process the expressions for the array
35 descriptors and data pointers are also translated.
36
37 If the expression is an assignment, we must then resolve any dependencies.
38 In Fortran all the rhs values of an assignment must be evaluated before
39 any assignments take place. This can require a temporary array to store the
40 values. We also require a temporary when we are passing array expressions
41 or vector subscripts as procedure parameters.
42
43 Array sections are passed without copying to a temporary. These use the
44 scalarizer to determine the shape of the section. The flag
45 loop->array_parameter tells the scalarizer that the actual values and loop
46 variables will not be required.
47
48 The function gfc_conv_loop_setup generates the scalarization setup code.
49 It determines the range of the scalarizing loop variables. If a temporary
50 is required, this is created and initialized. Code for scalar expressions
51 taken outside the loop is also generated at this time. Next the offset and
52 scaling required to translate from loop variables to array indices for each
53 term is calculated.
54
55 A call to gfc_start_scalarized_body marks the start of the scalarized
56 expression. This creates a scope and declares the loop variables. Before
57 calling this gfc_make_ss_chain_used must be used to indicate which terms
58 will be used inside this loop.
59
60 The scalar gfc_conv_* functions are then used to build the main body of the
61 scalarization loop. Scalarization loop variables and precalculated scalar
62 values are automatically substituted. Note that gfc_advance_se_ss_chain
63 must be used, rather than changing the se->ss directly.
64
65 For assignment expressions requiring a temporary two sub loops are
66 generated. The first stores the result of the expression in the temporary,
67 the second copies it to the result. A call to
68 gfc_trans_scalarized_loop_boundary marks the end of the main loop code and
69 the start of the copying loop. The temporary may be less than full rank.
70
71 Finally gfc_trans_scalarizing_loops is called to generate the implicit do
72 loops. The loops are added to the pre chain of the loopinfo. The post
73 chain may still contain cleanup code.
74
75 After the loop code has been added into its parent scope gfc_cleanup_loop
76 is called to free all the SS allocated by the scalarizer. */
77
78 #include "config.h"
79 #include "system.h"
80 #include "coretypes.h"
81 #include "options.h"
82 #include "tree.h"
83 #include "gfortran.h"
84 #include "gimple-expr.h"
85 #include "trans.h"
86 #include "fold-const.h"
87 #include "constructor.h"
88 #include "trans-types.h"
89 #include "trans-array.h"
90 #include "trans-const.h"
91 #include "dependency.h"
92
93 static bool gfc_get_array_constructor_size (mpz_t *, gfc_constructor_base);
94
95 /* The contents of this structure aren't actually used, just the address. */
96 static gfc_ss gfc_ss_terminator_var;
97 gfc_ss * const gfc_ss_terminator = &gfc_ss_terminator_var;
98
99
100 static tree
gfc_array_dataptr_type(tree desc)101 gfc_array_dataptr_type (tree desc)
102 {
103 return (GFC_TYPE_ARRAY_DATAPTR_TYPE (TREE_TYPE (desc)));
104 }
105
106 /* Build expressions to access members of the CFI descriptor. */
107 #define CFI_FIELD_BASE_ADDR 0
108 #define CFI_FIELD_ELEM_LEN 1
109 #define CFI_FIELD_VERSION 2
110 #define CFI_FIELD_RANK 3
111 #define CFI_FIELD_ATTRIBUTE 4
112 #define CFI_FIELD_TYPE 5
113 #define CFI_FIELD_DIM 6
114
115 #define CFI_DIM_FIELD_LOWER_BOUND 0
116 #define CFI_DIM_FIELD_EXTENT 1
117 #define CFI_DIM_FIELD_SM 2
118
119 static tree
gfc_get_cfi_descriptor_field(tree desc,unsigned field_idx)120 gfc_get_cfi_descriptor_field (tree desc, unsigned field_idx)
121 {
122 tree type = TREE_TYPE (desc);
123 gcc_assert (TREE_CODE (type) == RECORD_TYPE
124 && TYPE_FIELDS (type)
125 && (strcmp ("base_addr",
126 IDENTIFIER_POINTER (DECL_NAME (TYPE_FIELDS (type))))
127 == 0));
128 tree field = gfc_advance_chain (TYPE_FIELDS (type), field_idx);
129 gcc_assert (field != NULL_TREE);
130
131 return fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (field),
132 desc, field, NULL_TREE);
133 }
134
135 tree
gfc_get_cfi_desc_base_addr(tree desc)136 gfc_get_cfi_desc_base_addr (tree desc)
137 {
138 return gfc_get_cfi_descriptor_field (desc, CFI_FIELD_BASE_ADDR);
139 }
140
141 tree
gfc_get_cfi_desc_elem_len(tree desc)142 gfc_get_cfi_desc_elem_len (tree desc)
143 {
144 return gfc_get_cfi_descriptor_field (desc, CFI_FIELD_ELEM_LEN);
145 }
146
147 tree
gfc_get_cfi_desc_version(tree desc)148 gfc_get_cfi_desc_version (tree desc)
149 {
150 return gfc_get_cfi_descriptor_field (desc, CFI_FIELD_VERSION);
151 }
152
153 tree
gfc_get_cfi_desc_rank(tree desc)154 gfc_get_cfi_desc_rank (tree desc)
155 {
156 return gfc_get_cfi_descriptor_field (desc, CFI_FIELD_RANK);
157 }
158
159 tree
gfc_get_cfi_desc_type(tree desc)160 gfc_get_cfi_desc_type (tree desc)
161 {
162 return gfc_get_cfi_descriptor_field (desc, CFI_FIELD_TYPE);
163 }
164
165 tree
gfc_get_cfi_desc_attribute(tree desc)166 gfc_get_cfi_desc_attribute (tree desc)
167 {
168 return gfc_get_cfi_descriptor_field (desc, CFI_FIELD_ATTRIBUTE);
169 }
170
171 static tree
gfc_get_cfi_dim_item(tree desc,tree idx,unsigned field_idx)172 gfc_get_cfi_dim_item (tree desc, tree idx, unsigned field_idx)
173 {
174 tree tmp = gfc_get_cfi_descriptor_field (desc, CFI_FIELD_DIM);
175 tmp = gfc_build_array_ref (tmp, idx, NULL_TREE, true);
176 tree field = gfc_advance_chain (TYPE_FIELDS (TREE_TYPE (tmp)), field_idx);
177 gcc_assert (field != NULL_TREE);
178 return fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (field),
179 tmp, field, NULL_TREE);
180 }
181
182 tree
gfc_get_cfi_dim_lbound(tree desc,tree idx)183 gfc_get_cfi_dim_lbound (tree desc, tree idx)
184 {
185 return gfc_get_cfi_dim_item (desc, idx, CFI_DIM_FIELD_LOWER_BOUND);
186 }
187
188 tree
gfc_get_cfi_dim_extent(tree desc,tree idx)189 gfc_get_cfi_dim_extent (tree desc, tree idx)
190 {
191 return gfc_get_cfi_dim_item (desc, idx, CFI_DIM_FIELD_EXTENT);
192 }
193
194 tree
gfc_get_cfi_dim_sm(tree desc,tree idx)195 gfc_get_cfi_dim_sm (tree desc, tree idx)
196 {
197 return gfc_get_cfi_dim_item (desc, idx, CFI_DIM_FIELD_SM);
198 }
199
200 #undef CFI_FIELD_BASE_ADDR
201 #undef CFI_FIELD_ELEM_LEN
202 #undef CFI_FIELD_VERSION
203 #undef CFI_FIELD_RANK
204 #undef CFI_FIELD_ATTRIBUTE
205 #undef CFI_FIELD_TYPE
206 #undef CFI_FIELD_DIM
207
208 #undef CFI_DIM_FIELD_LOWER_BOUND
209 #undef CFI_DIM_FIELD_EXTENT
210 #undef CFI_DIM_FIELD_SM
211
212 /* Build expressions to access the members of an array descriptor.
213 It's surprisingly easy to mess up here, so never access
214 an array descriptor by "brute force", always use these
215 functions. This also avoids problems if we change the format
216 of an array descriptor.
217
218 To understand these magic numbers, look at the comments
219 before gfc_build_array_type() in trans-types.cc.
220
221 The code within these defines should be the only code which knows the format
222 of an array descriptor.
223
224 Any code just needing to read obtain the bounds of an array should use
225 gfc_conv_array_* rather than the following functions as these will return
226 know constant values, and work with arrays which do not have descriptors.
227
228 Don't forget to #undef these! */
229
230 #define DATA_FIELD 0
231 #define OFFSET_FIELD 1
232 #define DTYPE_FIELD 2
233 #define SPAN_FIELD 3
234 #define DIMENSION_FIELD 4
235 #define CAF_TOKEN_FIELD 5
236
237 #define STRIDE_SUBFIELD 0
238 #define LBOUND_SUBFIELD 1
239 #define UBOUND_SUBFIELD 2
240
241 static tree
gfc_get_descriptor_field(tree desc,unsigned field_idx)242 gfc_get_descriptor_field (tree desc, unsigned field_idx)
243 {
244 tree type = TREE_TYPE (desc);
245 gcc_assert (GFC_DESCRIPTOR_TYPE_P (type));
246
247 tree field = gfc_advance_chain (TYPE_FIELDS (type), field_idx);
248 gcc_assert (field != NULL_TREE);
249
250 return fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (field),
251 desc, field, NULL_TREE);
252 }
253
254 /* This provides READ-ONLY access to the data field. The field itself
255 doesn't have the proper type. */
256
257 tree
gfc_conv_descriptor_data_get(tree desc)258 gfc_conv_descriptor_data_get (tree desc)
259 {
260 tree type = TREE_TYPE (desc);
261 if (TREE_CODE (type) == REFERENCE_TYPE)
262 gcc_unreachable ();
263
264 tree field = gfc_get_descriptor_field (desc, DATA_FIELD);
265 return fold_convert (GFC_TYPE_ARRAY_DATAPTR_TYPE (type), field);
266 }
267
268 /* This provides WRITE access to the data field.
269
270 TUPLES_P is true if we are generating tuples.
271
272 This function gets called through the following macros:
273 gfc_conv_descriptor_data_set
274 gfc_conv_descriptor_data_set. */
275
276 void
gfc_conv_descriptor_data_set(stmtblock_t * block,tree desc,tree value)277 gfc_conv_descriptor_data_set (stmtblock_t *block, tree desc, tree value)
278 {
279 tree field = gfc_get_descriptor_field (desc, DATA_FIELD);
280 gfc_add_modify (block, field, fold_convert (TREE_TYPE (field), value));
281 }
282
283
284 /* This provides address access to the data field. This should only be
285 used by array allocation, passing this on to the runtime. */
286
287 tree
gfc_conv_descriptor_data_addr(tree desc)288 gfc_conv_descriptor_data_addr (tree desc)
289 {
290 tree field = gfc_get_descriptor_field (desc, DATA_FIELD);
291 return gfc_build_addr_expr (NULL_TREE, field);
292 }
293
294 static tree
gfc_conv_descriptor_offset(tree desc)295 gfc_conv_descriptor_offset (tree desc)
296 {
297 tree field = gfc_get_descriptor_field (desc, OFFSET_FIELD);
298 gcc_assert (TREE_TYPE (field) == gfc_array_index_type);
299 return field;
300 }
301
302 tree
gfc_conv_descriptor_offset_get(tree desc)303 gfc_conv_descriptor_offset_get (tree desc)
304 {
305 return gfc_conv_descriptor_offset (desc);
306 }
307
308 void
gfc_conv_descriptor_offset_set(stmtblock_t * block,tree desc,tree value)309 gfc_conv_descriptor_offset_set (stmtblock_t *block, tree desc,
310 tree value)
311 {
312 tree t = gfc_conv_descriptor_offset (desc);
313 gfc_add_modify (block, t, fold_convert (TREE_TYPE (t), value));
314 }
315
316
317 tree
gfc_conv_descriptor_dtype(tree desc)318 gfc_conv_descriptor_dtype (tree desc)
319 {
320 tree field = gfc_get_descriptor_field (desc, DTYPE_FIELD);
321 gcc_assert (TREE_TYPE (field) == get_dtype_type_node ());
322 return field;
323 }
324
325 static tree
gfc_conv_descriptor_span(tree desc)326 gfc_conv_descriptor_span (tree desc)
327 {
328 tree field = gfc_get_descriptor_field (desc, SPAN_FIELD);
329 gcc_assert (TREE_TYPE (field) == gfc_array_index_type);
330 return field;
331 }
332
333 tree
gfc_conv_descriptor_span_get(tree desc)334 gfc_conv_descriptor_span_get (tree desc)
335 {
336 return gfc_conv_descriptor_span (desc);
337 }
338
339 void
gfc_conv_descriptor_span_set(stmtblock_t * block,tree desc,tree value)340 gfc_conv_descriptor_span_set (stmtblock_t *block, tree desc,
341 tree value)
342 {
343 tree t = gfc_conv_descriptor_span (desc);
344 gfc_add_modify (block, t, fold_convert (TREE_TYPE (t), value));
345 }
346
347
348 tree
gfc_conv_descriptor_rank(tree desc)349 gfc_conv_descriptor_rank (tree desc)
350 {
351 tree tmp;
352 tree dtype;
353
354 dtype = gfc_conv_descriptor_dtype (desc);
355 tmp = gfc_advance_chain (TYPE_FIELDS (TREE_TYPE (dtype)), GFC_DTYPE_RANK);
356 gcc_assert (tmp != NULL_TREE
357 && TREE_TYPE (tmp) == signed_char_type_node);
358 return fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (tmp),
359 dtype, tmp, NULL_TREE);
360 }
361
362
363 /* Return the element length from the descriptor dtype field. */
364
365 tree
gfc_conv_descriptor_elem_len(tree desc)366 gfc_conv_descriptor_elem_len (tree desc)
367 {
368 tree tmp;
369 tree dtype;
370
371 dtype = gfc_conv_descriptor_dtype (desc);
372 tmp = gfc_advance_chain (TYPE_FIELDS (TREE_TYPE (dtype)),
373 GFC_DTYPE_ELEM_LEN);
374 gcc_assert (tmp != NULL_TREE
375 && TREE_TYPE (tmp) == size_type_node);
376 return fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (tmp),
377 dtype, tmp, NULL_TREE);
378 }
379
380
381 tree
gfc_conv_descriptor_attribute(tree desc)382 gfc_conv_descriptor_attribute (tree desc)
383 {
384 tree tmp;
385 tree dtype;
386
387 dtype = gfc_conv_descriptor_dtype (desc);
388 tmp = gfc_advance_chain (TYPE_FIELDS (TREE_TYPE (dtype)),
389 GFC_DTYPE_ATTRIBUTE);
390 gcc_assert (tmp!= NULL_TREE
391 && TREE_TYPE (tmp) == short_integer_type_node);
392 return fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (tmp),
393 dtype, tmp, NULL_TREE);
394 }
395
396 tree
gfc_conv_descriptor_type(tree desc)397 gfc_conv_descriptor_type (tree desc)
398 {
399 tree tmp;
400 tree dtype;
401
402 dtype = gfc_conv_descriptor_dtype (desc);
403 tmp = gfc_advance_chain (TYPE_FIELDS (TREE_TYPE (dtype)), GFC_DTYPE_TYPE);
404 gcc_assert (tmp!= NULL_TREE
405 && TREE_TYPE (tmp) == signed_char_type_node);
406 return fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (tmp),
407 dtype, tmp, NULL_TREE);
408 }
409
410 tree
gfc_get_descriptor_dimension(tree desc)411 gfc_get_descriptor_dimension (tree desc)
412 {
413 tree field = gfc_get_descriptor_field (desc, DIMENSION_FIELD);
414 gcc_assert (TREE_CODE (TREE_TYPE (field)) == ARRAY_TYPE
415 && TREE_CODE (TREE_TYPE (TREE_TYPE (field))) == RECORD_TYPE);
416 return field;
417 }
418
419
420 static tree
gfc_conv_descriptor_dimension(tree desc,tree dim)421 gfc_conv_descriptor_dimension (tree desc, tree dim)
422 {
423 tree tmp;
424
425 tmp = gfc_get_descriptor_dimension (desc);
426
427 return gfc_build_array_ref (tmp, dim, NULL_TREE, true);
428 }
429
430
431 tree
gfc_conv_descriptor_token(tree desc)432 gfc_conv_descriptor_token (tree desc)
433 {
434 gcc_assert (flag_coarray == GFC_FCOARRAY_LIB);
435 tree field = gfc_get_descriptor_field (desc, CAF_TOKEN_FIELD);
436 /* Should be a restricted pointer - except in the finalization wrapper. */
437 gcc_assert (TREE_TYPE (field) == prvoid_type_node
438 || TREE_TYPE (field) == pvoid_type_node);
439 return field;
440 }
441
442 static tree
gfc_conv_descriptor_subfield(tree desc,tree dim,unsigned field_idx)443 gfc_conv_descriptor_subfield (tree desc, tree dim, unsigned field_idx)
444 {
445 tree tmp = gfc_conv_descriptor_dimension (desc, dim);
446 tree field = gfc_advance_chain (TYPE_FIELDS (TREE_TYPE (tmp)), field_idx);
447 gcc_assert (field != NULL_TREE);
448
449 return fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (field),
450 tmp, field, NULL_TREE);
451 }
452
453 static tree
gfc_conv_descriptor_stride(tree desc,tree dim)454 gfc_conv_descriptor_stride (tree desc, tree dim)
455 {
456 tree field = gfc_conv_descriptor_subfield (desc, dim, STRIDE_SUBFIELD);
457 gcc_assert (TREE_TYPE (field) == gfc_array_index_type);
458 return field;
459 }
460
461 tree
gfc_conv_descriptor_stride_get(tree desc,tree dim)462 gfc_conv_descriptor_stride_get (tree desc, tree dim)
463 {
464 tree type = TREE_TYPE (desc);
465 gcc_assert (GFC_DESCRIPTOR_TYPE_P (type));
466 if (integer_zerop (dim)
467 && (GFC_TYPE_ARRAY_AKIND (type) == GFC_ARRAY_ALLOCATABLE
468 ||GFC_TYPE_ARRAY_AKIND (type) == GFC_ARRAY_ASSUMED_SHAPE_CONT
469 ||GFC_TYPE_ARRAY_AKIND (type) == GFC_ARRAY_ASSUMED_RANK_CONT
470 ||GFC_TYPE_ARRAY_AKIND (type) == GFC_ARRAY_POINTER_CONT))
471 return gfc_index_one_node;
472
473 return gfc_conv_descriptor_stride (desc, dim);
474 }
475
476 void
gfc_conv_descriptor_stride_set(stmtblock_t * block,tree desc,tree dim,tree value)477 gfc_conv_descriptor_stride_set (stmtblock_t *block, tree desc,
478 tree dim, tree value)
479 {
480 tree t = gfc_conv_descriptor_stride (desc, dim);
481 gfc_add_modify (block, t, fold_convert (TREE_TYPE (t), value));
482 }
483
484 static tree
gfc_conv_descriptor_lbound(tree desc,tree dim)485 gfc_conv_descriptor_lbound (tree desc, tree dim)
486 {
487 tree field = gfc_conv_descriptor_subfield (desc, dim, LBOUND_SUBFIELD);
488 gcc_assert (TREE_TYPE (field) == gfc_array_index_type);
489 return field;
490 }
491
492 tree
gfc_conv_descriptor_lbound_get(tree desc,tree dim)493 gfc_conv_descriptor_lbound_get (tree desc, tree dim)
494 {
495 return gfc_conv_descriptor_lbound (desc, dim);
496 }
497
498 void
gfc_conv_descriptor_lbound_set(stmtblock_t * block,tree desc,tree dim,tree value)499 gfc_conv_descriptor_lbound_set (stmtblock_t *block, tree desc,
500 tree dim, tree value)
501 {
502 tree t = gfc_conv_descriptor_lbound (desc, dim);
503 gfc_add_modify (block, t, fold_convert (TREE_TYPE (t), value));
504 }
505
506 static tree
gfc_conv_descriptor_ubound(tree desc,tree dim)507 gfc_conv_descriptor_ubound (tree desc, tree dim)
508 {
509 tree field = gfc_conv_descriptor_subfield (desc, dim, UBOUND_SUBFIELD);
510 gcc_assert (TREE_TYPE (field) == gfc_array_index_type);
511 return field;
512 }
513
514 tree
gfc_conv_descriptor_ubound_get(tree desc,tree dim)515 gfc_conv_descriptor_ubound_get (tree desc, tree dim)
516 {
517 return gfc_conv_descriptor_ubound (desc, dim);
518 }
519
520 void
gfc_conv_descriptor_ubound_set(stmtblock_t * block,tree desc,tree dim,tree value)521 gfc_conv_descriptor_ubound_set (stmtblock_t *block, tree desc,
522 tree dim, tree value)
523 {
524 tree t = gfc_conv_descriptor_ubound (desc, dim);
525 gfc_add_modify (block, t, fold_convert (TREE_TYPE (t), value));
526 }
527
528 /* Build a null array descriptor constructor. */
529
530 tree
gfc_build_null_descriptor(tree type)531 gfc_build_null_descriptor (tree type)
532 {
533 tree field;
534 tree tmp;
535
536 gcc_assert (GFC_DESCRIPTOR_TYPE_P (type));
537 gcc_assert (DATA_FIELD == 0);
538 field = TYPE_FIELDS (type);
539
540 /* Set a NULL data pointer. */
541 tmp = build_constructor_single (type, field, null_pointer_node);
542 TREE_CONSTANT (tmp) = 1;
543 /* All other fields are ignored. */
544
545 return tmp;
546 }
547
548
549 /* Modify a descriptor such that the lbound of a given dimension is the value
550 specified. This also updates ubound and offset accordingly. */
551
552 void
gfc_conv_shift_descriptor_lbound(stmtblock_t * block,tree desc,int dim,tree new_lbound)553 gfc_conv_shift_descriptor_lbound (stmtblock_t* block, tree desc,
554 int dim, tree new_lbound)
555 {
556 tree offs, ubound, lbound, stride;
557 tree diff, offs_diff;
558
559 new_lbound = fold_convert (gfc_array_index_type, new_lbound);
560
561 offs = gfc_conv_descriptor_offset_get (desc);
562 lbound = gfc_conv_descriptor_lbound_get (desc, gfc_rank_cst[dim]);
563 ubound = gfc_conv_descriptor_ubound_get (desc, gfc_rank_cst[dim]);
564 stride = gfc_conv_descriptor_stride_get (desc, gfc_rank_cst[dim]);
565
566 /* Get difference (new - old) by which to shift stuff. */
567 diff = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
568 new_lbound, lbound);
569
570 /* Shift ubound and offset accordingly. This has to be done before
571 updating the lbound, as they depend on the lbound expression! */
572 ubound = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
573 ubound, diff);
574 gfc_conv_descriptor_ubound_set (block, desc, gfc_rank_cst[dim], ubound);
575 offs_diff = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
576 diff, stride);
577 offs = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
578 offs, offs_diff);
579 gfc_conv_descriptor_offset_set (block, desc, offs);
580
581 /* Finally set lbound to value we want. */
582 gfc_conv_descriptor_lbound_set (block, desc, gfc_rank_cst[dim], new_lbound);
583 }
584
585
586 /* Obtain offsets for trans-types.cc(gfc_get_array_descr_info). */
587
588 void
gfc_get_descriptor_offsets_for_info(const_tree desc_type,tree * data_off,tree * dtype_off,tree * span_off,tree * dim_off,tree * dim_size,tree * stride_suboff,tree * lower_suboff,tree * upper_suboff)589 gfc_get_descriptor_offsets_for_info (const_tree desc_type, tree *data_off,
590 tree *dtype_off, tree *span_off,
591 tree *dim_off, tree *dim_size,
592 tree *stride_suboff, tree *lower_suboff,
593 tree *upper_suboff)
594 {
595 tree field;
596 tree type;
597
598 type = TYPE_MAIN_VARIANT (desc_type);
599 field = gfc_advance_chain (TYPE_FIELDS (type), DATA_FIELD);
600 *data_off = byte_position (field);
601 field = gfc_advance_chain (TYPE_FIELDS (type), DTYPE_FIELD);
602 *dtype_off = byte_position (field);
603 field = gfc_advance_chain (TYPE_FIELDS (type), SPAN_FIELD);
604 *span_off = byte_position (field);
605 field = gfc_advance_chain (TYPE_FIELDS (type), DIMENSION_FIELD);
606 *dim_off = byte_position (field);
607 type = TREE_TYPE (TREE_TYPE (field));
608 *dim_size = TYPE_SIZE_UNIT (type);
609 field = gfc_advance_chain (TYPE_FIELDS (type), STRIDE_SUBFIELD);
610 *stride_suboff = byte_position (field);
611 field = gfc_advance_chain (TYPE_FIELDS (type), LBOUND_SUBFIELD);
612 *lower_suboff = byte_position (field);
613 field = gfc_advance_chain (TYPE_FIELDS (type), UBOUND_SUBFIELD);
614 *upper_suboff = byte_position (field);
615 }
616
617
618 /* Cleanup those #defines. */
619
620 #undef DATA_FIELD
621 #undef OFFSET_FIELD
622 #undef DTYPE_FIELD
623 #undef SPAN_FIELD
624 #undef DIMENSION_FIELD
625 #undef CAF_TOKEN_FIELD
626 #undef STRIDE_SUBFIELD
627 #undef LBOUND_SUBFIELD
628 #undef UBOUND_SUBFIELD
629
630
631 /* Mark a SS chain as used. Flags specifies in which loops the SS is used.
632 flags & 1 = Main loop body.
633 flags & 2 = temp copy loop. */
634
635 void
gfc_mark_ss_chain_used(gfc_ss * ss,unsigned flags)636 gfc_mark_ss_chain_used (gfc_ss * ss, unsigned flags)
637 {
638 for (; ss != gfc_ss_terminator; ss = ss->next)
639 ss->info->useflags = flags;
640 }
641
642
643 /* Free a gfc_ss chain. */
644
645 void
gfc_free_ss_chain(gfc_ss * ss)646 gfc_free_ss_chain (gfc_ss * ss)
647 {
648 gfc_ss *next;
649
650 while (ss != gfc_ss_terminator)
651 {
652 gcc_assert (ss != NULL);
653 next = ss->next;
654 gfc_free_ss (ss);
655 ss = next;
656 }
657 }
658
659
660 static void
free_ss_info(gfc_ss_info * ss_info)661 free_ss_info (gfc_ss_info *ss_info)
662 {
663 int n;
664
665 ss_info->refcount--;
666 if (ss_info->refcount > 0)
667 return;
668
669 gcc_assert (ss_info->refcount == 0);
670
671 switch (ss_info->type)
672 {
673 case GFC_SS_SECTION:
674 for (n = 0; n < GFC_MAX_DIMENSIONS; n++)
675 if (ss_info->data.array.subscript[n])
676 gfc_free_ss_chain (ss_info->data.array.subscript[n]);
677 break;
678
679 default:
680 break;
681 }
682
683 free (ss_info);
684 }
685
686
687 /* Free a SS. */
688
689 void
gfc_free_ss(gfc_ss * ss)690 gfc_free_ss (gfc_ss * ss)
691 {
692 free_ss_info (ss->info);
693 free (ss);
694 }
695
696
697 /* Creates and initializes an array type gfc_ss struct. */
698
699 gfc_ss *
gfc_get_array_ss(gfc_ss * next,gfc_expr * expr,int dimen,gfc_ss_type type)700 gfc_get_array_ss (gfc_ss *next, gfc_expr *expr, int dimen, gfc_ss_type type)
701 {
702 gfc_ss *ss;
703 gfc_ss_info *ss_info;
704 int i;
705
706 ss_info = gfc_get_ss_info ();
707 ss_info->refcount++;
708 ss_info->type = type;
709 ss_info->expr = expr;
710
711 ss = gfc_get_ss ();
712 ss->info = ss_info;
713 ss->next = next;
714 ss->dimen = dimen;
715 for (i = 0; i < ss->dimen; i++)
716 ss->dim[i] = i;
717
718 return ss;
719 }
720
721
722 /* Creates and initializes a temporary type gfc_ss struct. */
723
724 gfc_ss *
gfc_get_temp_ss(tree type,tree string_length,int dimen)725 gfc_get_temp_ss (tree type, tree string_length, int dimen)
726 {
727 gfc_ss *ss;
728 gfc_ss_info *ss_info;
729 int i;
730
731 ss_info = gfc_get_ss_info ();
732 ss_info->refcount++;
733 ss_info->type = GFC_SS_TEMP;
734 ss_info->string_length = string_length;
735 ss_info->data.temp.type = type;
736
737 ss = gfc_get_ss ();
738 ss->info = ss_info;
739 ss->next = gfc_ss_terminator;
740 ss->dimen = dimen;
741 for (i = 0; i < ss->dimen; i++)
742 ss->dim[i] = i;
743
744 return ss;
745 }
746
747
748 /* Creates and initializes a scalar type gfc_ss struct. */
749
750 gfc_ss *
gfc_get_scalar_ss(gfc_ss * next,gfc_expr * expr)751 gfc_get_scalar_ss (gfc_ss *next, gfc_expr *expr)
752 {
753 gfc_ss *ss;
754 gfc_ss_info *ss_info;
755
756 ss_info = gfc_get_ss_info ();
757 ss_info->refcount++;
758 ss_info->type = GFC_SS_SCALAR;
759 ss_info->expr = expr;
760
761 ss = gfc_get_ss ();
762 ss->info = ss_info;
763 ss->next = next;
764
765 return ss;
766 }
767
768
769 /* Free all the SS associated with a loop. */
770
771 void
gfc_cleanup_loop(gfc_loopinfo * loop)772 gfc_cleanup_loop (gfc_loopinfo * loop)
773 {
774 gfc_loopinfo *loop_next, **ploop;
775 gfc_ss *ss;
776 gfc_ss *next;
777
778 ss = loop->ss;
779 while (ss != gfc_ss_terminator)
780 {
781 gcc_assert (ss != NULL);
782 next = ss->loop_chain;
783 gfc_free_ss (ss);
784 ss = next;
785 }
786
787 /* Remove reference to self in the parent loop. */
788 if (loop->parent)
789 for (ploop = &loop->parent->nested; *ploop; ploop = &(*ploop)->next)
790 if (*ploop == loop)
791 {
792 *ploop = loop->next;
793 break;
794 }
795
796 /* Free non-freed nested loops. */
797 for (loop = loop->nested; loop; loop = loop_next)
798 {
799 loop_next = loop->next;
800 gfc_cleanup_loop (loop);
801 free (loop);
802 }
803 }
804
805
806 static void
set_ss_loop(gfc_ss * ss,gfc_loopinfo * loop)807 set_ss_loop (gfc_ss *ss, gfc_loopinfo *loop)
808 {
809 int n;
810
811 for (; ss != gfc_ss_terminator; ss = ss->next)
812 {
813 ss->loop = loop;
814
815 if (ss->info->type == GFC_SS_SCALAR
816 || ss->info->type == GFC_SS_REFERENCE
817 || ss->info->type == GFC_SS_TEMP)
818 continue;
819
820 for (n = 0; n < GFC_MAX_DIMENSIONS; n++)
821 if (ss->info->data.array.subscript[n] != NULL)
822 set_ss_loop (ss->info->data.array.subscript[n], loop);
823 }
824 }
825
826
827 /* Associate a SS chain with a loop. */
828
829 void
gfc_add_ss_to_loop(gfc_loopinfo * loop,gfc_ss * head)830 gfc_add_ss_to_loop (gfc_loopinfo * loop, gfc_ss * head)
831 {
832 gfc_ss *ss;
833 gfc_loopinfo *nested_loop;
834
835 if (head == gfc_ss_terminator)
836 return;
837
838 set_ss_loop (head, loop);
839
840 ss = head;
841 for (; ss && ss != gfc_ss_terminator; ss = ss->next)
842 {
843 if (ss->nested_ss)
844 {
845 nested_loop = ss->nested_ss->loop;
846
847 /* More than one ss can belong to the same loop. Hence, we add the
848 loop to the chain only if it is different from the previously
849 added one, to avoid duplicate nested loops. */
850 if (nested_loop != loop->nested)
851 {
852 gcc_assert (nested_loop->parent == NULL);
853 nested_loop->parent = loop;
854
855 gcc_assert (nested_loop->next == NULL);
856 nested_loop->next = loop->nested;
857 loop->nested = nested_loop;
858 }
859 else
860 gcc_assert (nested_loop->parent == loop);
861 }
862
863 if (ss->next == gfc_ss_terminator)
864 ss->loop_chain = loop->ss;
865 else
866 ss->loop_chain = ss->next;
867 }
868 gcc_assert (ss == gfc_ss_terminator);
869 loop->ss = head;
870 }
871
872
873 /* Returns true if the expression is an array pointer. */
874
875 static bool
is_pointer_array(tree expr)876 is_pointer_array (tree expr)
877 {
878 if (expr == NULL_TREE
879 || !GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (expr))
880 || GFC_CLASS_TYPE_P (TREE_TYPE (expr)))
881 return false;
882
883 if (TREE_CODE (expr) == VAR_DECL
884 && GFC_DECL_PTR_ARRAY_P (expr))
885 return true;
886
887 if (TREE_CODE (expr) == PARM_DECL
888 && GFC_DECL_PTR_ARRAY_P (expr))
889 return true;
890
891 if (TREE_CODE (expr) == INDIRECT_REF
892 && GFC_DECL_PTR_ARRAY_P (TREE_OPERAND (expr, 0)))
893 return true;
894
895 /* The field declaration is marked as an pointer array. */
896 if (TREE_CODE (expr) == COMPONENT_REF
897 && GFC_DECL_PTR_ARRAY_P (TREE_OPERAND (expr, 1))
898 && !GFC_CLASS_TYPE_P (TREE_TYPE (TREE_OPERAND (expr, 1))))
899 return true;
900
901 return false;
902 }
903
904
905 /* If the symbol or expression reference a CFI descriptor, return the
906 pointer to the converted gfc descriptor. If an array reference is
907 present as the last argument, check that it is the one applied to
908 the CFI descriptor in the expression. Note that the CFI object is
909 always the symbol in the expression! */
910
911 static bool
get_CFI_desc(gfc_symbol * sym,gfc_expr * expr,tree * desc,gfc_array_ref * ar)912 get_CFI_desc (gfc_symbol *sym, gfc_expr *expr,
913 tree *desc, gfc_array_ref *ar)
914 {
915 tree tmp;
916
917 if (!is_CFI_desc (sym, expr))
918 return false;
919
920 if (expr && ar)
921 {
922 if (!(expr->ref && expr->ref->type == REF_ARRAY)
923 || (&expr->ref->u.ar != ar))
924 return false;
925 }
926
927 if (sym == NULL)
928 tmp = expr->symtree->n.sym->backend_decl;
929 else
930 tmp = sym->backend_decl;
931
932 if (tmp && DECL_LANG_SPECIFIC (tmp) && GFC_DECL_SAVED_DESCRIPTOR (tmp))
933 tmp = GFC_DECL_SAVED_DESCRIPTOR (tmp);
934
935 *desc = tmp;
936 return true;
937 }
938
939
940 /* Return the span of an array. */
941
942 tree
gfc_get_array_span(tree desc,gfc_expr * expr)943 gfc_get_array_span (tree desc, gfc_expr *expr)
944 {
945 tree tmp;
946
947 if (is_pointer_array (desc)
948 || (get_CFI_desc (NULL, expr, &desc, NULL)
949 && (POINTER_TYPE_P (TREE_TYPE (desc))
950 ? GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (TREE_TYPE (desc)))
951 : GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (desc)))))
952 {
953 if (POINTER_TYPE_P (TREE_TYPE (desc)))
954 desc = build_fold_indirect_ref_loc (input_location, desc);
955
956 /* This will have the span field set. */
957 tmp = gfc_conv_descriptor_span_get (desc);
958 }
959 else if (expr->ts.type == BT_ASSUMED)
960 {
961 if (DECL_LANG_SPECIFIC (desc) && GFC_DECL_SAVED_DESCRIPTOR (desc))
962 desc = GFC_DECL_SAVED_DESCRIPTOR (desc);
963 if (POINTER_TYPE_P (TREE_TYPE (desc)))
964 desc = build_fold_indirect_ref_loc (input_location, desc);
965 tmp = gfc_conv_descriptor_span_get (desc);
966 }
967 else if (TREE_CODE (desc) == COMPONENT_REF
968 && GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (desc))
969 && GFC_CLASS_TYPE_P (TREE_TYPE (TREE_OPERAND (desc, 0))))
970 {
971 /* The descriptor is a class _data field and so use the vtable
972 size for the receiving span field. */
973 tmp = gfc_get_vptr_from_expr (desc);
974 tmp = gfc_vptr_size_get (tmp);
975 }
976 else if (expr && expr->expr_type == EXPR_VARIABLE
977 && expr->symtree->n.sym->ts.type == BT_CLASS
978 && expr->ref->type == REF_COMPONENT
979 && expr->ref->next->type == REF_ARRAY
980 && expr->ref->next->next == NULL
981 && CLASS_DATA (expr->symtree->n.sym)->attr.dimension)
982 {
983 /* Dummys come in sometimes with the descriptor detached from
984 the class field or declaration. */
985 tmp = gfc_class_vptr_get (expr->symtree->n.sym->backend_decl);
986 tmp = gfc_vptr_size_get (tmp);
987 }
988 else
989 {
990 /* If none of the fancy stuff works, the span is the element
991 size of the array. Attempt to deal with unbounded character
992 types if possible. Otherwise, return NULL_TREE. */
993 tmp = gfc_get_element_type (TREE_TYPE (desc));
994 if (tmp && TREE_CODE (tmp) == ARRAY_TYPE && TYPE_STRING_FLAG (tmp))
995 {
996 gcc_assert (expr->ts.type == BT_CHARACTER);
997
998 tmp = gfc_get_character_len_in_bytes (tmp);
999
1000 if (tmp == NULL_TREE || integer_zerop (tmp))
1001 {
1002 tree bs;
1003
1004 tmp = gfc_get_expr_charlen (expr);
1005 tmp = fold_convert (gfc_array_index_type, tmp);
1006 bs = build_int_cst (gfc_array_index_type, expr->ts.kind);
1007 tmp = fold_build2_loc (input_location, MULT_EXPR,
1008 gfc_array_index_type, tmp, bs);
1009 }
1010
1011 tmp = (tmp && !integer_zerop (tmp))
1012 ? (fold_convert (gfc_array_index_type, tmp)) : (NULL_TREE);
1013 }
1014 else
1015 tmp = fold_convert (gfc_array_index_type,
1016 size_in_bytes (tmp));
1017 }
1018 return tmp;
1019 }
1020
1021
1022 /* Generate an initializer for a static pointer or allocatable array. */
1023
1024 void
gfc_trans_static_array_pointer(gfc_symbol * sym)1025 gfc_trans_static_array_pointer (gfc_symbol * sym)
1026 {
1027 tree type;
1028
1029 gcc_assert (TREE_STATIC (sym->backend_decl));
1030 /* Just zero the data member. */
1031 type = TREE_TYPE (sym->backend_decl);
1032 DECL_INITIAL (sym->backend_decl) = gfc_build_null_descriptor (type);
1033 }
1034
1035
1036 /* If the bounds of SE's loop have not yet been set, see if they can be
1037 determined from array spec AS, which is the array spec of a called
1038 function. MAPPING maps the callee's dummy arguments to the values
1039 that the caller is passing. Add any initialization and finalization
1040 code to SE. */
1041
1042 void
gfc_set_loop_bounds_from_array_spec(gfc_interface_mapping * mapping,gfc_se * se,gfc_array_spec * as)1043 gfc_set_loop_bounds_from_array_spec (gfc_interface_mapping * mapping,
1044 gfc_se * se, gfc_array_spec * as)
1045 {
1046 int n, dim, total_dim;
1047 gfc_se tmpse;
1048 gfc_ss *ss;
1049 tree lower;
1050 tree upper;
1051 tree tmp;
1052
1053 total_dim = 0;
1054
1055 if (!as || as->type != AS_EXPLICIT)
1056 return;
1057
1058 for (ss = se->ss; ss; ss = ss->parent)
1059 {
1060 total_dim += ss->loop->dimen;
1061 for (n = 0; n < ss->loop->dimen; n++)
1062 {
1063 /* The bound is known, nothing to do. */
1064 if (ss->loop->to[n] != NULL_TREE)
1065 continue;
1066
1067 dim = ss->dim[n];
1068 gcc_assert (dim < as->rank);
1069 gcc_assert (ss->loop->dimen <= as->rank);
1070
1071 /* Evaluate the lower bound. */
1072 gfc_init_se (&tmpse, NULL);
1073 gfc_apply_interface_mapping (mapping, &tmpse, as->lower[dim]);
1074 gfc_add_block_to_block (&se->pre, &tmpse.pre);
1075 gfc_add_block_to_block (&se->post, &tmpse.post);
1076 lower = fold_convert (gfc_array_index_type, tmpse.expr);
1077
1078 /* ...and the upper bound. */
1079 gfc_init_se (&tmpse, NULL);
1080 gfc_apply_interface_mapping (mapping, &tmpse, as->upper[dim]);
1081 gfc_add_block_to_block (&se->pre, &tmpse.pre);
1082 gfc_add_block_to_block (&se->post, &tmpse.post);
1083 upper = fold_convert (gfc_array_index_type, tmpse.expr);
1084
1085 /* Set the upper bound of the loop to UPPER - LOWER. */
1086 tmp = fold_build2_loc (input_location, MINUS_EXPR,
1087 gfc_array_index_type, upper, lower);
1088 tmp = gfc_evaluate_now (tmp, &se->pre);
1089 ss->loop->to[n] = tmp;
1090 }
1091 }
1092
1093 gcc_assert (total_dim == as->rank);
1094 }
1095
1096
1097 /* Generate code to allocate an array temporary, or create a variable to
1098 hold the data. If size is NULL, zero the descriptor so that the
1099 callee will allocate the array. If DEALLOC is true, also generate code to
1100 free the array afterwards.
1101
1102 If INITIAL is not NULL, it is packed using internal_pack and the result used
1103 as data instead of allocating a fresh, unitialized area of memory.
1104
1105 Initialization code is added to PRE and finalization code to POST.
1106 DYNAMIC is true if the caller may want to extend the array later
1107 using realloc. This prevents us from putting the array on the stack. */
1108
1109 static void
gfc_trans_allocate_array_storage(stmtblock_t * pre,stmtblock_t * post,gfc_array_info * info,tree size,tree nelem,tree initial,bool dynamic,bool dealloc)1110 gfc_trans_allocate_array_storage (stmtblock_t * pre, stmtblock_t * post,
1111 gfc_array_info * info, tree size, tree nelem,
1112 tree initial, bool dynamic, bool dealloc)
1113 {
1114 tree tmp;
1115 tree desc;
1116 bool onstack;
1117
1118 desc = info->descriptor;
1119 info->offset = gfc_index_zero_node;
1120 if (size == NULL_TREE || integer_zerop (size))
1121 {
1122 /* A callee allocated array. */
1123 gfc_conv_descriptor_data_set (pre, desc, null_pointer_node);
1124 onstack = FALSE;
1125 }
1126 else
1127 {
1128 /* Allocate the temporary. */
1129 onstack = !dynamic && initial == NULL_TREE
1130 && (flag_stack_arrays
1131 || gfc_can_put_var_on_stack (size));
1132
1133 if (onstack)
1134 {
1135 /* Make a temporary variable to hold the data. */
1136 tmp = fold_build2_loc (input_location, MINUS_EXPR, TREE_TYPE (nelem),
1137 nelem, gfc_index_one_node);
1138 tmp = gfc_evaluate_now (tmp, pre);
1139 tmp = build_range_type (gfc_array_index_type, gfc_index_zero_node,
1140 tmp);
1141 tmp = build_array_type (gfc_get_element_type (TREE_TYPE (desc)),
1142 tmp);
1143 tmp = gfc_create_var (tmp, "A");
1144 /* If we're here only because of -fstack-arrays we have to
1145 emit a DECL_EXPR to make the gimplifier emit alloca calls. */
1146 if (!gfc_can_put_var_on_stack (size))
1147 gfc_add_expr_to_block (pre,
1148 fold_build1_loc (input_location,
1149 DECL_EXPR, TREE_TYPE (tmp),
1150 tmp));
1151 tmp = gfc_build_addr_expr (NULL_TREE, tmp);
1152 gfc_conv_descriptor_data_set (pre, desc, tmp);
1153 }
1154 else
1155 {
1156 /* Allocate memory to hold the data or call internal_pack. */
1157 if (initial == NULL_TREE)
1158 {
1159 tmp = gfc_call_malloc (pre, NULL, size);
1160 tmp = gfc_evaluate_now (tmp, pre);
1161 }
1162 else
1163 {
1164 tree packed;
1165 tree source_data;
1166 tree was_packed;
1167 stmtblock_t do_copying;
1168
1169 tmp = TREE_TYPE (initial); /* Pointer to descriptor. */
1170 gcc_assert (TREE_CODE (tmp) == POINTER_TYPE);
1171 tmp = TREE_TYPE (tmp); /* The descriptor itself. */
1172 tmp = gfc_get_element_type (tmp);
1173 packed = gfc_create_var (build_pointer_type (tmp), "data");
1174
1175 tmp = build_call_expr_loc (input_location,
1176 gfor_fndecl_in_pack, 1, initial);
1177 tmp = fold_convert (TREE_TYPE (packed), tmp);
1178 gfc_add_modify (pre, packed, tmp);
1179
1180 tmp = build_fold_indirect_ref_loc (input_location,
1181 initial);
1182 source_data = gfc_conv_descriptor_data_get (tmp);
1183
1184 /* internal_pack may return source->data without any allocation
1185 or copying if it is already packed. If that's the case, we
1186 need to allocate and copy manually. */
1187
1188 gfc_start_block (&do_copying);
1189 tmp = gfc_call_malloc (&do_copying, NULL, size);
1190 tmp = fold_convert (TREE_TYPE (packed), tmp);
1191 gfc_add_modify (&do_copying, packed, tmp);
1192 tmp = gfc_build_memcpy_call (packed, source_data, size);
1193 gfc_add_expr_to_block (&do_copying, tmp);
1194
1195 was_packed = fold_build2_loc (input_location, EQ_EXPR,
1196 logical_type_node, packed,
1197 source_data);
1198 tmp = gfc_finish_block (&do_copying);
1199 tmp = build3_v (COND_EXPR, was_packed, tmp,
1200 build_empty_stmt (input_location));
1201 gfc_add_expr_to_block (pre, tmp);
1202
1203 tmp = fold_convert (pvoid_type_node, packed);
1204 }
1205
1206 gfc_conv_descriptor_data_set (pre, desc, tmp);
1207 }
1208 }
1209 info->data = gfc_conv_descriptor_data_get (desc);
1210
1211 /* The offset is zero because we create temporaries with a zero
1212 lower bound. */
1213 gfc_conv_descriptor_offset_set (pre, desc, gfc_index_zero_node);
1214
1215 if (dealloc && !onstack)
1216 {
1217 /* Free the temporary. */
1218 tmp = gfc_conv_descriptor_data_get (desc);
1219 tmp = gfc_call_free (tmp);
1220 gfc_add_expr_to_block (post, tmp);
1221 }
1222 }
1223
1224
1225 /* Get the scalarizer array dimension corresponding to actual array dimension
1226 given by ARRAY_DIM.
1227
1228 For example, if SS represents the array ref a(1,:,:,1), it is a
1229 bidimensional scalarizer array, and the result would be 0 for ARRAY_DIM=1,
1230 and 1 for ARRAY_DIM=2.
1231 If SS represents transpose(a(:,1,1,:)), it is again a bidimensional
1232 scalarizer array, and the result would be 1 for ARRAY_DIM=0 and 0 for
1233 ARRAY_DIM=3.
1234 If SS represents sum(a(:,:,:,1), dim=1), it is a 2+1-dimensional scalarizer
1235 array. If called on the inner ss, the result would be respectively 0,1,2 for
1236 ARRAY_DIM=0,1,2. If called on the outer ss, the result would be 0,1
1237 for ARRAY_DIM=1,2. */
1238
1239 static int
get_scalarizer_dim_for_array_dim(gfc_ss * ss,int array_dim)1240 get_scalarizer_dim_for_array_dim (gfc_ss *ss, int array_dim)
1241 {
1242 int array_ref_dim;
1243 int n;
1244
1245 array_ref_dim = 0;
1246
1247 for (; ss; ss = ss->parent)
1248 for (n = 0; n < ss->dimen; n++)
1249 if (ss->dim[n] < array_dim)
1250 array_ref_dim++;
1251
1252 return array_ref_dim;
1253 }
1254
1255
1256 static gfc_ss *
innermost_ss(gfc_ss * ss)1257 innermost_ss (gfc_ss *ss)
1258 {
1259 while (ss->nested_ss != NULL)
1260 ss = ss->nested_ss;
1261
1262 return ss;
1263 }
1264
1265
1266
1267 /* Get the array reference dimension corresponding to the given loop dimension.
1268 It is different from the true array dimension given by the dim array in
1269 the case of a partial array reference (i.e. a(:,:,1,:) for example)
1270 It is different from the loop dimension in the case of a transposed array.
1271 */
1272
1273 static int
get_array_ref_dim_for_loop_dim(gfc_ss * ss,int loop_dim)1274 get_array_ref_dim_for_loop_dim (gfc_ss *ss, int loop_dim)
1275 {
1276 return get_scalarizer_dim_for_array_dim (innermost_ss (ss),
1277 ss->dim[loop_dim]);
1278 }
1279
1280
1281 /* Use the information in the ss to obtain the required information about
1282 the type and size of an array temporary, when the lhs in an assignment
1283 is a class expression. */
1284
1285 static tree
get_class_info_from_ss(stmtblock_t * pre,gfc_ss * ss,tree * eltype)1286 get_class_info_from_ss (stmtblock_t * pre, gfc_ss *ss, tree *eltype)
1287 {
1288 gfc_ss *lhs_ss;
1289 gfc_ss *rhs_ss;
1290 tree tmp;
1291 tree tmp2;
1292 tree vptr;
1293 tree rhs_class_expr = NULL_TREE;
1294 tree lhs_class_expr = NULL_TREE;
1295 bool unlimited_rhs = false;
1296 bool unlimited_lhs = false;
1297 bool rhs_function = false;
1298 gfc_symbol *vtab;
1299
1300 /* The second element in the loop chain contains the source for the
1301 temporary; ie. the rhs of the assignment. */
1302 rhs_ss = ss->loop->ss->loop_chain;
1303
1304 if (rhs_ss != gfc_ss_terminator
1305 && rhs_ss->info
1306 && rhs_ss->info->expr
1307 && rhs_ss->info->expr->ts.type == BT_CLASS
1308 && rhs_ss->info->data.array.descriptor)
1309 {
1310 if (rhs_ss->info->expr->expr_type != EXPR_VARIABLE)
1311 rhs_class_expr
1312 = gfc_get_class_from_expr (rhs_ss->info->data.array.descriptor);
1313 else
1314 rhs_class_expr = gfc_get_class_from_gfc_expr (rhs_ss->info->expr);
1315 unlimited_rhs = UNLIMITED_POLY (rhs_ss->info->expr);
1316 if (rhs_ss->info->expr->expr_type == EXPR_FUNCTION)
1317 rhs_function = true;
1318 }
1319
1320 /* For an assignment the lhs is the next element in the loop chain.
1321 If we have a class rhs, this had better be a class variable
1322 expression! */
1323 lhs_ss = rhs_ss->loop_chain;
1324 if (lhs_ss != gfc_ss_terminator
1325 && lhs_ss->info
1326 && lhs_ss->info->expr
1327 && lhs_ss->info->expr->expr_type ==EXPR_VARIABLE
1328 && lhs_ss->info->expr->ts.type == BT_CLASS)
1329 {
1330 tmp = lhs_ss->info->data.array.descriptor;
1331 unlimited_lhs = UNLIMITED_POLY (rhs_ss->info->expr);
1332 }
1333 else
1334 tmp = NULL_TREE;
1335
1336 /* Get the lhs class expression. */
1337 if (tmp != NULL_TREE && lhs_ss->loop_chain == gfc_ss_terminator)
1338 lhs_class_expr = gfc_get_class_from_expr (tmp);
1339 else
1340 return rhs_class_expr;
1341
1342 gcc_assert (GFC_CLASS_TYPE_P (TREE_TYPE (lhs_class_expr)));
1343
1344 /* Set the lhs vptr and, if necessary, the _len field. */
1345 if (rhs_class_expr)
1346 {
1347 /* Both lhs and rhs are class expressions. */
1348 tmp = gfc_class_vptr_get (lhs_class_expr);
1349 gfc_add_modify (pre, tmp,
1350 fold_convert (TREE_TYPE (tmp),
1351 gfc_class_vptr_get (rhs_class_expr)));
1352 if (unlimited_lhs)
1353 {
1354 tmp = gfc_class_len_get (lhs_class_expr);
1355 if (unlimited_rhs)
1356 tmp2 = gfc_class_len_get (rhs_class_expr);
1357 else
1358 tmp2 = build_int_cst (TREE_TYPE (tmp), 0);
1359 gfc_add_modify (pre, tmp, tmp2);
1360 }
1361
1362 if (rhs_function)
1363 {
1364 tmp = gfc_class_data_get (rhs_class_expr);
1365 gfc_conv_descriptor_offset_set (pre, tmp, gfc_index_zero_node);
1366 }
1367 }
1368 else
1369 {
1370 /* lhs is class and rhs is intrinsic or derived type. */
1371 *eltype = TREE_TYPE (rhs_ss->info->data.array.descriptor);
1372 *eltype = gfc_get_element_type (*eltype);
1373 vtab = gfc_find_vtab (&rhs_ss->info->expr->ts);
1374 vptr = vtab->backend_decl;
1375 if (vptr == NULL_TREE)
1376 vptr = gfc_get_symbol_decl (vtab);
1377 vptr = gfc_build_addr_expr (NULL_TREE, vptr);
1378 tmp = gfc_class_vptr_get (lhs_class_expr);
1379 gfc_add_modify (pre, tmp,
1380 fold_convert (TREE_TYPE (tmp), vptr));
1381
1382 if (unlimited_lhs)
1383 {
1384 tmp = gfc_class_len_get (lhs_class_expr);
1385 if (rhs_ss->info
1386 && rhs_ss->info->expr
1387 && rhs_ss->info->expr->ts.type == BT_CHARACTER)
1388 tmp2 = build_int_cst (TREE_TYPE (tmp),
1389 rhs_ss->info->expr->ts.kind);
1390 else
1391 tmp2 = build_int_cst (TREE_TYPE (tmp), 0);
1392 gfc_add_modify (pre, tmp, tmp2);
1393 }
1394 }
1395
1396 return rhs_class_expr;
1397 }
1398
1399
1400
1401 /* Generate code to create and initialize the descriptor for a temporary
1402 array. This is used for both temporaries needed by the scalarizer, and
1403 functions returning arrays. Adjusts the loop variables to be
1404 zero-based, and calculates the loop bounds for callee allocated arrays.
1405 Allocate the array unless it's callee allocated (we have a callee
1406 allocated array if 'callee_alloc' is true, or if loop->to[n] is
1407 NULL_TREE for any n). Also fills in the descriptor, data and offset
1408 fields of info if known. Returns the size of the array, or NULL for a
1409 callee allocated array.
1410
1411 'eltype' == NULL signals that the temporary should be a class object.
1412 The 'initial' expression is used to obtain the size of the dynamic
1413 type; otherwise the allocation and initialization proceeds as for any
1414 other expression
1415
1416 PRE, POST, INITIAL, DYNAMIC and DEALLOC are as for
1417 gfc_trans_allocate_array_storage. */
1418
1419 tree
gfc_trans_create_temp_array(stmtblock_t * pre,stmtblock_t * post,gfc_ss * ss,tree eltype,tree initial,bool dynamic,bool dealloc,bool callee_alloc,locus * where)1420 gfc_trans_create_temp_array (stmtblock_t * pre, stmtblock_t * post, gfc_ss * ss,
1421 tree eltype, tree initial, bool dynamic,
1422 bool dealloc, bool callee_alloc, locus * where)
1423 {
1424 gfc_loopinfo *loop;
1425 gfc_ss *s;
1426 gfc_array_info *info;
1427 tree from[GFC_MAX_DIMENSIONS], to[GFC_MAX_DIMENSIONS];
1428 tree type;
1429 tree desc;
1430 tree tmp;
1431 tree size;
1432 tree nelem;
1433 tree cond;
1434 tree or_expr;
1435 tree elemsize;
1436 tree class_expr = NULL_TREE;
1437 int n, dim, tmp_dim;
1438 int total_dim = 0;
1439
1440 /* This signals a class array for which we need the size of the
1441 dynamic type. Generate an eltype and then the class expression. */
1442 if (eltype == NULL_TREE && initial)
1443 {
1444 gcc_assert (POINTER_TYPE_P (TREE_TYPE (initial)));
1445 class_expr = build_fold_indirect_ref_loc (input_location, initial);
1446 /* Obtain the structure (class) expression. */
1447 class_expr = gfc_get_class_from_expr (class_expr);
1448 gcc_assert (class_expr);
1449 }
1450
1451 /* Otherwise, some expressions, such as class functions, arising from
1452 dependency checking in assignments come here with class element type.
1453 The descriptor can be obtained from the ss->info and then converted
1454 to the class object. */
1455 if (class_expr == NULL_TREE && GFC_CLASS_TYPE_P (eltype))
1456 class_expr = get_class_info_from_ss (pre, ss, &eltype);
1457
1458 /* If the dynamic type is not available, use the declared type. */
1459 if (eltype && GFC_CLASS_TYPE_P (eltype))
1460 eltype = gfc_get_element_type (TREE_TYPE (TYPE_FIELDS (eltype)));
1461
1462 if (class_expr == NULL_TREE)
1463 elemsize = fold_convert (gfc_array_index_type,
1464 TYPE_SIZE_UNIT (eltype));
1465 else
1466 {
1467 /* Unlimited polymorphic entities are initialised with NULL vptr. They
1468 can be tested for by checking if the len field is present. If so
1469 test the vptr before using the vtable size. */
1470 tmp = gfc_class_vptr_get (class_expr);
1471 tmp = fold_build2_loc (input_location, NE_EXPR,
1472 logical_type_node,
1473 tmp, build_int_cst (TREE_TYPE (tmp), 0));
1474 elemsize = fold_build3_loc (input_location, COND_EXPR,
1475 gfc_array_index_type,
1476 tmp,
1477 gfc_class_vtab_size_get (class_expr),
1478 gfc_index_zero_node);
1479 elemsize = gfc_evaluate_now (elemsize, pre);
1480 elemsize = gfc_resize_class_size_with_len (pre, class_expr, elemsize);
1481 /* Casting the data as a character of the dynamic length ensures that
1482 assignment of elements works when needed. */
1483 eltype = gfc_get_character_type_len (1, elemsize);
1484 }
1485
1486 memset (from, 0, sizeof (from));
1487 memset (to, 0, sizeof (to));
1488
1489 info = &ss->info->data.array;
1490
1491 gcc_assert (ss->dimen > 0);
1492 gcc_assert (ss->loop->dimen == ss->dimen);
1493
1494 if (warn_array_temporaries && where)
1495 gfc_warning (OPT_Warray_temporaries,
1496 "Creating array temporary at %L", where);
1497
1498 /* Set the lower bound to zero. */
1499 for (s = ss; s; s = s->parent)
1500 {
1501 loop = s->loop;
1502
1503 total_dim += loop->dimen;
1504 for (n = 0; n < loop->dimen; n++)
1505 {
1506 dim = s->dim[n];
1507
1508 /* Callee allocated arrays may not have a known bound yet. */
1509 if (loop->to[n])
1510 loop->to[n] = gfc_evaluate_now (
1511 fold_build2_loc (input_location, MINUS_EXPR,
1512 gfc_array_index_type,
1513 loop->to[n], loop->from[n]),
1514 pre);
1515 loop->from[n] = gfc_index_zero_node;
1516
1517 /* We have just changed the loop bounds, we must clear the
1518 corresponding specloop, so that delta calculation is not skipped
1519 later in gfc_set_delta. */
1520 loop->specloop[n] = NULL;
1521
1522 /* We are constructing the temporary's descriptor based on the loop
1523 dimensions. As the dimensions may be accessed in arbitrary order
1524 (think of transpose) the size taken from the n'th loop may not map
1525 to the n'th dimension of the array. We need to reconstruct loop
1526 infos in the right order before using it to set the descriptor
1527 bounds. */
1528 tmp_dim = get_scalarizer_dim_for_array_dim (ss, dim);
1529 from[tmp_dim] = loop->from[n];
1530 to[tmp_dim] = loop->to[n];
1531
1532 info->delta[dim] = gfc_index_zero_node;
1533 info->start[dim] = gfc_index_zero_node;
1534 info->end[dim] = gfc_index_zero_node;
1535 info->stride[dim] = gfc_index_one_node;
1536 }
1537 }
1538
1539 /* Initialize the descriptor. */
1540 type =
1541 gfc_get_array_type_bounds (eltype, total_dim, 0, from, to, 1,
1542 GFC_ARRAY_UNKNOWN, true);
1543 desc = gfc_create_var (type, "atmp");
1544 GFC_DECL_PACKED_ARRAY (desc) = 1;
1545
1546 /* Emit a DECL_EXPR for the variable sized array type in
1547 GFC_TYPE_ARRAY_DATAPTR_TYPE so the gimplification of its type
1548 sizes works correctly. */
1549 tree arraytype = TREE_TYPE (GFC_TYPE_ARRAY_DATAPTR_TYPE (type));
1550 if (! TYPE_NAME (arraytype))
1551 TYPE_NAME (arraytype) = build_decl (UNKNOWN_LOCATION, TYPE_DECL,
1552 NULL_TREE, arraytype);
1553 gfc_add_expr_to_block (pre, build1 (DECL_EXPR,
1554 arraytype, TYPE_NAME (arraytype)));
1555
1556 if (class_expr != NULL_TREE)
1557 {
1558 tree class_data;
1559 tree dtype;
1560
1561 /* Create a class temporary. */
1562 tmp = gfc_create_var (TREE_TYPE (class_expr), "ctmp");
1563 gfc_add_modify (pre, tmp, class_expr);
1564
1565 /* Assign the new descriptor to the _data field. This allows the
1566 vptr _copy to be used for scalarized assignment since the class
1567 temporary can be found from the descriptor. */
1568 class_data = gfc_class_data_get (tmp);
1569 tmp = fold_build1_loc (input_location, VIEW_CONVERT_EXPR,
1570 TREE_TYPE (desc), desc);
1571 gfc_add_modify (pre, class_data, tmp);
1572
1573 /* Take the dtype from the class expression. */
1574 dtype = gfc_conv_descriptor_dtype (gfc_class_data_get (class_expr));
1575 tmp = gfc_conv_descriptor_dtype (class_data);
1576 gfc_add_modify (pre, tmp, dtype);
1577
1578 /* Point desc to the class _data field. */
1579 desc = class_data;
1580 }
1581 else
1582 {
1583 /* Fill in the array dtype. */
1584 tmp = gfc_conv_descriptor_dtype (desc);
1585 gfc_add_modify (pre, tmp, gfc_get_dtype (TREE_TYPE (desc)));
1586 }
1587
1588 info->descriptor = desc;
1589 size = gfc_index_one_node;
1590
1591 /*
1592 Fill in the bounds and stride. This is a packed array, so:
1593
1594 size = 1;
1595 for (n = 0; n < rank; n++)
1596 {
1597 stride[n] = size
1598 delta = ubound[n] + 1 - lbound[n];
1599 size = size * delta;
1600 }
1601 size = size * sizeof(element);
1602 */
1603
1604 or_expr = NULL_TREE;
1605
1606 /* If there is at least one null loop->to[n], it is a callee allocated
1607 array. */
1608 for (n = 0; n < total_dim; n++)
1609 if (to[n] == NULL_TREE)
1610 {
1611 size = NULL_TREE;
1612 break;
1613 }
1614
1615 if (size == NULL_TREE)
1616 for (s = ss; s; s = s->parent)
1617 for (n = 0; n < s->loop->dimen; n++)
1618 {
1619 dim = get_scalarizer_dim_for_array_dim (ss, s->dim[n]);
1620
1621 /* For a callee allocated array express the loop bounds in terms
1622 of the descriptor fields. */
1623 tmp = fold_build2_loc (input_location,
1624 MINUS_EXPR, gfc_array_index_type,
1625 gfc_conv_descriptor_ubound_get (desc, gfc_rank_cst[dim]),
1626 gfc_conv_descriptor_lbound_get (desc, gfc_rank_cst[dim]));
1627 s->loop->to[n] = tmp;
1628 }
1629 else
1630 {
1631 for (n = 0; n < total_dim; n++)
1632 {
1633 /* Store the stride and bound components in the descriptor. */
1634 gfc_conv_descriptor_stride_set (pre, desc, gfc_rank_cst[n], size);
1635
1636 gfc_conv_descriptor_lbound_set (pre, desc, gfc_rank_cst[n],
1637 gfc_index_zero_node);
1638
1639 gfc_conv_descriptor_ubound_set (pre, desc, gfc_rank_cst[n], to[n]);
1640
1641 tmp = fold_build2_loc (input_location, PLUS_EXPR,
1642 gfc_array_index_type,
1643 to[n], gfc_index_one_node);
1644
1645 /* Check whether the size for this dimension is negative. */
1646 cond = fold_build2_loc (input_location, LE_EXPR, logical_type_node,
1647 tmp, gfc_index_zero_node);
1648 cond = gfc_evaluate_now (cond, pre);
1649
1650 if (n == 0)
1651 or_expr = cond;
1652 else
1653 or_expr = fold_build2_loc (input_location, TRUTH_OR_EXPR,
1654 logical_type_node, or_expr, cond);
1655
1656 size = fold_build2_loc (input_location, MULT_EXPR,
1657 gfc_array_index_type, size, tmp);
1658 size = gfc_evaluate_now (size, pre);
1659 }
1660 }
1661
1662 /* Get the size of the array. */
1663 if (size && !callee_alloc)
1664 {
1665 /* If or_expr is true, then the extent in at least one
1666 dimension is zero and the size is set to zero. */
1667 size = fold_build3_loc (input_location, COND_EXPR, gfc_array_index_type,
1668 or_expr, gfc_index_zero_node, size);
1669
1670 nelem = size;
1671 size = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
1672 size, elemsize);
1673 }
1674 else
1675 {
1676 nelem = size;
1677 size = NULL_TREE;
1678 }
1679
1680 /* Set the span. */
1681 tmp = fold_convert (gfc_array_index_type, elemsize);
1682 gfc_conv_descriptor_span_set (pre, desc, tmp);
1683
1684 gfc_trans_allocate_array_storage (pre, post, info, size, nelem, initial,
1685 dynamic, dealloc);
1686
1687 while (ss->parent)
1688 ss = ss->parent;
1689
1690 if (ss->dimen > ss->loop->temp_dim)
1691 ss->loop->temp_dim = ss->dimen;
1692
1693 return size;
1694 }
1695
1696
1697 /* Return the number of iterations in a loop that starts at START,
1698 ends at END, and has step STEP. */
1699
1700 static tree
gfc_get_iteration_count(tree start,tree end,tree step)1701 gfc_get_iteration_count (tree start, tree end, tree step)
1702 {
1703 tree tmp;
1704 tree type;
1705
1706 type = TREE_TYPE (step);
1707 tmp = fold_build2_loc (input_location, MINUS_EXPR, type, end, start);
1708 tmp = fold_build2_loc (input_location, FLOOR_DIV_EXPR, type, tmp, step);
1709 tmp = fold_build2_loc (input_location, PLUS_EXPR, type, tmp,
1710 build_int_cst (type, 1));
1711 tmp = fold_build2_loc (input_location, MAX_EXPR, type, tmp,
1712 build_int_cst (type, 0));
1713 return fold_convert (gfc_array_index_type, tmp);
1714 }
1715
1716
1717 /* Extend the data in array DESC by EXTRA elements. */
1718
1719 static void
gfc_grow_array(stmtblock_t * pblock,tree desc,tree extra)1720 gfc_grow_array (stmtblock_t * pblock, tree desc, tree extra)
1721 {
1722 tree arg0, arg1;
1723 tree tmp;
1724 tree size;
1725 tree ubound;
1726
1727 if (integer_zerop (extra))
1728 return;
1729
1730 ubound = gfc_conv_descriptor_ubound_get (desc, gfc_rank_cst[0]);
1731
1732 /* Add EXTRA to the upper bound. */
1733 tmp = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
1734 ubound, extra);
1735 gfc_conv_descriptor_ubound_set (pblock, desc, gfc_rank_cst[0], tmp);
1736
1737 /* Get the value of the current data pointer. */
1738 arg0 = gfc_conv_descriptor_data_get (desc);
1739
1740 /* Calculate the new array size. */
1741 size = TYPE_SIZE_UNIT (gfc_get_element_type (TREE_TYPE (desc)));
1742 tmp = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
1743 ubound, gfc_index_one_node);
1744 arg1 = fold_build2_loc (input_location, MULT_EXPR, size_type_node,
1745 fold_convert (size_type_node, tmp),
1746 fold_convert (size_type_node, size));
1747
1748 /* Call the realloc() function. */
1749 tmp = gfc_call_realloc (pblock, arg0, arg1);
1750 gfc_conv_descriptor_data_set (pblock, desc, tmp);
1751 }
1752
1753
1754 /* Return true if the bounds of iterator I can only be determined
1755 at run time. */
1756
1757 static inline bool
gfc_iterator_has_dynamic_bounds(gfc_iterator * i)1758 gfc_iterator_has_dynamic_bounds (gfc_iterator * i)
1759 {
1760 return (i->start->expr_type != EXPR_CONSTANT
1761 || i->end->expr_type != EXPR_CONSTANT
1762 || i->step->expr_type != EXPR_CONSTANT);
1763 }
1764
1765
1766 /* Split the size of constructor element EXPR into the sum of two terms,
1767 one of which can be determined at compile time and one of which must
1768 be calculated at run time. Set *SIZE to the former and return true
1769 if the latter might be nonzero. */
1770
1771 static bool
gfc_get_array_constructor_element_size(mpz_t * size,gfc_expr * expr)1772 gfc_get_array_constructor_element_size (mpz_t * size, gfc_expr * expr)
1773 {
1774 if (expr->expr_type == EXPR_ARRAY)
1775 return gfc_get_array_constructor_size (size, expr->value.constructor);
1776 else if (expr->rank > 0)
1777 {
1778 /* Calculate everything at run time. */
1779 mpz_set_ui (*size, 0);
1780 return true;
1781 }
1782 else
1783 {
1784 /* A single element. */
1785 mpz_set_ui (*size, 1);
1786 return false;
1787 }
1788 }
1789
1790
1791 /* Like gfc_get_array_constructor_element_size, but applied to the whole
1792 of array constructor C. */
1793
1794 static bool
gfc_get_array_constructor_size(mpz_t * size,gfc_constructor_base base)1795 gfc_get_array_constructor_size (mpz_t * size, gfc_constructor_base base)
1796 {
1797 gfc_constructor *c;
1798 gfc_iterator *i;
1799 mpz_t val;
1800 mpz_t len;
1801 bool dynamic;
1802
1803 mpz_set_ui (*size, 0);
1804 mpz_init (len);
1805 mpz_init (val);
1806
1807 dynamic = false;
1808 for (c = gfc_constructor_first (base); c; c = gfc_constructor_next (c))
1809 {
1810 i = c->iterator;
1811 if (i && gfc_iterator_has_dynamic_bounds (i))
1812 dynamic = true;
1813 else
1814 {
1815 dynamic |= gfc_get_array_constructor_element_size (&len, c->expr);
1816 if (i)
1817 {
1818 /* Multiply the static part of the element size by the
1819 number of iterations. */
1820 mpz_sub (val, i->end->value.integer, i->start->value.integer);
1821 mpz_fdiv_q (val, val, i->step->value.integer);
1822 mpz_add_ui (val, val, 1);
1823 if (mpz_sgn (val) > 0)
1824 mpz_mul (len, len, val);
1825 else
1826 mpz_set_ui (len, 0);
1827 }
1828 mpz_add (*size, *size, len);
1829 }
1830 }
1831 mpz_clear (len);
1832 mpz_clear (val);
1833 return dynamic;
1834 }
1835
1836
1837 /* Make sure offset is a variable. */
1838
1839 static void
gfc_put_offset_into_var(stmtblock_t * pblock,tree * poffset,tree * offsetvar)1840 gfc_put_offset_into_var (stmtblock_t * pblock, tree * poffset,
1841 tree * offsetvar)
1842 {
1843 /* We should have already created the offset variable. We cannot
1844 create it here because we may be in an inner scope. */
1845 gcc_assert (*offsetvar != NULL_TREE);
1846 gfc_add_modify (pblock, *offsetvar, *poffset);
1847 *poffset = *offsetvar;
1848 TREE_USED (*offsetvar) = 1;
1849 }
1850
1851
1852 /* Variables needed for bounds-checking. */
1853 static bool first_len;
1854 static tree first_len_val;
1855 static bool typespec_chararray_ctor;
1856
1857 static void
gfc_trans_array_ctor_element(stmtblock_t * pblock,tree desc,tree offset,gfc_se * se,gfc_expr * expr)1858 gfc_trans_array_ctor_element (stmtblock_t * pblock, tree desc,
1859 tree offset, gfc_se * se, gfc_expr * expr)
1860 {
1861 tree tmp;
1862
1863 gfc_conv_expr (se, expr);
1864
1865 /* Store the value. */
1866 tmp = build_fold_indirect_ref_loc (input_location,
1867 gfc_conv_descriptor_data_get (desc));
1868 tmp = gfc_build_array_ref (tmp, offset, NULL);
1869
1870 if (expr->ts.type == BT_CHARACTER)
1871 {
1872 int i = gfc_validate_kind (BT_CHARACTER, expr->ts.kind, false);
1873 tree esize;
1874
1875 esize = size_in_bytes (gfc_get_element_type (TREE_TYPE (desc)));
1876 esize = fold_convert (gfc_charlen_type_node, esize);
1877 esize = fold_build2_loc (input_location, TRUNC_DIV_EXPR,
1878 TREE_TYPE (esize), esize,
1879 build_int_cst (TREE_TYPE (esize),
1880 gfc_character_kinds[i].bit_size / 8));
1881
1882 gfc_conv_string_parameter (se);
1883 if (POINTER_TYPE_P (TREE_TYPE (tmp)))
1884 {
1885 /* The temporary is an array of pointers. */
1886 se->expr = fold_convert (TREE_TYPE (tmp), se->expr);
1887 gfc_add_modify (&se->pre, tmp, se->expr);
1888 }
1889 else
1890 {
1891 /* The temporary is an array of string values. */
1892 tmp = gfc_build_addr_expr (gfc_get_pchar_type (expr->ts.kind), tmp);
1893 /* We know the temporary and the value will be the same length,
1894 so can use memcpy. */
1895 gfc_trans_string_copy (&se->pre, esize, tmp, expr->ts.kind,
1896 se->string_length, se->expr, expr->ts.kind);
1897 }
1898 if ((gfc_option.rtcheck & GFC_RTCHECK_BOUNDS) && !typespec_chararray_ctor)
1899 {
1900 if (first_len)
1901 {
1902 gfc_add_modify (&se->pre, first_len_val,
1903 fold_convert (TREE_TYPE (first_len_val),
1904 se->string_length));
1905 first_len = false;
1906 }
1907 else
1908 {
1909 /* Verify that all constructor elements are of the same
1910 length. */
1911 tree rhs = fold_convert (TREE_TYPE (first_len_val),
1912 se->string_length);
1913 tree cond = fold_build2_loc (input_location, NE_EXPR,
1914 logical_type_node, first_len_val,
1915 rhs);
1916 gfc_trans_runtime_check
1917 (true, false, cond, &se->pre, &expr->where,
1918 "Different CHARACTER lengths (%ld/%ld) in array constructor",
1919 fold_convert (long_integer_type_node, first_len_val),
1920 fold_convert (long_integer_type_node, se->string_length));
1921 }
1922 }
1923 }
1924 else if (GFC_CLASS_TYPE_P (TREE_TYPE (se->expr))
1925 && !GFC_CLASS_TYPE_P (gfc_get_element_type (TREE_TYPE (desc))))
1926 {
1927 /* Assignment of a CLASS array constructor to a derived type array. */
1928 if (expr->expr_type == EXPR_FUNCTION)
1929 se->expr = gfc_evaluate_now (se->expr, pblock);
1930 se->expr = gfc_class_data_get (se->expr);
1931 se->expr = build_fold_indirect_ref_loc (input_location, se->expr);
1932 se->expr = fold_convert (TREE_TYPE (tmp), se->expr);
1933 gfc_add_modify (&se->pre, tmp, se->expr);
1934 }
1935 else
1936 {
1937 /* TODO: Should the frontend already have done this conversion? */
1938 se->expr = fold_convert (TREE_TYPE (tmp), se->expr);
1939 gfc_add_modify (&se->pre, tmp, se->expr);
1940 }
1941
1942 gfc_add_block_to_block (pblock, &se->pre);
1943 gfc_add_block_to_block (pblock, &se->post);
1944 }
1945
1946
1947 /* Add the contents of an array to the constructor. DYNAMIC is as for
1948 gfc_trans_array_constructor_value. */
1949
1950 static void
gfc_trans_array_constructor_subarray(stmtblock_t * pblock,tree type ATTRIBUTE_UNUSED,tree desc,gfc_expr * expr,tree * poffset,tree * offsetvar,bool dynamic)1951 gfc_trans_array_constructor_subarray (stmtblock_t * pblock,
1952 tree type ATTRIBUTE_UNUSED,
1953 tree desc, gfc_expr * expr,
1954 tree * poffset, tree * offsetvar,
1955 bool dynamic)
1956 {
1957 gfc_se se;
1958 gfc_ss *ss;
1959 gfc_loopinfo loop;
1960 stmtblock_t body;
1961 tree tmp;
1962 tree size;
1963 int n;
1964
1965 /* We need this to be a variable so we can increment it. */
1966 gfc_put_offset_into_var (pblock, poffset, offsetvar);
1967
1968 gfc_init_se (&se, NULL);
1969
1970 /* Walk the array expression. */
1971 ss = gfc_walk_expr (expr);
1972 gcc_assert (ss != gfc_ss_terminator);
1973
1974 /* Initialize the scalarizer. */
1975 gfc_init_loopinfo (&loop);
1976 gfc_add_ss_to_loop (&loop, ss);
1977
1978 /* Initialize the loop. */
1979 gfc_conv_ss_startstride (&loop);
1980 gfc_conv_loop_setup (&loop, &expr->where);
1981
1982 /* Make sure the constructed array has room for the new data. */
1983 if (dynamic)
1984 {
1985 /* Set SIZE to the total number of elements in the subarray. */
1986 size = gfc_index_one_node;
1987 for (n = 0; n < loop.dimen; n++)
1988 {
1989 tmp = gfc_get_iteration_count (loop.from[n], loop.to[n],
1990 gfc_index_one_node);
1991 size = fold_build2_loc (input_location, MULT_EXPR,
1992 gfc_array_index_type, size, tmp);
1993 }
1994
1995 /* Grow the constructed array by SIZE elements. */
1996 gfc_grow_array (&loop.pre, desc, size);
1997 }
1998
1999 /* Make the loop body. */
2000 gfc_mark_ss_chain_used (ss, 1);
2001 gfc_start_scalarized_body (&loop, &body);
2002 gfc_copy_loopinfo_to_se (&se, &loop);
2003 se.ss = ss;
2004
2005 gfc_trans_array_ctor_element (&body, desc, *poffset, &se, expr);
2006 gcc_assert (se.ss == gfc_ss_terminator);
2007
2008 /* Increment the offset. */
2009 tmp = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
2010 *poffset, gfc_index_one_node);
2011 gfc_add_modify (&body, *poffset, tmp);
2012
2013 /* Finish the loop. */
2014 gfc_trans_scalarizing_loops (&loop, &body);
2015 gfc_add_block_to_block (&loop.pre, &loop.post);
2016 tmp = gfc_finish_block (&loop.pre);
2017 gfc_add_expr_to_block (pblock, tmp);
2018
2019 gfc_cleanup_loop (&loop);
2020 }
2021
2022
2023 /* Assign the values to the elements of an array constructor. DYNAMIC
2024 is true if descriptor DESC only contains enough data for the static
2025 size calculated by gfc_get_array_constructor_size. When true, memory
2026 for the dynamic parts must be allocated using realloc. */
2027
2028 static void
gfc_trans_array_constructor_value(stmtblock_t * pblock,tree type,tree desc,gfc_constructor_base base,tree * poffset,tree * offsetvar,bool dynamic)2029 gfc_trans_array_constructor_value (stmtblock_t * pblock, tree type,
2030 tree desc, gfc_constructor_base base,
2031 tree * poffset, tree * offsetvar,
2032 bool dynamic)
2033 {
2034 tree tmp;
2035 tree start = NULL_TREE;
2036 tree end = NULL_TREE;
2037 tree step = NULL_TREE;
2038 stmtblock_t body;
2039 gfc_se se;
2040 mpz_t size;
2041 gfc_constructor *c;
2042
2043 tree shadow_loopvar = NULL_TREE;
2044 gfc_saved_var saved_loopvar;
2045
2046 mpz_init (size);
2047 for (c = gfc_constructor_first (base); c; c = gfc_constructor_next (c))
2048 {
2049 /* If this is an iterator or an array, the offset must be a variable. */
2050 if ((c->iterator || c->expr->rank > 0) && INTEGER_CST_P (*poffset))
2051 gfc_put_offset_into_var (pblock, poffset, offsetvar);
2052
2053 /* Shadowing the iterator avoids changing its value and saves us from
2054 keeping track of it. Further, it makes sure that there's always a
2055 backend-decl for the symbol, even if there wasn't one before,
2056 e.g. in the case of an iterator that appears in a specification
2057 expression in an interface mapping. */
2058 if (c->iterator)
2059 {
2060 gfc_symbol *sym;
2061 tree type;
2062
2063 /* Evaluate loop bounds before substituting the loop variable
2064 in case they depend on it. Such a case is invalid, but it is
2065 not more expensive to do the right thing here.
2066 See PR 44354. */
2067 gfc_init_se (&se, NULL);
2068 gfc_conv_expr_val (&se, c->iterator->start);
2069 gfc_add_block_to_block (pblock, &se.pre);
2070 start = gfc_evaluate_now (se.expr, pblock);
2071
2072 gfc_init_se (&se, NULL);
2073 gfc_conv_expr_val (&se, c->iterator->end);
2074 gfc_add_block_to_block (pblock, &se.pre);
2075 end = gfc_evaluate_now (se.expr, pblock);
2076
2077 gfc_init_se (&se, NULL);
2078 gfc_conv_expr_val (&se, c->iterator->step);
2079 gfc_add_block_to_block (pblock, &se.pre);
2080 step = gfc_evaluate_now (se.expr, pblock);
2081
2082 sym = c->iterator->var->symtree->n.sym;
2083 type = gfc_typenode_for_spec (&sym->ts);
2084
2085 shadow_loopvar = gfc_create_var (type, "shadow_loopvar");
2086 gfc_shadow_sym (sym, shadow_loopvar, &saved_loopvar);
2087 }
2088
2089 gfc_start_block (&body);
2090
2091 if (c->expr->expr_type == EXPR_ARRAY)
2092 {
2093 /* Array constructors can be nested. */
2094 gfc_trans_array_constructor_value (&body, type, desc,
2095 c->expr->value.constructor,
2096 poffset, offsetvar, dynamic);
2097 }
2098 else if (c->expr->rank > 0)
2099 {
2100 gfc_trans_array_constructor_subarray (&body, type, desc, c->expr,
2101 poffset, offsetvar, dynamic);
2102 }
2103 else
2104 {
2105 /* This code really upsets the gimplifier so don't bother for now. */
2106 gfc_constructor *p;
2107 HOST_WIDE_INT n;
2108 HOST_WIDE_INT size;
2109
2110 p = c;
2111 n = 0;
2112 while (p && !(p->iterator || p->expr->expr_type != EXPR_CONSTANT))
2113 {
2114 p = gfc_constructor_next (p);
2115 n++;
2116 }
2117 if (n < 4)
2118 {
2119 /* Scalar values. */
2120 gfc_init_se (&se, NULL);
2121 gfc_trans_array_ctor_element (&body, desc, *poffset,
2122 &se, c->expr);
2123
2124 *poffset = fold_build2_loc (input_location, PLUS_EXPR,
2125 gfc_array_index_type,
2126 *poffset, gfc_index_one_node);
2127 }
2128 else
2129 {
2130 /* Collect multiple scalar constants into a constructor. */
2131 vec<constructor_elt, va_gc> *v = NULL;
2132 tree init;
2133 tree bound;
2134 tree tmptype;
2135 HOST_WIDE_INT idx = 0;
2136
2137 p = c;
2138 /* Count the number of consecutive scalar constants. */
2139 while (p && !(p->iterator
2140 || p->expr->expr_type != EXPR_CONSTANT))
2141 {
2142 gfc_init_se (&se, NULL);
2143 gfc_conv_constant (&se, p->expr);
2144
2145 if (c->expr->ts.type != BT_CHARACTER)
2146 se.expr = fold_convert (type, se.expr);
2147 /* For constant character array constructors we build
2148 an array of pointers. */
2149 else if (POINTER_TYPE_P (type))
2150 se.expr = gfc_build_addr_expr
2151 (gfc_get_pchar_type (p->expr->ts.kind),
2152 se.expr);
2153
2154 CONSTRUCTOR_APPEND_ELT (v,
2155 build_int_cst (gfc_array_index_type,
2156 idx++),
2157 se.expr);
2158 c = p;
2159 p = gfc_constructor_next (p);
2160 }
2161
2162 bound = size_int (n - 1);
2163 /* Create an array type to hold them. */
2164 tmptype = build_range_type (gfc_array_index_type,
2165 gfc_index_zero_node, bound);
2166 tmptype = build_array_type (type, tmptype);
2167
2168 init = build_constructor (tmptype, v);
2169 TREE_CONSTANT (init) = 1;
2170 TREE_STATIC (init) = 1;
2171 /* Create a static variable to hold the data. */
2172 tmp = gfc_create_var (tmptype, "data");
2173 TREE_STATIC (tmp) = 1;
2174 TREE_CONSTANT (tmp) = 1;
2175 TREE_READONLY (tmp) = 1;
2176 DECL_INITIAL (tmp) = init;
2177 init = tmp;
2178
2179 /* Use BUILTIN_MEMCPY to assign the values. */
2180 tmp = gfc_conv_descriptor_data_get (desc);
2181 tmp = build_fold_indirect_ref_loc (input_location,
2182 tmp);
2183 tmp = gfc_build_array_ref (tmp, *poffset, NULL);
2184 tmp = gfc_build_addr_expr (NULL_TREE, tmp);
2185 init = gfc_build_addr_expr (NULL_TREE, init);
2186
2187 size = TREE_INT_CST_LOW (TYPE_SIZE_UNIT (type));
2188 bound = build_int_cst (size_type_node, n * size);
2189 tmp = build_call_expr_loc (input_location,
2190 builtin_decl_explicit (BUILT_IN_MEMCPY),
2191 3, tmp, init, bound);
2192 gfc_add_expr_to_block (&body, tmp);
2193
2194 *poffset = fold_build2_loc (input_location, PLUS_EXPR,
2195 gfc_array_index_type, *poffset,
2196 build_int_cst (gfc_array_index_type, n));
2197 }
2198 if (!INTEGER_CST_P (*poffset))
2199 {
2200 gfc_add_modify (&body, *offsetvar, *poffset);
2201 *poffset = *offsetvar;
2202 }
2203 }
2204
2205 /* The frontend should already have done any expansions
2206 at compile-time. */
2207 if (!c->iterator)
2208 {
2209 /* Pass the code as is. */
2210 tmp = gfc_finish_block (&body);
2211 gfc_add_expr_to_block (pblock, tmp);
2212 }
2213 else
2214 {
2215 /* Build the implied do-loop. */
2216 stmtblock_t implied_do_block;
2217 tree cond;
2218 tree exit_label;
2219 tree loopbody;
2220 tree tmp2;
2221
2222 loopbody = gfc_finish_block (&body);
2223
2224 /* Create a new block that holds the implied-do loop. A temporary
2225 loop-variable is used. */
2226 gfc_start_block(&implied_do_block);
2227
2228 /* Initialize the loop. */
2229 gfc_add_modify (&implied_do_block, shadow_loopvar, start);
2230
2231 /* If this array expands dynamically, and the number of iterations
2232 is not constant, we won't have allocated space for the static
2233 part of C->EXPR's size. Do that now. */
2234 if (dynamic && gfc_iterator_has_dynamic_bounds (c->iterator))
2235 {
2236 /* Get the number of iterations. */
2237 tmp = gfc_get_iteration_count (shadow_loopvar, end, step);
2238
2239 /* Get the static part of C->EXPR's size. */
2240 gfc_get_array_constructor_element_size (&size, c->expr);
2241 tmp2 = gfc_conv_mpz_to_tree (size, gfc_index_integer_kind);
2242
2243 /* Grow the array by TMP * TMP2 elements. */
2244 tmp = fold_build2_loc (input_location, MULT_EXPR,
2245 gfc_array_index_type, tmp, tmp2);
2246 gfc_grow_array (&implied_do_block, desc, tmp);
2247 }
2248
2249 /* Generate the loop body. */
2250 exit_label = gfc_build_label_decl (NULL_TREE);
2251 gfc_start_block (&body);
2252
2253 /* Generate the exit condition. Depending on the sign of
2254 the step variable we have to generate the correct
2255 comparison. */
2256 tmp = fold_build2_loc (input_location, GT_EXPR, logical_type_node,
2257 step, build_int_cst (TREE_TYPE (step), 0));
2258 cond = fold_build3_loc (input_location, COND_EXPR,
2259 logical_type_node, tmp,
2260 fold_build2_loc (input_location, GT_EXPR,
2261 logical_type_node, shadow_loopvar, end),
2262 fold_build2_loc (input_location, LT_EXPR,
2263 logical_type_node, shadow_loopvar, end));
2264 tmp = build1_v (GOTO_EXPR, exit_label);
2265 TREE_USED (exit_label) = 1;
2266 tmp = build3_v (COND_EXPR, cond, tmp,
2267 build_empty_stmt (input_location));
2268 gfc_add_expr_to_block (&body, tmp);
2269
2270 /* The main loop body. */
2271 gfc_add_expr_to_block (&body, loopbody);
2272
2273 /* Increase loop variable by step. */
2274 tmp = fold_build2_loc (input_location, PLUS_EXPR,
2275 TREE_TYPE (shadow_loopvar), shadow_loopvar,
2276 step);
2277 gfc_add_modify (&body, shadow_loopvar, tmp);
2278
2279 /* Finish the loop. */
2280 tmp = gfc_finish_block (&body);
2281 tmp = build1_v (LOOP_EXPR, tmp);
2282 gfc_add_expr_to_block (&implied_do_block, tmp);
2283
2284 /* Add the exit label. */
2285 tmp = build1_v (LABEL_EXPR, exit_label);
2286 gfc_add_expr_to_block (&implied_do_block, tmp);
2287
2288 /* Finish the implied-do loop. */
2289 tmp = gfc_finish_block(&implied_do_block);
2290 gfc_add_expr_to_block(pblock, tmp);
2291
2292 gfc_restore_sym (c->iterator->var->symtree->n.sym, &saved_loopvar);
2293 }
2294 }
2295 mpz_clear (size);
2296 }
2297
2298
2299 /* The array constructor code can create a string length with an operand
2300 in the form of a temporary variable. This variable will retain its
2301 context (current_function_decl). If we store this length tree in a
2302 gfc_charlen structure which is shared by a variable in another
2303 context, the resulting gfc_charlen structure with a variable in a
2304 different context, we could trip the assertion in expand_expr_real_1
2305 when it sees that a variable has been created in one context and
2306 referenced in another.
2307
2308 If this might be the case, we create a new gfc_charlen structure and
2309 link it into the current namespace. */
2310
2311 static void
store_backend_decl(gfc_charlen ** clp,tree len,bool force_new_cl)2312 store_backend_decl (gfc_charlen **clp, tree len, bool force_new_cl)
2313 {
2314 if (force_new_cl)
2315 {
2316 gfc_charlen *new_cl = gfc_new_charlen (gfc_current_ns, *clp);
2317 *clp = new_cl;
2318 }
2319 (*clp)->backend_decl = len;
2320 }
2321
2322 /* A catch-all to obtain the string length for anything that is not
2323 a substring of non-constant length, a constant, array or variable. */
2324
2325 static void
get_array_ctor_all_strlen(stmtblock_t * block,gfc_expr * e,tree * len)2326 get_array_ctor_all_strlen (stmtblock_t *block, gfc_expr *e, tree *len)
2327 {
2328 gfc_se se;
2329
2330 /* Don't bother if we already know the length is a constant. */
2331 if (*len && INTEGER_CST_P (*len))
2332 return;
2333
2334 if (!e->ref && e->ts.u.cl && e->ts.u.cl->length
2335 && e->ts.u.cl->length->expr_type == EXPR_CONSTANT)
2336 {
2337 /* This is easy. */
2338 gfc_conv_const_charlen (e->ts.u.cl);
2339 *len = e->ts.u.cl->backend_decl;
2340 }
2341 else
2342 {
2343 /* Otherwise, be brutal even if inefficient. */
2344 gfc_init_se (&se, NULL);
2345
2346 /* No function call, in case of side effects. */
2347 se.no_function_call = 1;
2348 if (e->rank == 0)
2349 gfc_conv_expr (&se, e);
2350 else
2351 gfc_conv_expr_descriptor (&se, e);
2352
2353 /* Fix the value. */
2354 *len = gfc_evaluate_now (se.string_length, &se.pre);
2355
2356 gfc_add_block_to_block (block, &se.pre);
2357 gfc_add_block_to_block (block, &se.post);
2358
2359 store_backend_decl (&e->ts.u.cl, *len, true);
2360 }
2361 }
2362
2363
2364 /* Figure out the string length of a variable reference expression.
2365 Used by get_array_ctor_strlen. */
2366
2367 static void
get_array_ctor_var_strlen(stmtblock_t * block,gfc_expr * expr,tree * len)2368 get_array_ctor_var_strlen (stmtblock_t *block, gfc_expr * expr, tree * len)
2369 {
2370 gfc_ref *ref;
2371 gfc_typespec *ts;
2372 mpz_t char_len;
2373 gfc_se se;
2374
2375 /* Don't bother if we already know the length is a constant. */
2376 if (*len && INTEGER_CST_P (*len))
2377 return;
2378
2379 ts = &expr->symtree->n.sym->ts;
2380 for (ref = expr->ref; ref; ref = ref->next)
2381 {
2382 switch (ref->type)
2383 {
2384 case REF_ARRAY:
2385 /* Array references don't change the string length. */
2386 if (ts->deferred)
2387 get_array_ctor_all_strlen (block, expr, len);
2388 break;
2389
2390 case REF_COMPONENT:
2391 /* Use the length of the component. */
2392 ts = &ref->u.c.component->ts;
2393 break;
2394
2395 case REF_SUBSTRING:
2396 if (ref->u.ss.end == NULL
2397 || ref->u.ss.start->expr_type != EXPR_CONSTANT
2398 || ref->u.ss.end->expr_type != EXPR_CONSTANT)
2399 {
2400 /* Note that this might evaluate expr. */
2401 get_array_ctor_all_strlen (block, expr, len);
2402 return;
2403 }
2404 mpz_init_set_ui (char_len, 1);
2405 mpz_add (char_len, char_len, ref->u.ss.end->value.integer);
2406 mpz_sub (char_len, char_len, ref->u.ss.start->value.integer);
2407 *len = gfc_conv_mpz_to_tree_type (char_len, gfc_charlen_type_node);
2408 mpz_clear (char_len);
2409 return;
2410
2411 case REF_INQUIRY:
2412 break;
2413
2414 default:
2415 gcc_unreachable ();
2416 }
2417 }
2418
2419 /* A last ditch attempt that is sometimes needed for deferred characters. */
2420 if (!ts->u.cl->backend_decl)
2421 {
2422 gfc_init_se (&se, NULL);
2423 if (expr->rank)
2424 gfc_conv_expr_descriptor (&se, expr);
2425 else
2426 gfc_conv_expr (&se, expr);
2427 gcc_assert (se.string_length != NULL_TREE);
2428 gfc_add_block_to_block (block, &se.pre);
2429 ts->u.cl->backend_decl = se.string_length;
2430 }
2431
2432 *len = ts->u.cl->backend_decl;
2433 }
2434
2435
2436 /* Figure out the string length of a character array constructor.
2437 If len is NULL, don't calculate the length; this happens for recursive calls
2438 when a sub-array-constructor is an element but not at the first position,
2439 so when we're not interested in the length.
2440 Returns TRUE if all elements are character constants. */
2441
2442 bool
get_array_ctor_strlen(stmtblock_t * block,gfc_constructor_base base,tree * len)2443 get_array_ctor_strlen (stmtblock_t *block, gfc_constructor_base base, tree * len)
2444 {
2445 gfc_constructor *c;
2446 bool is_const;
2447
2448 is_const = TRUE;
2449
2450 if (gfc_constructor_first (base) == NULL)
2451 {
2452 if (len)
2453 *len = build_int_cstu (gfc_charlen_type_node, 0);
2454 return is_const;
2455 }
2456
2457 /* Loop over all constructor elements to find out is_const, but in len we
2458 want to store the length of the first, not the last, element. We can
2459 of course exit the loop as soon as is_const is found to be false. */
2460 for (c = gfc_constructor_first (base);
2461 c && is_const; c = gfc_constructor_next (c))
2462 {
2463 switch (c->expr->expr_type)
2464 {
2465 case EXPR_CONSTANT:
2466 if (len && !(*len && INTEGER_CST_P (*len)))
2467 *len = build_int_cstu (gfc_charlen_type_node,
2468 c->expr->value.character.length);
2469 break;
2470
2471 case EXPR_ARRAY:
2472 if (!get_array_ctor_strlen (block, c->expr->value.constructor, len))
2473 is_const = false;
2474 break;
2475
2476 case EXPR_VARIABLE:
2477 is_const = false;
2478 if (len)
2479 get_array_ctor_var_strlen (block, c->expr, len);
2480 break;
2481
2482 default:
2483 is_const = false;
2484 if (len)
2485 get_array_ctor_all_strlen (block, c->expr, len);
2486 break;
2487 }
2488
2489 /* After the first iteration, we don't want the length modified. */
2490 len = NULL;
2491 }
2492
2493 return is_const;
2494 }
2495
2496 /* Check whether the array constructor C consists entirely of constant
2497 elements, and if so returns the number of those elements, otherwise
2498 return zero. Note, an empty or NULL array constructor returns zero. */
2499
2500 unsigned HOST_WIDE_INT
gfc_constant_array_constructor_p(gfc_constructor_base base)2501 gfc_constant_array_constructor_p (gfc_constructor_base base)
2502 {
2503 unsigned HOST_WIDE_INT nelem = 0;
2504
2505 gfc_constructor *c = gfc_constructor_first (base);
2506 while (c)
2507 {
2508 if (c->iterator
2509 || c->expr->rank > 0
2510 || c->expr->expr_type != EXPR_CONSTANT)
2511 return 0;
2512 c = gfc_constructor_next (c);
2513 nelem++;
2514 }
2515 return nelem;
2516 }
2517
2518
2519 /* Given EXPR, the constant array constructor specified by an EXPR_ARRAY,
2520 and the tree type of it's elements, TYPE, return a static constant
2521 variable that is compile-time initialized. */
2522
2523 tree
gfc_build_constant_array_constructor(gfc_expr * expr,tree type)2524 gfc_build_constant_array_constructor (gfc_expr * expr, tree type)
2525 {
2526 tree tmptype, init, tmp;
2527 HOST_WIDE_INT nelem;
2528 gfc_constructor *c;
2529 gfc_array_spec as;
2530 gfc_se se;
2531 int i;
2532 vec<constructor_elt, va_gc> *v = NULL;
2533
2534 /* First traverse the constructor list, converting the constants
2535 to tree to build an initializer. */
2536 nelem = 0;
2537 c = gfc_constructor_first (expr->value.constructor);
2538 while (c)
2539 {
2540 gfc_init_se (&se, NULL);
2541 gfc_conv_constant (&se, c->expr);
2542 if (c->expr->ts.type != BT_CHARACTER)
2543 se.expr = fold_convert (type, se.expr);
2544 else if (POINTER_TYPE_P (type))
2545 se.expr = gfc_build_addr_expr (gfc_get_pchar_type (c->expr->ts.kind),
2546 se.expr);
2547 CONSTRUCTOR_APPEND_ELT (v, build_int_cst (gfc_array_index_type, nelem),
2548 se.expr);
2549 c = gfc_constructor_next (c);
2550 nelem++;
2551 }
2552
2553 /* Next determine the tree type for the array. We use the gfortran
2554 front-end's gfc_get_nodesc_array_type in order to create a suitable
2555 GFC_ARRAY_TYPE_P that may be used by the scalarizer. */
2556
2557 memset (&as, 0, sizeof (gfc_array_spec));
2558
2559 as.rank = expr->rank;
2560 as.type = AS_EXPLICIT;
2561 if (!expr->shape)
2562 {
2563 as.lower[0] = gfc_get_int_expr (gfc_default_integer_kind, NULL, 0);
2564 as.upper[0] = gfc_get_int_expr (gfc_default_integer_kind,
2565 NULL, nelem - 1);
2566 }
2567 else
2568 for (i = 0; i < expr->rank; i++)
2569 {
2570 int tmp = (int) mpz_get_si (expr->shape[i]);
2571 as.lower[i] = gfc_get_int_expr (gfc_default_integer_kind, NULL, 0);
2572 as.upper[i] = gfc_get_int_expr (gfc_default_integer_kind,
2573 NULL, tmp - 1);
2574 }
2575
2576 tmptype = gfc_get_nodesc_array_type (type, &as, PACKED_STATIC, true);
2577
2578 /* as is not needed anymore. */
2579 for (i = 0; i < as.rank + as.corank; i++)
2580 {
2581 gfc_free_expr (as.lower[i]);
2582 gfc_free_expr (as.upper[i]);
2583 }
2584
2585 init = build_constructor (tmptype, v);
2586
2587 TREE_CONSTANT (init) = 1;
2588 TREE_STATIC (init) = 1;
2589
2590 tmp = build_decl (input_location, VAR_DECL, create_tmp_var_name ("A"),
2591 tmptype);
2592 DECL_ARTIFICIAL (tmp) = 1;
2593 DECL_IGNORED_P (tmp) = 1;
2594 TREE_STATIC (tmp) = 1;
2595 TREE_CONSTANT (tmp) = 1;
2596 TREE_READONLY (tmp) = 1;
2597 DECL_INITIAL (tmp) = init;
2598 pushdecl (tmp);
2599
2600 return tmp;
2601 }
2602
2603
2604 /* Translate a constant EXPR_ARRAY array constructor for the scalarizer.
2605 This mostly initializes the scalarizer state info structure with the
2606 appropriate values to directly use the array created by the function
2607 gfc_build_constant_array_constructor. */
2608
2609 static void
trans_constant_array_constructor(gfc_ss * ss,tree type)2610 trans_constant_array_constructor (gfc_ss * ss, tree type)
2611 {
2612 gfc_array_info *info;
2613 tree tmp;
2614 int i;
2615
2616 tmp = gfc_build_constant_array_constructor (ss->info->expr, type);
2617
2618 info = &ss->info->data.array;
2619
2620 info->descriptor = tmp;
2621 info->data = gfc_build_addr_expr (NULL_TREE, tmp);
2622 info->offset = gfc_index_zero_node;
2623
2624 for (i = 0; i < ss->dimen; i++)
2625 {
2626 info->delta[i] = gfc_index_zero_node;
2627 info->start[i] = gfc_index_zero_node;
2628 info->end[i] = gfc_index_zero_node;
2629 info->stride[i] = gfc_index_one_node;
2630 }
2631 }
2632
2633
2634 static int
get_rank(gfc_loopinfo * loop)2635 get_rank (gfc_loopinfo *loop)
2636 {
2637 int rank;
2638
2639 rank = 0;
2640 for (; loop; loop = loop->parent)
2641 rank += loop->dimen;
2642
2643 return rank;
2644 }
2645
2646
2647 /* Helper routine of gfc_trans_array_constructor to determine if the
2648 bounds of the loop specified by LOOP are constant and simple enough
2649 to use with trans_constant_array_constructor. Returns the
2650 iteration count of the loop if suitable, and NULL_TREE otherwise. */
2651
2652 static tree
constant_array_constructor_loop_size(gfc_loopinfo * l)2653 constant_array_constructor_loop_size (gfc_loopinfo * l)
2654 {
2655 gfc_loopinfo *loop;
2656 tree size = gfc_index_one_node;
2657 tree tmp;
2658 int i, total_dim;
2659
2660 total_dim = get_rank (l);
2661
2662 for (loop = l; loop; loop = loop->parent)
2663 {
2664 for (i = 0; i < loop->dimen; i++)
2665 {
2666 /* If the bounds aren't constant, return NULL_TREE. */
2667 if (!INTEGER_CST_P (loop->from[i]) || !INTEGER_CST_P (loop->to[i]))
2668 return NULL_TREE;
2669 if (!integer_zerop (loop->from[i]))
2670 {
2671 /* Only allow nonzero "from" in one-dimensional arrays. */
2672 if (total_dim != 1)
2673 return NULL_TREE;
2674 tmp = fold_build2_loc (input_location, MINUS_EXPR,
2675 gfc_array_index_type,
2676 loop->to[i], loop->from[i]);
2677 }
2678 else
2679 tmp = loop->to[i];
2680 tmp = fold_build2_loc (input_location, PLUS_EXPR,
2681 gfc_array_index_type, tmp, gfc_index_one_node);
2682 size = fold_build2_loc (input_location, MULT_EXPR,
2683 gfc_array_index_type, size, tmp);
2684 }
2685 }
2686
2687 return size;
2688 }
2689
2690
2691 static tree *
get_loop_upper_bound_for_array(gfc_ss * array,int array_dim)2692 get_loop_upper_bound_for_array (gfc_ss *array, int array_dim)
2693 {
2694 gfc_ss *ss;
2695 int n;
2696
2697 gcc_assert (array->nested_ss == NULL);
2698
2699 for (ss = array; ss; ss = ss->parent)
2700 for (n = 0; n < ss->loop->dimen; n++)
2701 if (array_dim == get_array_ref_dim_for_loop_dim (ss, n))
2702 return &(ss->loop->to[n]);
2703
2704 gcc_unreachable ();
2705 }
2706
2707
2708 static gfc_loopinfo *
outermost_loop(gfc_loopinfo * loop)2709 outermost_loop (gfc_loopinfo * loop)
2710 {
2711 while (loop->parent != NULL)
2712 loop = loop->parent;
2713
2714 return loop;
2715 }
2716
2717
2718 /* Array constructors are handled by constructing a temporary, then using that
2719 within the scalarization loop. This is not optimal, but seems by far the
2720 simplest method. */
2721
2722 static void
trans_array_constructor(gfc_ss * ss,locus * where)2723 trans_array_constructor (gfc_ss * ss, locus * where)
2724 {
2725 gfc_constructor_base c;
2726 tree offset;
2727 tree offsetvar;
2728 tree desc;
2729 tree type;
2730 tree tmp;
2731 tree *loop_ubound0;
2732 bool dynamic;
2733 bool old_first_len, old_typespec_chararray_ctor;
2734 tree old_first_len_val;
2735 gfc_loopinfo *loop, *outer_loop;
2736 gfc_ss_info *ss_info;
2737 gfc_expr *expr;
2738 gfc_ss *s;
2739 tree neg_len;
2740 char *msg;
2741
2742 /* Save the old values for nested checking. */
2743 old_first_len = first_len;
2744 old_first_len_val = first_len_val;
2745 old_typespec_chararray_ctor = typespec_chararray_ctor;
2746
2747 loop = ss->loop;
2748 outer_loop = outermost_loop (loop);
2749 ss_info = ss->info;
2750 expr = ss_info->expr;
2751
2752 /* Do bounds-checking here and in gfc_trans_array_ctor_element only if no
2753 typespec was given for the array constructor. */
2754 typespec_chararray_ctor = (expr->ts.type == BT_CHARACTER
2755 && expr->ts.u.cl
2756 && expr->ts.u.cl->length_from_typespec);
2757
2758 if ((gfc_option.rtcheck & GFC_RTCHECK_BOUNDS)
2759 && expr->ts.type == BT_CHARACTER && !typespec_chararray_ctor)
2760 {
2761 first_len_val = gfc_create_var (gfc_charlen_type_node, "len");
2762 first_len = true;
2763 }
2764
2765 gcc_assert (ss->dimen == ss->loop->dimen);
2766
2767 c = expr->value.constructor;
2768 if (expr->ts.type == BT_CHARACTER)
2769 {
2770 bool const_string;
2771 bool force_new_cl = false;
2772
2773 /* get_array_ctor_strlen walks the elements of the constructor, if a
2774 typespec was given, we already know the string length and want the one
2775 specified there. */
2776 if (typespec_chararray_ctor && expr->ts.u.cl->length
2777 && expr->ts.u.cl->length->expr_type != EXPR_CONSTANT)
2778 {
2779 gfc_se length_se;
2780
2781 const_string = false;
2782 gfc_init_se (&length_se, NULL);
2783 gfc_conv_expr_type (&length_se, expr->ts.u.cl->length,
2784 gfc_charlen_type_node);
2785 ss_info->string_length = length_se.expr;
2786
2787 /* Check if the character length is negative. If it is, then
2788 set LEN = 0. */
2789 neg_len = fold_build2_loc (input_location, LT_EXPR,
2790 logical_type_node, ss_info->string_length,
2791 build_zero_cst (TREE_TYPE
2792 (ss_info->string_length)));
2793 /* Print a warning if bounds checking is enabled. */
2794 if (gfc_option.rtcheck & GFC_RTCHECK_BOUNDS)
2795 {
2796 msg = xasprintf ("Negative character length treated as LEN = 0");
2797 gfc_trans_runtime_check (false, true, neg_len, &length_se.pre,
2798 where, msg);
2799 free (msg);
2800 }
2801
2802 ss_info->string_length
2803 = fold_build3_loc (input_location, COND_EXPR,
2804 gfc_charlen_type_node, neg_len,
2805 build_zero_cst
2806 (TREE_TYPE (ss_info->string_length)),
2807 ss_info->string_length);
2808 ss_info->string_length = gfc_evaluate_now (ss_info->string_length,
2809 &length_se.pre);
2810 gfc_add_block_to_block (&outer_loop->pre, &length_se.pre);
2811 gfc_add_block_to_block (&outer_loop->post, &length_se.post);
2812 }
2813 else
2814 {
2815 const_string = get_array_ctor_strlen (&outer_loop->pre, c,
2816 &ss_info->string_length);
2817 force_new_cl = true;
2818 }
2819
2820 /* Complex character array constructors should have been taken care of
2821 and not end up here. */
2822 gcc_assert (ss_info->string_length);
2823
2824 store_backend_decl (&expr->ts.u.cl, ss_info->string_length, force_new_cl);
2825
2826 type = gfc_get_character_type_len (expr->ts.kind, ss_info->string_length);
2827 if (const_string)
2828 type = build_pointer_type (type);
2829 }
2830 else
2831 type = gfc_typenode_for_spec (expr->ts.type == BT_CLASS
2832 ? &CLASS_DATA (expr)->ts : &expr->ts);
2833
2834 /* See if the constructor determines the loop bounds. */
2835 dynamic = false;
2836
2837 loop_ubound0 = get_loop_upper_bound_for_array (ss, 0);
2838
2839 if (expr->shape && get_rank (loop) > 1 && *loop_ubound0 == NULL_TREE)
2840 {
2841 /* We have a multidimensional parameter. */
2842 for (s = ss; s; s = s->parent)
2843 {
2844 int n;
2845 for (n = 0; n < s->loop->dimen; n++)
2846 {
2847 s->loop->from[n] = gfc_index_zero_node;
2848 s->loop->to[n] = gfc_conv_mpz_to_tree (expr->shape[s->dim[n]],
2849 gfc_index_integer_kind);
2850 s->loop->to[n] = fold_build2_loc (input_location, MINUS_EXPR,
2851 gfc_array_index_type,
2852 s->loop->to[n],
2853 gfc_index_one_node);
2854 }
2855 }
2856 }
2857
2858 if (*loop_ubound0 == NULL_TREE)
2859 {
2860 mpz_t size;
2861
2862 /* We should have a 1-dimensional, zero-based loop. */
2863 gcc_assert (loop->parent == NULL && loop->nested == NULL);
2864 gcc_assert (loop->dimen == 1);
2865 gcc_assert (integer_zerop (loop->from[0]));
2866
2867 /* Split the constructor size into a static part and a dynamic part.
2868 Allocate the static size up-front and record whether the dynamic
2869 size might be nonzero. */
2870 mpz_init (size);
2871 dynamic = gfc_get_array_constructor_size (&size, c);
2872 mpz_sub_ui (size, size, 1);
2873 loop->to[0] = gfc_conv_mpz_to_tree (size, gfc_index_integer_kind);
2874 mpz_clear (size);
2875 }
2876
2877 /* Special case constant array constructors. */
2878 if (!dynamic)
2879 {
2880 unsigned HOST_WIDE_INT nelem = gfc_constant_array_constructor_p (c);
2881 if (nelem > 0)
2882 {
2883 tree size = constant_array_constructor_loop_size (loop);
2884 if (size && compare_tree_int (size, nelem) == 0)
2885 {
2886 trans_constant_array_constructor (ss, type);
2887 goto finish;
2888 }
2889 }
2890 }
2891
2892 gfc_trans_create_temp_array (&outer_loop->pre, &outer_loop->post, ss, type,
2893 NULL_TREE, dynamic, true, false, where);
2894
2895 desc = ss_info->data.array.descriptor;
2896 offset = gfc_index_zero_node;
2897 offsetvar = gfc_create_var_np (gfc_array_index_type, "offset");
2898 suppress_warning (offsetvar);
2899 TREE_USED (offsetvar) = 0;
2900 gfc_trans_array_constructor_value (&outer_loop->pre, type, desc, c,
2901 &offset, &offsetvar, dynamic);
2902
2903 /* If the array grows dynamically, the upper bound of the loop variable
2904 is determined by the array's final upper bound. */
2905 if (dynamic)
2906 {
2907 tmp = fold_build2_loc (input_location, MINUS_EXPR,
2908 gfc_array_index_type,
2909 offsetvar, gfc_index_one_node);
2910 tmp = gfc_evaluate_now (tmp, &outer_loop->pre);
2911 gfc_conv_descriptor_ubound_set (&loop->pre, desc, gfc_rank_cst[0], tmp);
2912 if (*loop_ubound0 && VAR_P (*loop_ubound0))
2913 gfc_add_modify (&outer_loop->pre, *loop_ubound0, tmp);
2914 else
2915 *loop_ubound0 = tmp;
2916 }
2917
2918 if (TREE_USED (offsetvar))
2919 pushdecl (offsetvar);
2920 else
2921 gcc_assert (INTEGER_CST_P (offset));
2922
2923 #if 0
2924 /* Disable bound checking for now because it's probably broken. */
2925 if (gfc_option.rtcheck & GFC_RTCHECK_BOUNDS)
2926 {
2927 gcc_unreachable ();
2928 }
2929 #endif
2930
2931 finish:
2932 /* Restore old values of globals. */
2933 first_len = old_first_len;
2934 first_len_val = old_first_len_val;
2935 typespec_chararray_ctor = old_typespec_chararray_ctor;
2936 }
2937
2938
2939 /* INFO describes a GFC_SS_SECTION in loop LOOP, and this function is
2940 called after evaluating all of INFO's vector dimensions. Go through
2941 each such vector dimension and see if we can now fill in any missing
2942 loop bounds. */
2943
2944 static void
set_vector_loop_bounds(gfc_ss * ss)2945 set_vector_loop_bounds (gfc_ss * ss)
2946 {
2947 gfc_loopinfo *loop, *outer_loop;
2948 gfc_array_info *info;
2949 gfc_se se;
2950 tree tmp;
2951 tree desc;
2952 tree zero;
2953 int n;
2954 int dim;
2955
2956 outer_loop = outermost_loop (ss->loop);
2957
2958 info = &ss->info->data.array;
2959
2960 for (; ss; ss = ss->parent)
2961 {
2962 loop = ss->loop;
2963
2964 for (n = 0; n < loop->dimen; n++)
2965 {
2966 dim = ss->dim[n];
2967 if (info->ref->u.ar.dimen_type[dim] != DIMEN_VECTOR
2968 || loop->to[n] != NULL)
2969 continue;
2970
2971 /* Loop variable N indexes vector dimension DIM, and we don't
2972 yet know the upper bound of loop variable N. Set it to the
2973 difference between the vector's upper and lower bounds. */
2974 gcc_assert (loop->from[n] == gfc_index_zero_node);
2975 gcc_assert (info->subscript[dim]
2976 && info->subscript[dim]->info->type == GFC_SS_VECTOR);
2977
2978 gfc_init_se (&se, NULL);
2979 desc = info->subscript[dim]->info->data.array.descriptor;
2980 zero = gfc_rank_cst[0];
2981 tmp = fold_build2_loc (input_location, MINUS_EXPR,
2982 gfc_array_index_type,
2983 gfc_conv_descriptor_ubound_get (desc, zero),
2984 gfc_conv_descriptor_lbound_get (desc, zero));
2985 tmp = gfc_evaluate_now (tmp, &outer_loop->pre);
2986 loop->to[n] = tmp;
2987 }
2988 }
2989 }
2990
2991
2992 /* Tells whether a scalar argument to an elemental procedure is saved out
2993 of a scalarization loop as a value or as a reference. */
2994
2995 bool
gfc_scalar_elemental_arg_saved_as_reference(gfc_ss_info * ss_info)2996 gfc_scalar_elemental_arg_saved_as_reference (gfc_ss_info * ss_info)
2997 {
2998 if (ss_info->type != GFC_SS_REFERENCE)
2999 return false;
3000
3001 if (ss_info->data.scalar.needs_temporary)
3002 return false;
3003
3004 /* If the actual argument can be absent (in other words, it can
3005 be a NULL reference), don't try to evaluate it; pass instead
3006 the reference directly. */
3007 if (ss_info->can_be_null_ref)
3008 return true;
3009
3010 /* If the expression is of polymorphic type, it's actual size is not known,
3011 so we avoid copying it anywhere. */
3012 if (ss_info->data.scalar.dummy_arg
3013 && gfc_dummy_arg_get_typespec (*ss_info->data.scalar.dummy_arg).type
3014 == BT_CLASS
3015 && ss_info->expr->ts.type == BT_CLASS)
3016 return true;
3017
3018 /* If the expression is a data reference of aggregate type,
3019 and the data reference is not used on the left hand side,
3020 avoid a copy by saving a reference to the content. */
3021 if (!ss_info->data.scalar.needs_temporary
3022 && (ss_info->expr->ts.type == BT_DERIVED
3023 || ss_info->expr->ts.type == BT_CLASS)
3024 && gfc_expr_is_variable (ss_info->expr))
3025 return true;
3026
3027 /* Otherwise the expression is evaluated to a temporary variable before the
3028 scalarization loop. */
3029 return false;
3030 }
3031
3032
3033 /* Add the pre and post chains for all the scalar expressions in a SS chain
3034 to loop. This is called after the loop parameters have been calculated,
3035 but before the actual scalarizing loops. */
3036
3037 static void
gfc_add_loop_ss_code(gfc_loopinfo * loop,gfc_ss * ss,bool subscript,locus * where)3038 gfc_add_loop_ss_code (gfc_loopinfo * loop, gfc_ss * ss, bool subscript,
3039 locus * where)
3040 {
3041 gfc_loopinfo *nested_loop, *outer_loop;
3042 gfc_se se;
3043 gfc_ss_info *ss_info;
3044 gfc_array_info *info;
3045 gfc_expr *expr;
3046 int n;
3047
3048 /* Don't evaluate the arguments for realloc_lhs_loop_for_fcn_call; otherwise,
3049 arguments could get evaluated multiple times. */
3050 if (ss->is_alloc_lhs)
3051 return;
3052
3053 outer_loop = outermost_loop (loop);
3054
3055 /* TODO: This can generate bad code if there are ordering dependencies,
3056 e.g., a callee allocated function and an unknown size constructor. */
3057 gcc_assert (ss != NULL);
3058
3059 for (; ss != gfc_ss_terminator; ss = ss->loop_chain)
3060 {
3061 gcc_assert (ss);
3062
3063 /* Cross loop arrays are handled from within the most nested loop. */
3064 if (ss->nested_ss != NULL)
3065 continue;
3066
3067 ss_info = ss->info;
3068 expr = ss_info->expr;
3069 info = &ss_info->data.array;
3070
3071 switch (ss_info->type)
3072 {
3073 case GFC_SS_SCALAR:
3074 /* Scalar expression. Evaluate this now. This includes elemental
3075 dimension indices, but not array section bounds. */
3076 gfc_init_se (&se, NULL);
3077 gfc_conv_expr (&se, expr);
3078 gfc_add_block_to_block (&outer_loop->pre, &se.pre);
3079
3080 if (expr->ts.type != BT_CHARACTER
3081 && !gfc_is_alloc_class_scalar_function (expr))
3082 {
3083 /* Move the evaluation of scalar expressions outside the
3084 scalarization loop, except for WHERE assignments. */
3085 if (subscript)
3086 se.expr = convert(gfc_array_index_type, se.expr);
3087 if (!ss_info->where)
3088 se.expr = gfc_evaluate_now (se.expr, &outer_loop->pre);
3089 gfc_add_block_to_block (&outer_loop->pre, &se.post);
3090 }
3091 else
3092 gfc_add_block_to_block (&outer_loop->post, &se.post);
3093
3094 ss_info->data.scalar.value = se.expr;
3095 ss_info->string_length = se.string_length;
3096 break;
3097
3098 case GFC_SS_REFERENCE:
3099 /* Scalar argument to elemental procedure. */
3100 gfc_init_se (&se, NULL);
3101 if (gfc_scalar_elemental_arg_saved_as_reference (ss_info))
3102 gfc_conv_expr_reference (&se, expr);
3103 else
3104 {
3105 /* Evaluate the argument outside the loop and pass
3106 a reference to the value. */
3107 gfc_conv_expr (&se, expr);
3108 }
3109
3110 /* Ensure that a pointer to the string is stored. */
3111 if (expr->ts.type == BT_CHARACTER)
3112 gfc_conv_string_parameter (&se);
3113
3114 gfc_add_block_to_block (&outer_loop->pre, &se.pre);
3115 gfc_add_block_to_block (&outer_loop->post, &se.post);
3116 if (gfc_is_class_scalar_expr (expr))
3117 /* This is necessary because the dynamic type will always be
3118 large than the declared type. In consequence, assigning
3119 the value to a temporary could segfault.
3120 OOP-TODO: see if this is generally correct or is the value
3121 has to be written to an allocated temporary, whose address
3122 is passed via ss_info. */
3123 ss_info->data.scalar.value = se.expr;
3124 else
3125 ss_info->data.scalar.value = gfc_evaluate_now (se.expr,
3126 &outer_loop->pre);
3127
3128 ss_info->string_length = se.string_length;
3129 break;
3130
3131 case GFC_SS_SECTION:
3132 /* Add the expressions for scalar and vector subscripts. */
3133 for (n = 0; n < GFC_MAX_DIMENSIONS; n++)
3134 if (info->subscript[n])
3135 gfc_add_loop_ss_code (loop, info->subscript[n], true, where);
3136
3137 set_vector_loop_bounds (ss);
3138 break;
3139
3140 case GFC_SS_VECTOR:
3141 /* Get the vector's descriptor and store it in SS. */
3142 gfc_init_se (&se, NULL);
3143 gfc_conv_expr_descriptor (&se, expr);
3144 gfc_add_block_to_block (&outer_loop->pre, &se.pre);
3145 gfc_add_block_to_block (&outer_loop->post, &se.post);
3146 info->descriptor = se.expr;
3147 break;
3148
3149 case GFC_SS_INTRINSIC:
3150 gfc_add_intrinsic_ss_code (loop, ss);
3151 break;
3152
3153 case GFC_SS_FUNCTION:
3154 /* Array function return value. We call the function and save its
3155 result in a temporary for use inside the loop. */
3156 gfc_init_se (&se, NULL);
3157 se.loop = loop;
3158 se.ss = ss;
3159 if (gfc_is_class_array_function (expr))
3160 expr->must_finalize = 1;
3161 gfc_conv_expr (&se, expr);
3162 gfc_add_block_to_block (&outer_loop->pre, &se.pre);
3163 gfc_add_block_to_block (&outer_loop->post, &se.post);
3164 ss_info->string_length = se.string_length;
3165 break;
3166
3167 case GFC_SS_CONSTRUCTOR:
3168 if (expr->ts.type == BT_CHARACTER
3169 && ss_info->string_length == NULL
3170 && expr->ts.u.cl
3171 && expr->ts.u.cl->length
3172 && expr->ts.u.cl->length->expr_type == EXPR_CONSTANT)
3173 {
3174 gfc_init_se (&se, NULL);
3175 gfc_conv_expr_type (&se, expr->ts.u.cl->length,
3176 gfc_charlen_type_node);
3177 ss_info->string_length = se.expr;
3178 gfc_add_block_to_block (&outer_loop->pre, &se.pre);
3179 gfc_add_block_to_block (&outer_loop->post, &se.post);
3180 }
3181 trans_array_constructor (ss, where);
3182 break;
3183
3184 case GFC_SS_TEMP:
3185 case GFC_SS_COMPONENT:
3186 /* Do nothing. These are handled elsewhere. */
3187 break;
3188
3189 default:
3190 gcc_unreachable ();
3191 }
3192 }
3193
3194 if (!subscript)
3195 for (nested_loop = loop->nested; nested_loop;
3196 nested_loop = nested_loop->next)
3197 gfc_add_loop_ss_code (nested_loop, nested_loop->ss, subscript, where);
3198 }
3199
3200
3201 /* Translate expressions for the descriptor and data pointer of a SS. */
3202 /*GCC ARRAYS*/
3203
3204 static void
gfc_conv_ss_descriptor(stmtblock_t * block,gfc_ss * ss,int base)3205 gfc_conv_ss_descriptor (stmtblock_t * block, gfc_ss * ss, int base)
3206 {
3207 gfc_se se;
3208 gfc_ss_info *ss_info;
3209 gfc_array_info *info;
3210 tree tmp;
3211
3212 ss_info = ss->info;
3213 info = &ss_info->data.array;
3214
3215 /* Get the descriptor for the array to be scalarized. */
3216 gcc_assert (ss_info->expr->expr_type == EXPR_VARIABLE);
3217 gfc_init_se (&se, NULL);
3218 se.descriptor_only = 1;
3219 gfc_conv_expr_lhs (&se, ss_info->expr);
3220 gfc_add_block_to_block (block, &se.pre);
3221 info->descriptor = se.expr;
3222 ss_info->string_length = se.string_length;
3223
3224 if (base)
3225 {
3226 if (ss_info->expr->ts.type == BT_CHARACTER && !ss_info->expr->ts.deferred
3227 && ss_info->expr->ts.u.cl->length == NULL)
3228 {
3229 /* Emit a DECL_EXPR for the variable sized array type in
3230 GFC_TYPE_ARRAY_DATAPTR_TYPE so the gimplification of its type
3231 sizes works correctly. */
3232 tree arraytype = TREE_TYPE (
3233 GFC_TYPE_ARRAY_DATAPTR_TYPE (TREE_TYPE (info->descriptor)));
3234 if (! TYPE_NAME (arraytype))
3235 TYPE_NAME (arraytype) = build_decl (UNKNOWN_LOCATION, TYPE_DECL,
3236 NULL_TREE, arraytype);
3237 gfc_add_expr_to_block (block, build1 (DECL_EXPR, arraytype,
3238 TYPE_NAME (arraytype)));
3239 }
3240 /* Also the data pointer. */
3241 tmp = gfc_conv_array_data (se.expr);
3242 /* If this is a variable or address or a class array, use it directly.
3243 Otherwise we must evaluate it now to avoid breaking dependency
3244 analysis by pulling the expressions for elemental array indices
3245 inside the loop. */
3246 if (!(DECL_P (tmp)
3247 || (TREE_CODE (tmp) == ADDR_EXPR
3248 && DECL_P (TREE_OPERAND (tmp, 0)))
3249 || (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (se.expr))
3250 && TREE_CODE (se.expr) == COMPONENT_REF
3251 && GFC_CLASS_TYPE_P (TREE_TYPE (TREE_OPERAND (se.expr, 0))))))
3252 tmp = gfc_evaluate_now (tmp, block);
3253 info->data = tmp;
3254
3255 tmp = gfc_conv_array_offset (se.expr);
3256 info->offset = gfc_evaluate_now (tmp, block);
3257
3258 /* Make absolutely sure that the saved_offset is indeed saved
3259 so that the variable is still accessible after the loops
3260 are translated. */
3261 info->saved_offset = info->offset;
3262 }
3263 }
3264
3265
3266 /* Initialize a gfc_loopinfo structure. */
3267
3268 void
gfc_init_loopinfo(gfc_loopinfo * loop)3269 gfc_init_loopinfo (gfc_loopinfo * loop)
3270 {
3271 int n;
3272
3273 memset (loop, 0, sizeof (gfc_loopinfo));
3274 gfc_init_block (&loop->pre);
3275 gfc_init_block (&loop->post);
3276
3277 /* Initially scalarize in order and default to no loop reversal. */
3278 for (n = 0; n < GFC_MAX_DIMENSIONS; n++)
3279 {
3280 loop->order[n] = n;
3281 loop->reverse[n] = GFC_INHIBIT_REVERSE;
3282 }
3283
3284 loop->ss = gfc_ss_terminator;
3285 }
3286
3287
3288 /* Copies the loop variable info to a gfc_se structure. Does not copy the SS
3289 chain. */
3290
3291 void
gfc_copy_loopinfo_to_se(gfc_se * se,gfc_loopinfo * loop)3292 gfc_copy_loopinfo_to_se (gfc_se * se, gfc_loopinfo * loop)
3293 {
3294 se->loop = loop;
3295 }
3296
3297
3298 /* Return an expression for the data pointer of an array. */
3299
3300 tree
gfc_conv_array_data(tree descriptor)3301 gfc_conv_array_data (tree descriptor)
3302 {
3303 tree type;
3304
3305 type = TREE_TYPE (descriptor);
3306 if (GFC_ARRAY_TYPE_P (type))
3307 {
3308 if (TREE_CODE (type) == POINTER_TYPE)
3309 return descriptor;
3310 else
3311 {
3312 /* Descriptorless arrays. */
3313 return gfc_build_addr_expr (NULL_TREE, descriptor);
3314 }
3315 }
3316 else
3317 return gfc_conv_descriptor_data_get (descriptor);
3318 }
3319
3320
3321 /* Return an expression for the base offset of an array. */
3322
3323 tree
gfc_conv_array_offset(tree descriptor)3324 gfc_conv_array_offset (tree descriptor)
3325 {
3326 tree type;
3327
3328 type = TREE_TYPE (descriptor);
3329 if (GFC_ARRAY_TYPE_P (type))
3330 return GFC_TYPE_ARRAY_OFFSET (type);
3331 else
3332 return gfc_conv_descriptor_offset_get (descriptor);
3333 }
3334
3335
3336 /* Get an expression for the array stride. */
3337
3338 tree
gfc_conv_array_stride(tree descriptor,int dim)3339 gfc_conv_array_stride (tree descriptor, int dim)
3340 {
3341 tree tmp;
3342 tree type;
3343
3344 type = TREE_TYPE (descriptor);
3345
3346 /* For descriptorless arrays use the array size. */
3347 tmp = GFC_TYPE_ARRAY_STRIDE (type, dim);
3348 if (tmp != NULL_TREE)
3349 return tmp;
3350
3351 tmp = gfc_conv_descriptor_stride_get (descriptor, gfc_rank_cst[dim]);
3352 return tmp;
3353 }
3354
3355
3356 /* Like gfc_conv_array_stride, but for the lower bound. */
3357
3358 tree
gfc_conv_array_lbound(tree descriptor,int dim)3359 gfc_conv_array_lbound (tree descriptor, int dim)
3360 {
3361 tree tmp;
3362 tree type;
3363
3364 type = TREE_TYPE (descriptor);
3365
3366 tmp = GFC_TYPE_ARRAY_LBOUND (type, dim);
3367 if (tmp != NULL_TREE)
3368 return tmp;
3369
3370 tmp = gfc_conv_descriptor_lbound_get (descriptor, gfc_rank_cst[dim]);
3371 return tmp;
3372 }
3373
3374
3375 /* Like gfc_conv_array_stride, but for the upper bound. */
3376
3377 tree
gfc_conv_array_ubound(tree descriptor,int dim)3378 gfc_conv_array_ubound (tree descriptor, int dim)
3379 {
3380 tree tmp;
3381 tree type;
3382
3383 type = TREE_TYPE (descriptor);
3384
3385 tmp = GFC_TYPE_ARRAY_UBOUND (type, dim);
3386 if (tmp != NULL_TREE)
3387 return tmp;
3388
3389 /* This should only ever happen when passing an assumed shape array
3390 as an actual parameter. The value will never be used. */
3391 if (GFC_ARRAY_TYPE_P (TREE_TYPE (descriptor)))
3392 return gfc_index_zero_node;
3393
3394 tmp = gfc_conv_descriptor_ubound_get (descriptor, gfc_rank_cst[dim]);
3395 return tmp;
3396 }
3397
3398
3399 /* Generate code to perform an array index bound check. */
3400
3401 static tree
trans_array_bound_check(gfc_se * se,gfc_ss * ss,tree index,int n,locus * where,bool check_upper)3402 trans_array_bound_check (gfc_se * se, gfc_ss *ss, tree index, int n,
3403 locus * where, bool check_upper)
3404 {
3405 tree fault;
3406 tree tmp_lo, tmp_up;
3407 tree descriptor;
3408 char *msg;
3409 const char * name = NULL;
3410
3411 if (!(gfc_option.rtcheck & GFC_RTCHECK_BOUNDS))
3412 return index;
3413
3414 descriptor = ss->info->data.array.descriptor;
3415
3416 index = gfc_evaluate_now (index, &se->pre);
3417
3418 /* We find a name for the error message. */
3419 name = ss->info->expr->symtree->n.sym->name;
3420 gcc_assert (name != NULL);
3421
3422 if (VAR_P (descriptor))
3423 name = IDENTIFIER_POINTER (DECL_NAME (descriptor));
3424
3425 /* If upper bound is present, include both bounds in the error message. */
3426 if (check_upper)
3427 {
3428 tmp_lo = gfc_conv_array_lbound (descriptor, n);
3429 tmp_up = gfc_conv_array_ubound (descriptor, n);
3430
3431 if (name)
3432 msg = xasprintf ("Index '%%ld' of dimension %d of array '%s' "
3433 "outside of expected range (%%ld:%%ld)", n+1, name);
3434 else
3435 msg = xasprintf ("Index '%%ld' of dimension %d "
3436 "outside of expected range (%%ld:%%ld)", n+1);
3437
3438 fault = fold_build2_loc (input_location, LT_EXPR, logical_type_node,
3439 index, tmp_lo);
3440 gfc_trans_runtime_check (true, false, fault, &se->pre, where, msg,
3441 fold_convert (long_integer_type_node, index),
3442 fold_convert (long_integer_type_node, tmp_lo),
3443 fold_convert (long_integer_type_node, tmp_up));
3444 fault = fold_build2_loc (input_location, GT_EXPR, logical_type_node,
3445 index, tmp_up);
3446 gfc_trans_runtime_check (true, false, fault, &se->pre, where, msg,
3447 fold_convert (long_integer_type_node, index),
3448 fold_convert (long_integer_type_node, tmp_lo),
3449 fold_convert (long_integer_type_node, tmp_up));
3450 free (msg);
3451 }
3452 else
3453 {
3454 tmp_lo = gfc_conv_array_lbound (descriptor, n);
3455
3456 if (name)
3457 msg = xasprintf ("Index '%%ld' of dimension %d of array '%s' "
3458 "below lower bound of %%ld", n+1, name);
3459 else
3460 msg = xasprintf ("Index '%%ld' of dimension %d "
3461 "below lower bound of %%ld", n+1);
3462
3463 fault = fold_build2_loc (input_location, LT_EXPR, logical_type_node,
3464 index, tmp_lo);
3465 gfc_trans_runtime_check (true, false, fault, &se->pre, where, msg,
3466 fold_convert (long_integer_type_node, index),
3467 fold_convert (long_integer_type_node, tmp_lo));
3468 free (msg);
3469 }
3470
3471 return index;
3472 }
3473
3474
3475 /* Return the offset for an index. Performs bound checking for elemental
3476 dimensions. Single element references are processed separately.
3477 DIM is the array dimension, I is the loop dimension. */
3478
3479 static tree
conv_array_index_offset(gfc_se * se,gfc_ss * ss,int dim,int i,gfc_array_ref * ar,tree stride)3480 conv_array_index_offset (gfc_se * se, gfc_ss * ss, int dim, int i,
3481 gfc_array_ref * ar, tree stride)
3482 {
3483 gfc_array_info *info;
3484 tree index;
3485 tree desc;
3486 tree data;
3487
3488 info = &ss->info->data.array;
3489
3490 /* Get the index into the array for this dimension. */
3491 if (ar)
3492 {
3493 gcc_assert (ar->type != AR_ELEMENT);
3494 switch (ar->dimen_type[dim])
3495 {
3496 case DIMEN_THIS_IMAGE:
3497 gcc_unreachable ();
3498 break;
3499 case DIMEN_ELEMENT:
3500 /* Elemental dimension. */
3501 gcc_assert (info->subscript[dim]
3502 && info->subscript[dim]->info->type == GFC_SS_SCALAR);
3503 /* We've already translated this value outside the loop. */
3504 index = info->subscript[dim]->info->data.scalar.value;
3505
3506 index = trans_array_bound_check (se, ss, index, dim, &ar->where,
3507 ar->as->type != AS_ASSUMED_SIZE
3508 || dim < ar->dimen - 1);
3509 break;
3510
3511 case DIMEN_VECTOR:
3512 gcc_assert (info && se->loop);
3513 gcc_assert (info->subscript[dim]
3514 && info->subscript[dim]->info->type == GFC_SS_VECTOR);
3515 desc = info->subscript[dim]->info->data.array.descriptor;
3516
3517 /* Get a zero-based index into the vector. */
3518 index = fold_build2_loc (input_location, MINUS_EXPR,
3519 gfc_array_index_type,
3520 se->loop->loopvar[i], se->loop->from[i]);
3521
3522 /* Multiply the index by the stride. */
3523 index = fold_build2_loc (input_location, MULT_EXPR,
3524 gfc_array_index_type,
3525 index, gfc_conv_array_stride (desc, 0));
3526
3527 /* Read the vector to get an index into info->descriptor. */
3528 data = build_fold_indirect_ref_loc (input_location,
3529 gfc_conv_array_data (desc));
3530 index = gfc_build_array_ref (data, index, NULL);
3531 index = gfc_evaluate_now (index, &se->pre);
3532 index = fold_convert (gfc_array_index_type, index);
3533
3534 /* Do any bounds checking on the final info->descriptor index. */
3535 index = trans_array_bound_check (se, ss, index, dim, &ar->where,
3536 ar->as->type != AS_ASSUMED_SIZE
3537 || dim < ar->dimen - 1);
3538 break;
3539
3540 case DIMEN_RANGE:
3541 /* Scalarized dimension. */
3542 gcc_assert (info && se->loop);
3543
3544 /* Multiply the loop variable by the stride and delta. */
3545 index = se->loop->loopvar[i];
3546 if (!integer_onep (info->stride[dim]))
3547 index = fold_build2_loc (input_location, MULT_EXPR,
3548 gfc_array_index_type, index,
3549 info->stride[dim]);
3550 if (!integer_zerop (info->delta[dim]))
3551 index = fold_build2_loc (input_location, PLUS_EXPR,
3552 gfc_array_index_type, index,
3553 info->delta[dim]);
3554 break;
3555
3556 default:
3557 gcc_unreachable ();
3558 }
3559 }
3560 else
3561 {
3562 /* Temporary array or derived type component. */
3563 gcc_assert (se->loop);
3564 index = se->loop->loopvar[se->loop->order[i]];
3565
3566 /* Pointer functions can have stride[0] different from unity.
3567 Use the stride returned by the function call and stored in
3568 the descriptor for the temporary. */
3569 if (se->ss && se->ss->info->type == GFC_SS_FUNCTION
3570 && se->ss->info->expr
3571 && se->ss->info->expr->symtree
3572 && se->ss->info->expr->symtree->n.sym->result
3573 && se->ss->info->expr->symtree->n.sym->result->attr.pointer)
3574 stride = gfc_conv_descriptor_stride_get (info->descriptor,
3575 gfc_rank_cst[dim]);
3576
3577 if (info->delta[dim] && !integer_zerop (info->delta[dim]))
3578 index = fold_build2_loc (input_location, PLUS_EXPR,
3579 gfc_array_index_type, index, info->delta[dim]);
3580 }
3581
3582 /* Multiply by the stride. */
3583 if (stride != NULL && !integer_onep (stride))
3584 index = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
3585 index, stride);
3586
3587 return index;
3588 }
3589
3590
3591 /* Build a scalarized array reference using the vptr 'size'. */
3592
3593 static bool
build_class_array_ref(gfc_se * se,tree base,tree index)3594 build_class_array_ref (gfc_se *se, tree base, tree index)
3595 {
3596 tree size;
3597 tree decl = NULL_TREE;
3598 tree tmp;
3599 gfc_expr *expr = se->ss->info->expr;
3600 gfc_expr *class_expr;
3601 gfc_typespec *ts;
3602 gfc_symbol *sym;
3603
3604 tmp = !VAR_P (base) ? gfc_get_class_from_expr (base) : NULL_TREE;
3605
3606 if (tmp != NULL_TREE)
3607 decl = tmp;
3608 else
3609 {
3610 /* The base expression does not contain a class component, either
3611 because it is a temporary array or array descriptor. Class
3612 array functions are correctly resolved above. */
3613 if (!expr
3614 || (expr->ts.type != BT_CLASS
3615 && !gfc_is_class_array_ref (expr, NULL)))
3616 return false;
3617
3618 /* Obtain the expression for the class entity or component that is
3619 followed by an array reference, which is not an element, so that
3620 the span of the array can be obtained. */
3621 class_expr = gfc_find_and_cut_at_last_class_ref (expr, false, &ts);
3622
3623 if (!ts)
3624 return false;
3625
3626 sym = (!class_expr && expr) ? expr->symtree->n.sym : NULL;
3627 if (sym && sym->attr.function
3628 && sym == sym->result
3629 && sym->backend_decl == current_function_decl)
3630 /* The temporary is the data field of the class data component
3631 of the current function. */
3632 decl = gfc_get_fake_result_decl (sym, 0);
3633 else if (sym)
3634 {
3635 if (decl == NULL_TREE)
3636 decl = expr->symtree->n.sym->backend_decl;
3637 /* For class arrays the tree containing the class is stored in
3638 GFC_DECL_SAVED_DESCRIPTOR of the sym's backend_decl.
3639 For all others it's sym's backend_decl directly. */
3640 if (DECL_LANG_SPECIFIC (decl) && GFC_DECL_SAVED_DESCRIPTOR (decl))
3641 decl = GFC_DECL_SAVED_DESCRIPTOR (decl);
3642 }
3643 else
3644 decl = gfc_get_class_from_gfc_expr (class_expr);
3645
3646 if (POINTER_TYPE_P (TREE_TYPE (decl)))
3647 decl = build_fold_indirect_ref_loc (input_location, decl);
3648
3649 if (!GFC_CLASS_TYPE_P (TREE_TYPE (decl)))
3650 return false;
3651 }
3652
3653 se->class_vptr = gfc_evaluate_now (gfc_class_vptr_get (decl), &se->pre);
3654
3655 size = gfc_class_vtab_size_get (decl);
3656 /* For unlimited polymorphic entities then _len component needs to be
3657 multiplied with the size. */
3658 size = gfc_resize_class_size_with_len (&se->pre, decl, size);
3659 size = fold_convert (TREE_TYPE (index), size);
3660
3661 /* Return the element in the se expression. */
3662 se->expr = gfc_build_spanned_array_ref (base, index, size);
3663 return true;
3664 }
3665
3666
3667 /* Indicates that the tree EXPR is a reference to an array that can’t
3668 have any negative stride. */
3669
3670 static bool
non_negative_strides_array_p(tree expr)3671 non_negative_strides_array_p (tree expr)
3672 {
3673 if (expr == NULL_TREE)
3674 return false;
3675
3676 tree type = TREE_TYPE (expr);
3677 if (POINTER_TYPE_P (type))
3678 type = TREE_TYPE (type);
3679
3680 if (TYPE_LANG_SPECIFIC (type))
3681 {
3682 gfc_array_kind array_kind = GFC_TYPE_ARRAY_AKIND (type);
3683
3684 if (array_kind == GFC_ARRAY_ALLOCATABLE
3685 || array_kind == GFC_ARRAY_ASSUMED_SHAPE_CONT)
3686 return true;
3687 }
3688
3689 /* An array with descriptor can have negative strides.
3690 We try to be conservative and return false by default here
3691 if we don’t recognize a contiguous array instead of
3692 returning false if we can identify a non-contiguous one. */
3693 if (!GFC_ARRAY_TYPE_P (type))
3694 return false;
3695
3696 /* If the array was originally a dummy with a descriptor, strides can be
3697 negative. */
3698 if (DECL_P (expr)
3699 && DECL_LANG_SPECIFIC (expr)
3700 && GFC_DECL_SAVED_DESCRIPTOR (expr)
3701 && GFC_DECL_SAVED_DESCRIPTOR (expr) != expr)
3702 return non_negative_strides_array_p (GFC_DECL_SAVED_DESCRIPTOR (expr));
3703
3704 return true;
3705 }
3706
3707
3708 /* Build a scalarized reference to an array. */
3709
3710 static void
gfc_conv_scalarized_array_ref(gfc_se * se,gfc_array_ref * ar,bool tmp_array=false)3711 gfc_conv_scalarized_array_ref (gfc_se * se, gfc_array_ref * ar,
3712 bool tmp_array = false)
3713 {
3714 gfc_array_info *info;
3715 tree decl = NULL_TREE;
3716 tree index;
3717 tree base;
3718 gfc_ss *ss;
3719 gfc_expr *expr;
3720 int n;
3721
3722 ss = se->ss;
3723 expr = ss->info->expr;
3724 info = &ss->info->data.array;
3725 if (ar)
3726 n = se->loop->order[0];
3727 else
3728 n = 0;
3729
3730 index = conv_array_index_offset (se, ss, ss->dim[n], n, ar, info->stride0);
3731 /* Add the offset for this dimension to the stored offset for all other
3732 dimensions. */
3733 if (info->offset && !integer_zerop (info->offset))
3734 index = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
3735 index, info->offset);
3736
3737 base = build_fold_indirect_ref_loc (input_location, info->data);
3738
3739 /* Use the vptr 'size' field to access the element of a class array. */
3740 if (build_class_array_ref (se, base, index))
3741 return;
3742
3743 if (get_CFI_desc (NULL, expr, &decl, ar))
3744 decl = build_fold_indirect_ref_loc (input_location, decl);
3745
3746 /* A pointer array component can be detected from its field decl. Fix
3747 the descriptor, mark the resulting variable decl and pass it to
3748 gfc_build_array_ref. */
3749 if (is_pointer_array (info->descriptor)
3750 || (expr && expr->ts.deferred && info->descriptor
3751 && GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (info->descriptor))))
3752 {
3753 if (TREE_CODE (info->descriptor) == COMPONENT_REF)
3754 decl = info->descriptor;
3755 else if (TREE_CODE (info->descriptor) == INDIRECT_REF)
3756 decl = TREE_OPERAND (info->descriptor, 0);
3757
3758 if (decl == NULL_TREE)
3759 decl = info->descriptor;
3760 }
3761
3762 bool non_negative_stride = tmp_array
3763 || non_negative_strides_array_p (info->descriptor);
3764 se->expr = gfc_build_array_ref (base, index, decl,
3765 non_negative_stride);
3766 }
3767
3768
3769 /* Translate access of temporary array. */
3770
3771 void
gfc_conv_tmp_array_ref(gfc_se * se)3772 gfc_conv_tmp_array_ref (gfc_se * se)
3773 {
3774 se->string_length = se->ss->info->string_length;
3775 gfc_conv_scalarized_array_ref (se, NULL, true);
3776 gfc_advance_se_ss_chain (se);
3777 }
3778
3779 /* Add T to the offset pair *OFFSET, *CST_OFFSET. */
3780
3781 static void
add_to_offset(tree * cst_offset,tree * offset,tree t)3782 add_to_offset (tree *cst_offset, tree *offset, tree t)
3783 {
3784 if (TREE_CODE (t) == INTEGER_CST)
3785 *cst_offset = int_const_binop (PLUS_EXPR, *cst_offset, t);
3786 else
3787 {
3788 if (!integer_zerop (*offset))
3789 *offset = fold_build2_loc (input_location, PLUS_EXPR,
3790 gfc_array_index_type, *offset, t);
3791 else
3792 *offset = t;
3793 }
3794 }
3795
3796
3797 static tree
build_array_ref(tree desc,tree offset,tree decl,tree vptr)3798 build_array_ref (tree desc, tree offset, tree decl, tree vptr)
3799 {
3800 tree tmp;
3801 tree type;
3802 tree cdesc;
3803
3804 /* For class arrays the class declaration is stored in the saved
3805 descriptor. */
3806 if (INDIRECT_REF_P (desc)
3807 && DECL_LANG_SPECIFIC (TREE_OPERAND (desc, 0))
3808 && GFC_DECL_SAVED_DESCRIPTOR (TREE_OPERAND (desc, 0)))
3809 cdesc = gfc_class_data_get (GFC_DECL_SAVED_DESCRIPTOR (
3810 TREE_OPERAND (desc, 0)));
3811 else
3812 cdesc = desc;
3813
3814 /* Class container types do not always have the GFC_CLASS_TYPE_P
3815 but the canonical type does. */
3816 if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (cdesc))
3817 && TREE_CODE (cdesc) == COMPONENT_REF)
3818 {
3819 type = TREE_TYPE (TREE_OPERAND (cdesc, 0));
3820 if (TYPE_CANONICAL (type)
3821 && GFC_CLASS_TYPE_P (TYPE_CANONICAL (type)))
3822 vptr = gfc_class_vptr_get (TREE_OPERAND (cdesc, 0));
3823 }
3824
3825 tmp = gfc_conv_array_data (desc);
3826 tmp = build_fold_indirect_ref_loc (input_location, tmp);
3827 tmp = gfc_build_array_ref (tmp, offset, decl,
3828 non_negative_strides_array_p (desc),
3829 vptr);
3830 return tmp;
3831 }
3832
3833
3834 /* Build an array reference. se->expr already holds the array descriptor.
3835 This should be either a variable, indirect variable reference or component
3836 reference. For arrays which do not have a descriptor, se->expr will be
3837 the data pointer.
3838 a(i, j, k) = base[offset + i * stride[0] + j * stride[1] + k * stride[2]]*/
3839
3840 void
gfc_conv_array_ref(gfc_se * se,gfc_array_ref * ar,gfc_expr * expr,locus * where)3841 gfc_conv_array_ref (gfc_se * se, gfc_array_ref * ar, gfc_expr *expr,
3842 locus * where)
3843 {
3844 int n;
3845 tree offset, cst_offset;
3846 tree tmp;
3847 tree stride;
3848 tree decl = NULL_TREE;
3849 gfc_se indexse;
3850 gfc_se tmpse;
3851 gfc_symbol * sym = expr->symtree->n.sym;
3852 char *var_name = NULL;
3853
3854 if (ar->dimen == 0)
3855 {
3856 gcc_assert (ar->codimen || sym->attr.select_rank_temporary
3857 || (ar->as && ar->as->corank));
3858
3859 if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (se->expr)))
3860 se->expr = build_fold_indirect_ref (gfc_conv_array_data (se->expr));
3861 else
3862 {
3863 if (GFC_ARRAY_TYPE_P (TREE_TYPE (se->expr))
3864 && TREE_CODE (TREE_TYPE (se->expr)) == POINTER_TYPE)
3865 se->expr = build_fold_indirect_ref_loc (input_location, se->expr);
3866
3867 /* Use the actual tree type and not the wrapped coarray. */
3868 if (!se->want_pointer)
3869 se->expr = fold_convert (TYPE_MAIN_VARIANT (TREE_TYPE (se->expr)),
3870 se->expr);
3871 }
3872
3873 return;
3874 }
3875
3876 /* Handle scalarized references separately. */
3877 if (ar->type != AR_ELEMENT)
3878 {
3879 gfc_conv_scalarized_array_ref (se, ar);
3880 gfc_advance_se_ss_chain (se);
3881 return;
3882 }
3883
3884 if (gfc_option.rtcheck & GFC_RTCHECK_BOUNDS)
3885 {
3886 size_t len;
3887 gfc_ref *ref;
3888
3889 len = strlen (sym->name) + 1;
3890 for (ref = expr->ref; ref; ref = ref->next)
3891 {
3892 if (ref->type == REF_ARRAY && &ref->u.ar == ar)
3893 break;
3894 if (ref->type == REF_COMPONENT)
3895 len += 2 + strlen (ref->u.c.component->name);
3896 }
3897
3898 var_name = XALLOCAVEC (char, len);
3899 strcpy (var_name, sym->name);
3900
3901 for (ref = expr->ref; ref; ref = ref->next)
3902 {
3903 if (ref->type == REF_ARRAY && &ref->u.ar == ar)
3904 break;
3905 if (ref->type == REF_COMPONENT)
3906 {
3907 strcat (var_name, "%%");
3908 strcat (var_name, ref->u.c.component->name);
3909 }
3910 }
3911 }
3912
3913 decl = se->expr;
3914 if (UNLIMITED_POLY(sym)
3915 && IS_CLASS_ARRAY (sym)
3916 && sym->attr.dummy
3917 && ar->as->type != AS_DEFERRED)
3918 decl = sym->backend_decl;
3919
3920 cst_offset = offset = gfc_index_zero_node;
3921 add_to_offset (&cst_offset, &offset, gfc_conv_array_offset (decl));
3922
3923 /* Calculate the offsets from all the dimensions. Make sure to associate
3924 the final offset so that we form a chain of loop invariant summands. */
3925 for (n = ar->dimen - 1; n >= 0; n--)
3926 {
3927 /* Calculate the index for this dimension. */
3928 gfc_init_se (&indexse, se);
3929 gfc_conv_expr_type (&indexse, ar->start[n], gfc_array_index_type);
3930 gfc_add_block_to_block (&se->pre, &indexse.pre);
3931
3932 if ((gfc_option.rtcheck & GFC_RTCHECK_BOUNDS) && ! expr->no_bounds_check)
3933 {
3934 /* Check array bounds. */
3935 tree cond;
3936 char *msg;
3937
3938 /* Evaluate the indexse.expr only once. */
3939 indexse.expr = save_expr (indexse.expr);
3940
3941 /* Lower bound. */
3942 tmp = gfc_conv_array_lbound (decl, n);
3943 if (sym->attr.temporary)
3944 {
3945 gfc_init_se (&tmpse, se);
3946 gfc_conv_expr_type (&tmpse, ar->as->lower[n],
3947 gfc_array_index_type);
3948 gfc_add_block_to_block (&se->pre, &tmpse.pre);
3949 tmp = tmpse.expr;
3950 }
3951
3952 cond = fold_build2_loc (input_location, LT_EXPR, logical_type_node,
3953 indexse.expr, tmp);
3954 msg = xasprintf ("Index '%%ld' of dimension %d of array '%s' "
3955 "below lower bound of %%ld", n+1, var_name);
3956 gfc_trans_runtime_check (true, false, cond, &se->pre, where, msg,
3957 fold_convert (long_integer_type_node,
3958 indexse.expr),
3959 fold_convert (long_integer_type_node, tmp));
3960 free (msg);
3961
3962 /* Upper bound, but not for the last dimension of assumed-size
3963 arrays. */
3964 if (n < ar->dimen - 1 || ar->as->type != AS_ASSUMED_SIZE)
3965 {
3966 tmp = gfc_conv_array_ubound (decl, n);
3967 if (sym->attr.temporary)
3968 {
3969 gfc_init_se (&tmpse, se);
3970 gfc_conv_expr_type (&tmpse, ar->as->upper[n],
3971 gfc_array_index_type);
3972 gfc_add_block_to_block (&se->pre, &tmpse.pre);
3973 tmp = tmpse.expr;
3974 }
3975
3976 cond = fold_build2_loc (input_location, GT_EXPR,
3977 logical_type_node, indexse.expr, tmp);
3978 msg = xasprintf ("Index '%%ld' of dimension %d of array '%s' "
3979 "above upper bound of %%ld", n+1, var_name);
3980 gfc_trans_runtime_check (true, false, cond, &se->pre, where, msg,
3981 fold_convert (long_integer_type_node,
3982 indexse.expr),
3983 fold_convert (long_integer_type_node, tmp));
3984 free (msg);
3985 }
3986 }
3987
3988 /* Multiply the index by the stride. */
3989 stride = gfc_conv_array_stride (decl, n);
3990 tmp = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
3991 indexse.expr, stride);
3992
3993 /* And add it to the total. */
3994 add_to_offset (&cst_offset, &offset, tmp);
3995 }
3996
3997 if (!integer_zerop (cst_offset))
3998 offset = fold_build2_loc (input_location, PLUS_EXPR,
3999 gfc_array_index_type, offset, cst_offset);
4000
4001 /* A pointer array component can be detected from its field decl. Fix
4002 the descriptor, mark the resulting variable decl and pass it to
4003 build_array_ref. */
4004 decl = NULL_TREE;
4005 if (get_CFI_desc (sym, expr, &decl, ar))
4006 decl = build_fold_indirect_ref_loc (input_location, decl);
4007 if (!expr->ts.deferred && !sym->attr.codimension
4008 && is_pointer_array (se->expr))
4009 {
4010 if (TREE_CODE (se->expr) == COMPONENT_REF)
4011 decl = se->expr;
4012 else if (TREE_CODE (se->expr) == INDIRECT_REF)
4013 decl = TREE_OPERAND (se->expr, 0);
4014 else
4015 decl = se->expr;
4016 }
4017 else if (expr->ts.deferred
4018 || (sym->ts.type == BT_CHARACTER
4019 && sym->attr.select_type_temporary))
4020 {
4021 if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (se->expr)))
4022 {
4023 decl = se->expr;
4024 if (TREE_CODE (decl) == INDIRECT_REF)
4025 decl = TREE_OPERAND (decl, 0);
4026 }
4027 else
4028 decl = sym->backend_decl;
4029 }
4030 else if (sym->ts.type == BT_CLASS)
4031 {
4032 if (UNLIMITED_POLY (sym))
4033 {
4034 gfc_expr *class_expr = gfc_find_and_cut_at_last_class_ref (expr);
4035 gfc_init_se (&tmpse, NULL);
4036 gfc_conv_expr (&tmpse, class_expr);
4037 if (!se->class_vptr)
4038 se->class_vptr = gfc_class_vptr_get (tmpse.expr);
4039 gfc_free_expr (class_expr);
4040 decl = tmpse.expr;
4041 }
4042 else
4043 decl = NULL_TREE;
4044 }
4045
4046 se->expr = build_array_ref (se->expr, offset, decl, se->class_vptr);
4047 }
4048
4049
4050 /* Add the offset corresponding to array's ARRAY_DIM dimension and loop's
4051 LOOP_DIM dimension (if any) to array's offset. */
4052
4053 static void
add_array_offset(stmtblock_t * pblock,gfc_loopinfo * loop,gfc_ss * ss,gfc_array_ref * ar,int array_dim,int loop_dim)4054 add_array_offset (stmtblock_t *pblock, gfc_loopinfo *loop, gfc_ss *ss,
4055 gfc_array_ref *ar, int array_dim, int loop_dim)
4056 {
4057 gfc_se se;
4058 gfc_array_info *info;
4059 tree stride, index;
4060
4061 info = &ss->info->data.array;
4062
4063 gfc_init_se (&se, NULL);
4064 se.loop = loop;
4065 se.expr = info->descriptor;
4066 stride = gfc_conv_array_stride (info->descriptor, array_dim);
4067 index = conv_array_index_offset (&se, ss, array_dim, loop_dim, ar, stride);
4068 gfc_add_block_to_block (pblock, &se.pre);
4069
4070 info->offset = fold_build2_loc (input_location, PLUS_EXPR,
4071 gfc_array_index_type,
4072 info->offset, index);
4073 info->offset = gfc_evaluate_now (info->offset, pblock);
4074 }
4075
4076
4077 /* Generate the code to be executed immediately before entering a
4078 scalarization loop. */
4079
4080 static void
gfc_trans_preloop_setup(gfc_loopinfo * loop,int dim,int flag,stmtblock_t * pblock)4081 gfc_trans_preloop_setup (gfc_loopinfo * loop, int dim, int flag,
4082 stmtblock_t * pblock)
4083 {
4084 tree stride;
4085 gfc_ss_info *ss_info;
4086 gfc_array_info *info;
4087 gfc_ss_type ss_type;
4088 gfc_ss *ss, *pss;
4089 gfc_loopinfo *ploop;
4090 gfc_array_ref *ar;
4091 int i;
4092
4093 /* This code will be executed before entering the scalarization loop
4094 for this dimension. */
4095 for (ss = loop->ss; ss != gfc_ss_terminator; ss = ss->loop_chain)
4096 {
4097 ss_info = ss->info;
4098
4099 if ((ss_info->useflags & flag) == 0)
4100 continue;
4101
4102 ss_type = ss_info->type;
4103 if (ss_type != GFC_SS_SECTION
4104 && ss_type != GFC_SS_FUNCTION
4105 && ss_type != GFC_SS_CONSTRUCTOR
4106 && ss_type != GFC_SS_COMPONENT)
4107 continue;
4108
4109 info = &ss_info->data.array;
4110
4111 gcc_assert (dim < ss->dimen);
4112 gcc_assert (ss->dimen == loop->dimen);
4113
4114 if (info->ref)
4115 ar = &info->ref->u.ar;
4116 else
4117 ar = NULL;
4118
4119 if (dim == loop->dimen - 1 && loop->parent != NULL)
4120 {
4121 /* If we are in the outermost dimension of this loop, the previous
4122 dimension shall be in the parent loop. */
4123 gcc_assert (ss->parent != NULL);
4124
4125 pss = ss->parent;
4126 ploop = loop->parent;
4127
4128 /* ss and ss->parent are about the same array. */
4129 gcc_assert (ss_info == pss->info);
4130 }
4131 else
4132 {
4133 ploop = loop;
4134 pss = ss;
4135 }
4136
4137 if (dim == loop->dimen - 1)
4138 i = 0;
4139 else
4140 i = dim + 1;
4141
4142 /* For the time being, there is no loop reordering. */
4143 gcc_assert (i == ploop->order[i]);
4144 i = ploop->order[i];
4145
4146 if (dim == loop->dimen - 1 && loop->parent == NULL)
4147 {
4148 stride = gfc_conv_array_stride (info->descriptor,
4149 innermost_ss (ss)->dim[i]);
4150
4151 /* Calculate the stride of the innermost loop. Hopefully this will
4152 allow the backend optimizers to do their stuff more effectively.
4153 */
4154 info->stride0 = gfc_evaluate_now (stride, pblock);
4155
4156 /* For the outermost loop calculate the offset due to any
4157 elemental dimensions. It will have been initialized with the
4158 base offset of the array. */
4159 if (info->ref)
4160 {
4161 for (i = 0; i < ar->dimen; i++)
4162 {
4163 if (ar->dimen_type[i] != DIMEN_ELEMENT)
4164 continue;
4165
4166 add_array_offset (pblock, loop, ss, ar, i, /* unused */ -1);
4167 }
4168 }
4169 }
4170 else
4171 /* Add the offset for the previous loop dimension. */
4172 add_array_offset (pblock, ploop, ss, ar, pss->dim[i], i);
4173
4174 /* Remember this offset for the second loop. */
4175 if (dim == loop->temp_dim - 1 && loop->parent == NULL)
4176 info->saved_offset = info->offset;
4177 }
4178 }
4179
4180
4181 /* Start a scalarized expression. Creates a scope and declares loop
4182 variables. */
4183
4184 void
gfc_start_scalarized_body(gfc_loopinfo * loop,stmtblock_t * pbody)4185 gfc_start_scalarized_body (gfc_loopinfo * loop, stmtblock_t * pbody)
4186 {
4187 int dim;
4188 int n;
4189 int flags;
4190
4191 gcc_assert (!loop->array_parameter);
4192
4193 for (dim = loop->dimen - 1; dim >= 0; dim--)
4194 {
4195 n = loop->order[dim];
4196
4197 gfc_start_block (&loop->code[n]);
4198
4199 /* Create the loop variable. */
4200 loop->loopvar[n] = gfc_create_var (gfc_array_index_type, "S");
4201
4202 if (dim < loop->temp_dim)
4203 flags = 3;
4204 else
4205 flags = 1;
4206 /* Calculate values that will be constant within this loop. */
4207 gfc_trans_preloop_setup (loop, dim, flags, &loop->code[n]);
4208 }
4209 gfc_start_block (pbody);
4210 }
4211
4212
4213 /* Generates the actual loop code for a scalarization loop. */
4214
4215 static void
gfc_trans_scalarized_loop_end(gfc_loopinfo * loop,int n,stmtblock_t * pbody)4216 gfc_trans_scalarized_loop_end (gfc_loopinfo * loop, int n,
4217 stmtblock_t * pbody)
4218 {
4219 stmtblock_t block;
4220 tree cond;
4221 tree tmp;
4222 tree loopbody;
4223 tree exit_label;
4224 tree stmt;
4225 tree init;
4226 tree incr;
4227
4228 if ((ompws_flags & (OMPWS_WORKSHARE_FLAG | OMPWS_SCALARIZER_WS
4229 | OMPWS_SCALARIZER_BODY))
4230 == (OMPWS_WORKSHARE_FLAG | OMPWS_SCALARIZER_WS)
4231 && n == loop->dimen - 1)
4232 {
4233 /* We create an OMP_FOR construct for the outermost scalarized loop. */
4234 init = make_tree_vec (1);
4235 cond = make_tree_vec (1);
4236 incr = make_tree_vec (1);
4237
4238 /* Cycle statement is implemented with a goto. Exit statement must not
4239 be present for this loop. */
4240 exit_label = gfc_build_label_decl (NULL_TREE);
4241 TREE_USED (exit_label) = 1;
4242
4243 /* Label for cycle statements (if needed). */
4244 tmp = build1_v (LABEL_EXPR, exit_label);
4245 gfc_add_expr_to_block (pbody, tmp);
4246
4247 stmt = make_node (OMP_FOR);
4248
4249 TREE_TYPE (stmt) = void_type_node;
4250 OMP_FOR_BODY (stmt) = loopbody = gfc_finish_block (pbody);
4251
4252 OMP_FOR_CLAUSES (stmt) = build_omp_clause (input_location,
4253 OMP_CLAUSE_SCHEDULE);
4254 OMP_CLAUSE_SCHEDULE_KIND (OMP_FOR_CLAUSES (stmt))
4255 = OMP_CLAUSE_SCHEDULE_STATIC;
4256 if (ompws_flags & OMPWS_NOWAIT)
4257 OMP_CLAUSE_CHAIN (OMP_FOR_CLAUSES (stmt))
4258 = build_omp_clause (input_location, OMP_CLAUSE_NOWAIT);
4259
4260 /* Initialize the loopvar. */
4261 TREE_VEC_ELT (init, 0) = build2_v (MODIFY_EXPR, loop->loopvar[n],
4262 loop->from[n]);
4263 OMP_FOR_INIT (stmt) = init;
4264 /* The exit condition. */
4265 TREE_VEC_ELT (cond, 0) = build2_loc (input_location, LE_EXPR,
4266 logical_type_node,
4267 loop->loopvar[n], loop->to[n]);
4268 SET_EXPR_LOCATION (TREE_VEC_ELT (cond, 0), input_location);
4269 OMP_FOR_COND (stmt) = cond;
4270 /* Increment the loopvar. */
4271 tmp = build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
4272 loop->loopvar[n], gfc_index_one_node);
4273 TREE_VEC_ELT (incr, 0) = fold_build2_loc (input_location, MODIFY_EXPR,
4274 void_type_node, loop->loopvar[n], tmp);
4275 OMP_FOR_INCR (stmt) = incr;
4276
4277 ompws_flags &= ~OMPWS_CURR_SINGLEUNIT;
4278 gfc_add_expr_to_block (&loop->code[n], stmt);
4279 }
4280 else
4281 {
4282 bool reverse_loop = (loop->reverse[n] == GFC_REVERSE_SET)
4283 && (loop->temp_ss == NULL);
4284
4285 loopbody = gfc_finish_block (pbody);
4286
4287 if (reverse_loop)
4288 std::swap (loop->from[n], loop->to[n]);
4289
4290 /* Initialize the loopvar. */
4291 if (loop->loopvar[n] != loop->from[n])
4292 gfc_add_modify (&loop->code[n], loop->loopvar[n], loop->from[n]);
4293
4294 exit_label = gfc_build_label_decl (NULL_TREE);
4295
4296 /* Generate the loop body. */
4297 gfc_init_block (&block);
4298
4299 /* The exit condition. */
4300 cond = fold_build2_loc (input_location, reverse_loop ? LT_EXPR : GT_EXPR,
4301 logical_type_node, loop->loopvar[n], loop->to[n]);
4302 tmp = build1_v (GOTO_EXPR, exit_label);
4303 TREE_USED (exit_label) = 1;
4304 tmp = build3_v (COND_EXPR, cond, tmp, build_empty_stmt (input_location));
4305 gfc_add_expr_to_block (&block, tmp);
4306
4307 /* The main body. */
4308 gfc_add_expr_to_block (&block, loopbody);
4309
4310 /* Increment the loopvar. */
4311 tmp = fold_build2_loc (input_location,
4312 reverse_loop ? MINUS_EXPR : PLUS_EXPR,
4313 gfc_array_index_type, loop->loopvar[n],
4314 gfc_index_one_node);
4315
4316 gfc_add_modify (&block, loop->loopvar[n], tmp);
4317
4318 /* Build the loop. */
4319 tmp = gfc_finish_block (&block);
4320 tmp = build1_v (LOOP_EXPR, tmp);
4321 gfc_add_expr_to_block (&loop->code[n], tmp);
4322
4323 /* Add the exit label. */
4324 tmp = build1_v (LABEL_EXPR, exit_label);
4325 gfc_add_expr_to_block (&loop->code[n], tmp);
4326 }
4327
4328 }
4329
4330
4331 /* Finishes and generates the loops for a scalarized expression. */
4332
4333 void
gfc_trans_scalarizing_loops(gfc_loopinfo * loop,stmtblock_t * body)4334 gfc_trans_scalarizing_loops (gfc_loopinfo * loop, stmtblock_t * body)
4335 {
4336 int dim;
4337 int n;
4338 gfc_ss *ss;
4339 stmtblock_t *pblock;
4340 tree tmp;
4341
4342 pblock = body;
4343 /* Generate the loops. */
4344 for (dim = 0; dim < loop->dimen; dim++)
4345 {
4346 n = loop->order[dim];
4347 gfc_trans_scalarized_loop_end (loop, n, pblock);
4348 loop->loopvar[n] = NULL_TREE;
4349 pblock = &loop->code[n];
4350 }
4351
4352 tmp = gfc_finish_block (pblock);
4353 gfc_add_expr_to_block (&loop->pre, tmp);
4354
4355 /* Clear all the used flags. */
4356 for (ss = loop->ss; ss != gfc_ss_terminator; ss = ss->loop_chain)
4357 if (ss->parent == NULL)
4358 ss->info->useflags = 0;
4359 }
4360
4361
4362 /* Finish the main body of a scalarized expression, and start the secondary
4363 copying body. */
4364
4365 void
gfc_trans_scalarized_loop_boundary(gfc_loopinfo * loop,stmtblock_t * body)4366 gfc_trans_scalarized_loop_boundary (gfc_loopinfo * loop, stmtblock_t * body)
4367 {
4368 int dim;
4369 int n;
4370 stmtblock_t *pblock;
4371 gfc_ss *ss;
4372
4373 pblock = body;
4374 /* We finish as many loops as are used by the temporary. */
4375 for (dim = 0; dim < loop->temp_dim - 1; dim++)
4376 {
4377 n = loop->order[dim];
4378 gfc_trans_scalarized_loop_end (loop, n, pblock);
4379 loop->loopvar[n] = NULL_TREE;
4380 pblock = &loop->code[n];
4381 }
4382
4383 /* We don't want to finish the outermost loop entirely. */
4384 n = loop->order[loop->temp_dim - 1];
4385 gfc_trans_scalarized_loop_end (loop, n, pblock);
4386
4387 /* Restore the initial offsets. */
4388 for (ss = loop->ss; ss != gfc_ss_terminator; ss = ss->loop_chain)
4389 {
4390 gfc_ss_type ss_type;
4391 gfc_ss_info *ss_info;
4392
4393 ss_info = ss->info;
4394
4395 if ((ss_info->useflags & 2) == 0)
4396 continue;
4397
4398 ss_type = ss_info->type;
4399 if (ss_type != GFC_SS_SECTION
4400 && ss_type != GFC_SS_FUNCTION
4401 && ss_type != GFC_SS_CONSTRUCTOR
4402 && ss_type != GFC_SS_COMPONENT)
4403 continue;
4404
4405 ss_info->data.array.offset = ss_info->data.array.saved_offset;
4406 }
4407
4408 /* Restart all the inner loops we just finished. */
4409 for (dim = loop->temp_dim - 2; dim >= 0; dim--)
4410 {
4411 n = loop->order[dim];
4412
4413 gfc_start_block (&loop->code[n]);
4414
4415 loop->loopvar[n] = gfc_create_var (gfc_array_index_type, "Q");
4416
4417 gfc_trans_preloop_setup (loop, dim, 2, &loop->code[n]);
4418 }
4419
4420 /* Start a block for the secondary copying code. */
4421 gfc_start_block (body);
4422 }
4423
4424
4425 /* Precalculate (either lower or upper) bound of an array section.
4426 BLOCK: Block in which the (pre)calculation code will go.
4427 BOUNDS[DIM]: Where the bound value will be stored once evaluated.
4428 VALUES[DIM]: Specified bound (NULL <=> unspecified).
4429 DESC: Array descriptor from which the bound will be picked if unspecified
4430 (either lower or upper bound according to LBOUND). */
4431
4432 static void
evaluate_bound(stmtblock_t * block,tree * bounds,gfc_expr ** values,tree desc,int dim,bool lbound,bool deferred)4433 evaluate_bound (stmtblock_t *block, tree *bounds, gfc_expr ** values,
4434 tree desc, int dim, bool lbound, bool deferred)
4435 {
4436 gfc_se se;
4437 gfc_expr * input_val = values[dim];
4438 tree *output = &bounds[dim];
4439
4440
4441 if (input_val)
4442 {
4443 /* Specified section bound. */
4444 gfc_init_se (&se, NULL);
4445 gfc_conv_expr_type (&se, input_val, gfc_array_index_type);
4446 gfc_add_block_to_block (block, &se.pre);
4447 *output = se.expr;
4448 }
4449 else if (deferred && GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (desc)))
4450 {
4451 /* The gfc_conv_array_lbound () routine returns a constant zero for
4452 deferred length arrays, which in the scalarizer wreaks havoc, when
4453 copying to a (newly allocated) one-based array.
4454 Keep returning the actual result in sync for both bounds. */
4455 *output = lbound ? gfc_conv_descriptor_lbound_get (desc,
4456 gfc_rank_cst[dim]):
4457 gfc_conv_descriptor_ubound_get (desc,
4458 gfc_rank_cst[dim]);
4459 }
4460 else
4461 {
4462 /* No specific bound specified so use the bound of the array. */
4463 *output = lbound ? gfc_conv_array_lbound (desc, dim) :
4464 gfc_conv_array_ubound (desc, dim);
4465 }
4466 *output = gfc_evaluate_now (*output, block);
4467 }
4468
4469
4470 /* Calculate the lower bound of an array section. */
4471
4472 static void
gfc_conv_section_startstride(stmtblock_t * block,gfc_ss * ss,int dim)4473 gfc_conv_section_startstride (stmtblock_t * block, gfc_ss * ss, int dim)
4474 {
4475 gfc_expr *stride = NULL;
4476 tree desc;
4477 gfc_se se;
4478 gfc_array_info *info;
4479 gfc_array_ref *ar;
4480
4481 gcc_assert (ss->info->type == GFC_SS_SECTION);
4482
4483 info = &ss->info->data.array;
4484 ar = &info->ref->u.ar;
4485
4486 if (ar->dimen_type[dim] == DIMEN_VECTOR)
4487 {
4488 /* We use a zero-based index to access the vector. */
4489 info->start[dim] = gfc_index_zero_node;
4490 info->end[dim] = NULL;
4491 info->stride[dim] = gfc_index_one_node;
4492 return;
4493 }
4494
4495 gcc_assert (ar->dimen_type[dim] == DIMEN_RANGE
4496 || ar->dimen_type[dim] == DIMEN_THIS_IMAGE);
4497 desc = info->descriptor;
4498 stride = ar->stride[dim];
4499
4500
4501 /* Calculate the start of the range. For vector subscripts this will
4502 be the range of the vector. */
4503 evaluate_bound (block, info->start, ar->start, desc, dim, true,
4504 ar->as->type == AS_DEFERRED);
4505
4506 /* Similarly calculate the end. Although this is not used in the
4507 scalarizer, it is needed when checking bounds and where the end
4508 is an expression with side-effects. */
4509 evaluate_bound (block, info->end, ar->end, desc, dim, false,
4510 ar->as->type == AS_DEFERRED);
4511
4512
4513 /* Calculate the stride. */
4514 if (stride == NULL)
4515 info->stride[dim] = gfc_index_one_node;
4516 else
4517 {
4518 gfc_init_se (&se, NULL);
4519 gfc_conv_expr_type (&se, stride, gfc_array_index_type);
4520 gfc_add_block_to_block (block, &se.pre);
4521 info->stride[dim] = gfc_evaluate_now (se.expr, block);
4522 }
4523 }
4524
4525
4526 /* Calculates the range start and stride for a SS chain. Also gets the
4527 descriptor and data pointer. The range of vector subscripts is the size
4528 of the vector. Array bounds are also checked. */
4529
4530 void
gfc_conv_ss_startstride(gfc_loopinfo * loop)4531 gfc_conv_ss_startstride (gfc_loopinfo * loop)
4532 {
4533 int n;
4534 tree tmp;
4535 gfc_ss *ss;
4536 tree desc;
4537
4538 gfc_loopinfo * const outer_loop = outermost_loop (loop);
4539
4540 loop->dimen = 0;
4541 /* Determine the rank of the loop. */
4542 for (ss = loop->ss; ss != gfc_ss_terminator; ss = ss->loop_chain)
4543 {
4544 switch (ss->info->type)
4545 {
4546 case GFC_SS_SECTION:
4547 case GFC_SS_CONSTRUCTOR:
4548 case GFC_SS_FUNCTION:
4549 case GFC_SS_COMPONENT:
4550 loop->dimen = ss->dimen;
4551 goto done;
4552
4553 /* As usual, lbound and ubound are exceptions!. */
4554 case GFC_SS_INTRINSIC:
4555 switch (ss->info->expr->value.function.isym->id)
4556 {
4557 case GFC_ISYM_LBOUND:
4558 case GFC_ISYM_UBOUND:
4559 case GFC_ISYM_LCOBOUND:
4560 case GFC_ISYM_UCOBOUND:
4561 case GFC_ISYM_SHAPE:
4562 case GFC_ISYM_THIS_IMAGE:
4563 loop->dimen = ss->dimen;
4564 goto done;
4565
4566 default:
4567 break;
4568 }
4569
4570 default:
4571 break;
4572 }
4573 }
4574
4575 /* We should have determined the rank of the expression by now. If
4576 not, that's bad news. */
4577 gcc_unreachable ();
4578
4579 done:
4580 /* Loop over all the SS in the chain. */
4581 for (ss = loop->ss; ss != gfc_ss_terminator; ss = ss->loop_chain)
4582 {
4583 gfc_ss_info *ss_info;
4584 gfc_array_info *info;
4585 gfc_expr *expr;
4586
4587 ss_info = ss->info;
4588 expr = ss_info->expr;
4589 info = &ss_info->data.array;
4590
4591 if (expr && expr->shape && !info->shape)
4592 info->shape = expr->shape;
4593
4594 switch (ss_info->type)
4595 {
4596 case GFC_SS_SECTION:
4597 /* Get the descriptor for the array. If it is a cross loops array,
4598 we got the descriptor already in the outermost loop. */
4599 if (ss->parent == NULL)
4600 gfc_conv_ss_descriptor (&outer_loop->pre, ss,
4601 !loop->array_parameter);
4602
4603 for (n = 0; n < ss->dimen; n++)
4604 gfc_conv_section_startstride (&outer_loop->pre, ss, ss->dim[n]);
4605 break;
4606
4607 case GFC_SS_INTRINSIC:
4608 switch (expr->value.function.isym->id)
4609 {
4610 /* Fall through to supply start and stride. */
4611 case GFC_ISYM_LBOUND:
4612 case GFC_ISYM_UBOUND:
4613 /* This is the variant without DIM=... */
4614 gcc_assert (expr->value.function.actual->next->expr == NULL);
4615 /* Fall through. */
4616
4617 case GFC_ISYM_SHAPE:
4618 {
4619 gfc_expr *arg;
4620
4621 arg = expr->value.function.actual->expr;
4622 if (arg->rank == -1)
4623 {
4624 gfc_se se;
4625 tree rank, tmp;
4626
4627 /* The rank (hence the return value's shape) is unknown,
4628 we have to retrieve it. */
4629 gfc_init_se (&se, NULL);
4630 se.descriptor_only = 1;
4631 gfc_conv_expr (&se, arg);
4632 /* This is a bare variable, so there is no preliminary
4633 or cleanup code. */
4634 gcc_assert (se.pre.head == NULL_TREE
4635 && se.post.head == NULL_TREE);
4636 rank = gfc_conv_descriptor_rank (se.expr);
4637 tmp = fold_build2_loc (input_location, MINUS_EXPR,
4638 gfc_array_index_type,
4639 fold_convert (gfc_array_index_type,
4640 rank),
4641 gfc_index_one_node);
4642 info->end[0] = gfc_evaluate_now (tmp, &outer_loop->pre);
4643 info->start[0] = gfc_index_zero_node;
4644 info->stride[0] = gfc_index_one_node;
4645 continue;
4646 }
4647 /* Otherwise fall through GFC_SS_FUNCTION. */
4648 gcc_fallthrough ();
4649 }
4650 case GFC_ISYM_LCOBOUND:
4651 case GFC_ISYM_UCOBOUND:
4652 case GFC_ISYM_THIS_IMAGE:
4653 break;
4654
4655 default:
4656 continue;
4657 }
4658
4659 /* FALLTHRU */
4660 case GFC_SS_CONSTRUCTOR:
4661 case GFC_SS_FUNCTION:
4662 for (n = 0; n < ss->dimen; n++)
4663 {
4664 int dim = ss->dim[n];
4665
4666 info->start[dim] = gfc_index_zero_node;
4667 info->end[dim] = gfc_index_zero_node;
4668 info->stride[dim] = gfc_index_one_node;
4669 }
4670 break;
4671
4672 default:
4673 break;
4674 }
4675 }
4676
4677 /* The rest is just runtime bounds checking. */
4678 if (gfc_option.rtcheck & GFC_RTCHECK_BOUNDS)
4679 {
4680 stmtblock_t block;
4681 tree lbound, ubound;
4682 tree end;
4683 tree size[GFC_MAX_DIMENSIONS];
4684 tree stride_pos, stride_neg, non_zerosized, tmp2, tmp3;
4685 gfc_array_info *info;
4686 char *msg;
4687 int dim;
4688
4689 gfc_start_block (&block);
4690
4691 for (n = 0; n < loop->dimen; n++)
4692 size[n] = NULL_TREE;
4693
4694 for (ss = loop->ss; ss != gfc_ss_terminator; ss = ss->loop_chain)
4695 {
4696 stmtblock_t inner;
4697 gfc_ss_info *ss_info;
4698 gfc_expr *expr;
4699 locus *expr_loc;
4700 const char *expr_name;
4701
4702 ss_info = ss->info;
4703 if (ss_info->type != GFC_SS_SECTION)
4704 continue;
4705
4706 /* Catch allocatable lhs in f2003. */
4707 if (flag_realloc_lhs && ss->no_bounds_check)
4708 continue;
4709
4710 expr = ss_info->expr;
4711 expr_loc = &expr->where;
4712 expr_name = expr->symtree->name;
4713
4714 gfc_start_block (&inner);
4715
4716 /* TODO: range checking for mapped dimensions. */
4717 info = &ss_info->data.array;
4718
4719 /* This code only checks ranges. Elemental and vector
4720 dimensions are checked later. */
4721 for (n = 0; n < loop->dimen; n++)
4722 {
4723 bool check_upper;
4724
4725 dim = ss->dim[n];
4726 if (info->ref->u.ar.dimen_type[dim] != DIMEN_RANGE)
4727 continue;
4728
4729 if (dim == info->ref->u.ar.dimen - 1
4730 && info->ref->u.ar.as->type == AS_ASSUMED_SIZE)
4731 check_upper = false;
4732 else
4733 check_upper = true;
4734
4735 /* Zero stride is not allowed. */
4736 tmp = fold_build2_loc (input_location, EQ_EXPR, logical_type_node,
4737 info->stride[dim], gfc_index_zero_node);
4738 msg = xasprintf ("Zero stride is not allowed, for dimension %d "
4739 "of array '%s'", dim + 1, expr_name);
4740 gfc_trans_runtime_check (true, false, tmp, &inner,
4741 expr_loc, msg);
4742 free (msg);
4743
4744 desc = info->descriptor;
4745
4746 /* This is the run-time equivalent of resolve.cc's
4747 check_dimension(). The logical is more readable there
4748 than it is here, with all the trees. */
4749 lbound = gfc_conv_array_lbound (desc, dim);
4750 end = info->end[dim];
4751 if (check_upper)
4752 ubound = gfc_conv_array_ubound (desc, dim);
4753 else
4754 ubound = NULL;
4755
4756 /* non_zerosized is true when the selected range is not
4757 empty. */
4758 stride_pos = fold_build2_loc (input_location, GT_EXPR,
4759 logical_type_node, info->stride[dim],
4760 gfc_index_zero_node);
4761 tmp = fold_build2_loc (input_location, LE_EXPR, logical_type_node,
4762 info->start[dim], end);
4763 stride_pos = fold_build2_loc (input_location, TRUTH_AND_EXPR,
4764 logical_type_node, stride_pos, tmp);
4765
4766 stride_neg = fold_build2_loc (input_location, LT_EXPR,
4767 logical_type_node,
4768 info->stride[dim], gfc_index_zero_node);
4769 tmp = fold_build2_loc (input_location, GE_EXPR, logical_type_node,
4770 info->start[dim], end);
4771 stride_neg = fold_build2_loc (input_location, TRUTH_AND_EXPR,
4772 logical_type_node,
4773 stride_neg, tmp);
4774 non_zerosized = fold_build2_loc (input_location, TRUTH_OR_EXPR,
4775 logical_type_node,
4776 stride_pos, stride_neg);
4777
4778 /* Check the start of the range against the lower and upper
4779 bounds of the array, if the range is not empty.
4780 If upper bound is present, include both bounds in the
4781 error message. */
4782 if (check_upper)
4783 {
4784 tmp = fold_build2_loc (input_location, LT_EXPR,
4785 logical_type_node,
4786 info->start[dim], lbound);
4787 tmp = fold_build2_loc (input_location, TRUTH_AND_EXPR,
4788 logical_type_node,
4789 non_zerosized, tmp);
4790 tmp2 = fold_build2_loc (input_location, GT_EXPR,
4791 logical_type_node,
4792 info->start[dim], ubound);
4793 tmp2 = fold_build2_loc (input_location, TRUTH_AND_EXPR,
4794 logical_type_node,
4795 non_zerosized, tmp2);
4796 msg = xasprintf ("Index '%%ld' of dimension %d of array '%s' "
4797 "outside of expected range (%%ld:%%ld)",
4798 dim + 1, expr_name);
4799 gfc_trans_runtime_check (true, false, tmp, &inner,
4800 expr_loc, msg,
4801 fold_convert (long_integer_type_node, info->start[dim]),
4802 fold_convert (long_integer_type_node, lbound),
4803 fold_convert (long_integer_type_node, ubound));
4804 gfc_trans_runtime_check (true, false, tmp2, &inner,
4805 expr_loc, msg,
4806 fold_convert (long_integer_type_node, info->start[dim]),
4807 fold_convert (long_integer_type_node, lbound),
4808 fold_convert (long_integer_type_node, ubound));
4809 free (msg);
4810 }
4811 else
4812 {
4813 tmp = fold_build2_loc (input_location, LT_EXPR,
4814 logical_type_node,
4815 info->start[dim], lbound);
4816 tmp = fold_build2_loc (input_location, TRUTH_AND_EXPR,
4817 logical_type_node, non_zerosized, tmp);
4818 msg = xasprintf ("Index '%%ld' of dimension %d of array '%s' "
4819 "below lower bound of %%ld",
4820 dim + 1, expr_name);
4821 gfc_trans_runtime_check (true, false, tmp, &inner,
4822 expr_loc, msg,
4823 fold_convert (long_integer_type_node, info->start[dim]),
4824 fold_convert (long_integer_type_node, lbound));
4825 free (msg);
4826 }
4827
4828 /* Compute the last element of the range, which is not
4829 necessarily "end" (think 0:5:3, which doesn't contain 5)
4830 and check it against both lower and upper bounds. */
4831
4832 tmp = fold_build2_loc (input_location, MINUS_EXPR,
4833 gfc_array_index_type, end,
4834 info->start[dim]);
4835 tmp = fold_build2_loc (input_location, TRUNC_MOD_EXPR,
4836 gfc_array_index_type, tmp,
4837 info->stride[dim]);
4838 tmp = fold_build2_loc (input_location, MINUS_EXPR,
4839 gfc_array_index_type, end, tmp);
4840 tmp2 = fold_build2_loc (input_location, LT_EXPR,
4841 logical_type_node, tmp, lbound);
4842 tmp2 = fold_build2_loc (input_location, TRUTH_AND_EXPR,
4843 logical_type_node, non_zerosized, tmp2);
4844 if (check_upper)
4845 {
4846 tmp3 = fold_build2_loc (input_location, GT_EXPR,
4847 logical_type_node, tmp, ubound);
4848 tmp3 = fold_build2_loc (input_location, TRUTH_AND_EXPR,
4849 logical_type_node, non_zerosized, tmp3);
4850 msg = xasprintf ("Index '%%ld' of dimension %d of array '%s' "
4851 "outside of expected range (%%ld:%%ld)",
4852 dim + 1, expr_name);
4853 gfc_trans_runtime_check (true, false, tmp2, &inner,
4854 expr_loc, msg,
4855 fold_convert (long_integer_type_node, tmp),
4856 fold_convert (long_integer_type_node, ubound),
4857 fold_convert (long_integer_type_node, lbound));
4858 gfc_trans_runtime_check (true, false, tmp3, &inner,
4859 expr_loc, msg,
4860 fold_convert (long_integer_type_node, tmp),
4861 fold_convert (long_integer_type_node, ubound),
4862 fold_convert (long_integer_type_node, lbound));
4863 free (msg);
4864 }
4865 else
4866 {
4867 msg = xasprintf ("Index '%%ld' of dimension %d of array '%s' "
4868 "below lower bound of %%ld",
4869 dim + 1, expr_name);
4870 gfc_trans_runtime_check (true, false, tmp2, &inner,
4871 expr_loc, msg,
4872 fold_convert (long_integer_type_node, tmp),
4873 fold_convert (long_integer_type_node, lbound));
4874 free (msg);
4875 }
4876
4877 /* Check the section sizes match. */
4878 tmp = fold_build2_loc (input_location, MINUS_EXPR,
4879 gfc_array_index_type, end,
4880 info->start[dim]);
4881 tmp = fold_build2_loc (input_location, FLOOR_DIV_EXPR,
4882 gfc_array_index_type, tmp,
4883 info->stride[dim]);
4884 tmp = fold_build2_loc (input_location, PLUS_EXPR,
4885 gfc_array_index_type,
4886 gfc_index_one_node, tmp);
4887 tmp = fold_build2_loc (input_location, MAX_EXPR,
4888 gfc_array_index_type, tmp,
4889 build_int_cst (gfc_array_index_type, 0));
4890 /* We remember the size of the first section, and check all the
4891 others against this. */
4892 if (size[n])
4893 {
4894 tmp3 = fold_build2_loc (input_location, NE_EXPR,
4895 logical_type_node, tmp, size[n]);
4896 msg = xasprintf ("Array bound mismatch for dimension %d "
4897 "of array '%s' (%%ld/%%ld)",
4898 dim + 1, expr_name);
4899
4900 gfc_trans_runtime_check (true, false, tmp3, &inner,
4901 expr_loc, msg,
4902 fold_convert (long_integer_type_node, tmp),
4903 fold_convert (long_integer_type_node, size[n]));
4904
4905 free (msg);
4906 }
4907 else
4908 size[n] = gfc_evaluate_now (tmp, &inner);
4909 }
4910
4911 tmp = gfc_finish_block (&inner);
4912
4913 /* For optional arguments, only check bounds if the argument is
4914 present. */
4915 if ((expr->symtree->n.sym->attr.optional
4916 || expr->symtree->n.sym->attr.not_always_present)
4917 && expr->symtree->n.sym->attr.dummy)
4918 tmp = build3_v (COND_EXPR,
4919 gfc_conv_expr_present (expr->symtree->n.sym),
4920 tmp, build_empty_stmt (input_location));
4921
4922 gfc_add_expr_to_block (&block, tmp);
4923
4924 }
4925
4926 tmp = gfc_finish_block (&block);
4927 gfc_add_expr_to_block (&outer_loop->pre, tmp);
4928 }
4929
4930 for (loop = loop->nested; loop; loop = loop->next)
4931 gfc_conv_ss_startstride (loop);
4932 }
4933
4934 /* Return true if both symbols could refer to the same data object. Does
4935 not take account of aliasing due to equivalence statements. */
4936
4937 static int
symbols_could_alias(gfc_symbol * lsym,gfc_symbol * rsym,bool lsym_pointer,bool lsym_target,bool rsym_pointer,bool rsym_target)4938 symbols_could_alias (gfc_symbol *lsym, gfc_symbol *rsym, bool lsym_pointer,
4939 bool lsym_target, bool rsym_pointer, bool rsym_target)
4940 {
4941 /* Aliasing isn't possible if the symbols have different base types. */
4942 if (gfc_compare_types (&lsym->ts, &rsym->ts) == 0)
4943 return 0;
4944
4945 /* Pointers can point to other pointers and target objects. */
4946
4947 if ((lsym_pointer && (rsym_pointer || rsym_target))
4948 || (rsym_pointer && (lsym_pointer || lsym_target)))
4949 return 1;
4950
4951 /* Special case: Argument association, cf. F90 12.4.1.6, F2003 12.4.1.7
4952 and F2008 12.5.2.13 items 3b and 4b. The pointer case (a) is already
4953 checked above. */
4954 if (lsym_target && rsym_target
4955 && ((lsym->attr.dummy && !lsym->attr.contiguous
4956 && (!lsym->attr.dimension || lsym->as->type == AS_ASSUMED_SHAPE))
4957 || (rsym->attr.dummy && !rsym->attr.contiguous
4958 && (!rsym->attr.dimension
4959 || rsym->as->type == AS_ASSUMED_SHAPE))))
4960 return 1;
4961
4962 return 0;
4963 }
4964
4965
4966 /* Return true if the two SS could be aliased, i.e. both point to the same data
4967 object. */
4968 /* TODO: resolve aliases based on frontend expressions. */
4969
4970 static int
gfc_could_be_alias(gfc_ss * lss,gfc_ss * rss)4971 gfc_could_be_alias (gfc_ss * lss, gfc_ss * rss)
4972 {
4973 gfc_ref *lref;
4974 gfc_ref *rref;
4975 gfc_expr *lexpr, *rexpr;
4976 gfc_symbol *lsym;
4977 gfc_symbol *rsym;
4978 bool lsym_pointer, lsym_target, rsym_pointer, rsym_target;
4979
4980 lexpr = lss->info->expr;
4981 rexpr = rss->info->expr;
4982
4983 lsym = lexpr->symtree->n.sym;
4984 rsym = rexpr->symtree->n.sym;
4985
4986 lsym_pointer = lsym->attr.pointer;
4987 lsym_target = lsym->attr.target;
4988 rsym_pointer = rsym->attr.pointer;
4989 rsym_target = rsym->attr.target;
4990
4991 if (symbols_could_alias (lsym, rsym, lsym_pointer, lsym_target,
4992 rsym_pointer, rsym_target))
4993 return 1;
4994
4995 if (rsym->ts.type != BT_DERIVED && rsym->ts.type != BT_CLASS
4996 && lsym->ts.type != BT_DERIVED && lsym->ts.type != BT_CLASS)
4997 return 0;
4998
4999 /* For derived types we must check all the component types. We can ignore
5000 array references as these will have the same base type as the previous
5001 component ref. */
5002 for (lref = lexpr->ref; lref != lss->info->data.array.ref; lref = lref->next)
5003 {
5004 if (lref->type != REF_COMPONENT)
5005 continue;
5006
5007 lsym_pointer = lsym_pointer || lref->u.c.sym->attr.pointer;
5008 lsym_target = lsym_target || lref->u.c.sym->attr.target;
5009
5010 if (symbols_could_alias (lref->u.c.sym, rsym, lsym_pointer, lsym_target,
5011 rsym_pointer, rsym_target))
5012 return 1;
5013
5014 if ((lsym_pointer && (rsym_pointer || rsym_target))
5015 || (rsym_pointer && (lsym_pointer || lsym_target)))
5016 {
5017 if (gfc_compare_types (&lref->u.c.component->ts,
5018 &rsym->ts))
5019 return 1;
5020 }
5021
5022 for (rref = rexpr->ref; rref != rss->info->data.array.ref;
5023 rref = rref->next)
5024 {
5025 if (rref->type != REF_COMPONENT)
5026 continue;
5027
5028 rsym_pointer = rsym_pointer || rref->u.c.sym->attr.pointer;
5029 rsym_target = lsym_target || rref->u.c.sym->attr.target;
5030
5031 if (symbols_could_alias (lref->u.c.sym, rref->u.c.sym,
5032 lsym_pointer, lsym_target,
5033 rsym_pointer, rsym_target))
5034 return 1;
5035
5036 if ((lsym_pointer && (rsym_pointer || rsym_target))
5037 || (rsym_pointer && (lsym_pointer || lsym_target)))
5038 {
5039 if (gfc_compare_types (&lref->u.c.component->ts,
5040 &rref->u.c.sym->ts))
5041 return 1;
5042 if (gfc_compare_types (&lref->u.c.sym->ts,
5043 &rref->u.c.component->ts))
5044 return 1;
5045 if (gfc_compare_types (&lref->u.c.component->ts,
5046 &rref->u.c.component->ts))
5047 return 1;
5048 }
5049 }
5050 }
5051
5052 lsym_pointer = lsym->attr.pointer;
5053 lsym_target = lsym->attr.target;
5054
5055 for (rref = rexpr->ref; rref != rss->info->data.array.ref; rref = rref->next)
5056 {
5057 if (rref->type != REF_COMPONENT)
5058 break;
5059
5060 rsym_pointer = rsym_pointer || rref->u.c.sym->attr.pointer;
5061 rsym_target = lsym_target || rref->u.c.sym->attr.target;
5062
5063 if (symbols_could_alias (rref->u.c.sym, lsym,
5064 lsym_pointer, lsym_target,
5065 rsym_pointer, rsym_target))
5066 return 1;
5067
5068 if ((lsym_pointer && (rsym_pointer || rsym_target))
5069 || (rsym_pointer && (lsym_pointer || lsym_target)))
5070 {
5071 if (gfc_compare_types (&lsym->ts, &rref->u.c.component->ts))
5072 return 1;
5073 }
5074 }
5075
5076 return 0;
5077 }
5078
5079
5080 /* Resolve array data dependencies. Creates a temporary if required. */
5081 /* TODO: Calc dependencies with gfc_expr rather than gfc_ss, and move to
5082 dependency.cc. */
5083
5084 void
gfc_conv_resolve_dependencies(gfc_loopinfo * loop,gfc_ss * dest,gfc_ss * rss)5085 gfc_conv_resolve_dependencies (gfc_loopinfo * loop, gfc_ss * dest,
5086 gfc_ss * rss)
5087 {
5088 gfc_ss *ss;
5089 gfc_ref *lref;
5090 gfc_ref *rref;
5091 gfc_ss_info *ss_info;
5092 gfc_expr *dest_expr;
5093 gfc_expr *ss_expr;
5094 int nDepend = 0;
5095 int i, j;
5096
5097 loop->temp_ss = NULL;
5098 dest_expr = dest->info->expr;
5099
5100 for (ss = rss; ss != gfc_ss_terminator; ss = ss->next)
5101 {
5102 ss_info = ss->info;
5103 ss_expr = ss_info->expr;
5104
5105 if (ss_info->array_outer_dependency)
5106 {
5107 nDepend = 1;
5108 break;
5109 }
5110
5111 if (ss_info->type != GFC_SS_SECTION)
5112 {
5113 if (flag_realloc_lhs
5114 && dest_expr != ss_expr
5115 && gfc_is_reallocatable_lhs (dest_expr)
5116 && ss_expr->rank)
5117 nDepend = gfc_check_dependency (dest_expr, ss_expr, true);
5118
5119 /* Check for cases like c(:)(1:2) = c(2)(2:3) */
5120 if (!nDepend && dest_expr->rank > 0
5121 && dest_expr->ts.type == BT_CHARACTER
5122 && ss_expr->expr_type == EXPR_VARIABLE)
5123
5124 nDepend = gfc_check_dependency (dest_expr, ss_expr, false);
5125
5126 if (ss_info->type == GFC_SS_REFERENCE
5127 && gfc_check_dependency (dest_expr, ss_expr, false))
5128 ss_info->data.scalar.needs_temporary = 1;
5129
5130 if (nDepend)
5131 break;
5132 else
5133 continue;
5134 }
5135
5136 if (dest_expr->symtree->n.sym != ss_expr->symtree->n.sym)
5137 {
5138 if (gfc_could_be_alias (dest, ss)
5139 || gfc_are_equivalenced_arrays (dest_expr, ss_expr))
5140 {
5141 nDepend = 1;
5142 break;
5143 }
5144 }
5145 else
5146 {
5147 lref = dest_expr->ref;
5148 rref = ss_expr->ref;
5149
5150 nDepend = gfc_dep_resolver (lref, rref, &loop->reverse[0]);
5151
5152 if (nDepend == 1)
5153 break;
5154
5155 for (i = 0; i < dest->dimen; i++)
5156 for (j = 0; j < ss->dimen; j++)
5157 if (i != j
5158 && dest->dim[i] == ss->dim[j])
5159 {
5160 /* If we don't access array elements in the same order,
5161 there is a dependency. */
5162 nDepend = 1;
5163 goto temporary;
5164 }
5165 #if 0
5166 /* TODO : loop shifting. */
5167 if (nDepend == 1)
5168 {
5169 /* Mark the dimensions for LOOP SHIFTING */
5170 for (n = 0; n < loop->dimen; n++)
5171 {
5172 int dim = dest->data.info.dim[n];
5173
5174 if (lref->u.ar.dimen_type[dim] == DIMEN_VECTOR)
5175 depends[n] = 2;
5176 else if (! gfc_is_same_range (&lref->u.ar,
5177 &rref->u.ar, dim, 0))
5178 depends[n] = 1;
5179 }
5180
5181 /* Put all the dimensions with dependencies in the
5182 innermost loops. */
5183 dim = 0;
5184 for (n = 0; n < loop->dimen; n++)
5185 {
5186 gcc_assert (loop->order[n] == n);
5187 if (depends[n])
5188 loop->order[dim++] = n;
5189 }
5190 for (n = 0; n < loop->dimen; n++)
5191 {
5192 if (! depends[n])
5193 loop->order[dim++] = n;
5194 }
5195
5196 gcc_assert (dim == loop->dimen);
5197 break;
5198 }
5199 #endif
5200 }
5201 }
5202
5203 temporary:
5204
5205 if (nDepend == 1)
5206 {
5207 tree base_type = gfc_typenode_for_spec (&dest_expr->ts);
5208 if (GFC_ARRAY_TYPE_P (base_type)
5209 || GFC_DESCRIPTOR_TYPE_P (base_type))
5210 base_type = gfc_get_element_type (base_type);
5211 loop->temp_ss = gfc_get_temp_ss (base_type, dest->info->string_length,
5212 loop->dimen);
5213 gfc_add_ss_to_loop (loop, loop->temp_ss);
5214 }
5215 else
5216 loop->temp_ss = NULL;
5217 }
5218
5219
5220 /* Browse through each array's information from the scalarizer and set the loop
5221 bounds according to the "best" one (per dimension), i.e. the one which
5222 provides the most information (constant bounds, shape, etc.). */
5223
5224 static void
set_loop_bounds(gfc_loopinfo * loop)5225 set_loop_bounds (gfc_loopinfo *loop)
5226 {
5227 int n, dim, spec_dim;
5228 gfc_array_info *info;
5229 gfc_array_info *specinfo;
5230 gfc_ss *ss;
5231 tree tmp;
5232 gfc_ss **loopspec;
5233 bool dynamic[GFC_MAX_DIMENSIONS];
5234 mpz_t *cshape;
5235 mpz_t i;
5236 bool nonoptional_arr;
5237
5238 gfc_loopinfo * const outer_loop = outermost_loop (loop);
5239
5240 loopspec = loop->specloop;
5241
5242 mpz_init (i);
5243 for (n = 0; n < loop->dimen; n++)
5244 {
5245 loopspec[n] = NULL;
5246 dynamic[n] = false;
5247
5248 /* If there are both optional and nonoptional array arguments, scalarize
5249 over the nonoptional; otherwise, it does not matter as then all
5250 (optional) arrays have to be present per F2008, 125.2.12p3(6). */
5251
5252 nonoptional_arr = false;
5253
5254 for (ss = loop->ss; ss != gfc_ss_terminator; ss = ss->loop_chain)
5255 if (ss->info->type != GFC_SS_SCALAR && ss->info->type != GFC_SS_TEMP
5256 && ss->info->type != GFC_SS_REFERENCE && !ss->info->can_be_null_ref)
5257 {
5258 nonoptional_arr = true;
5259 break;
5260 }
5261
5262 /* We use one SS term, and use that to determine the bounds of the
5263 loop for this dimension. We try to pick the simplest term. */
5264 for (ss = loop->ss; ss != gfc_ss_terminator; ss = ss->loop_chain)
5265 {
5266 gfc_ss_type ss_type;
5267
5268 ss_type = ss->info->type;
5269 if (ss_type == GFC_SS_SCALAR
5270 || ss_type == GFC_SS_TEMP
5271 || ss_type == GFC_SS_REFERENCE
5272 || (ss->info->can_be_null_ref && nonoptional_arr))
5273 continue;
5274
5275 info = &ss->info->data.array;
5276 dim = ss->dim[n];
5277
5278 if (loopspec[n] != NULL)
5279 {
5280 specinfo = &loopspec[n]->info->data.array;
5281 spec_dim = loopspec[n]->dim[n];
5282 }
5283 else
5284 {
5285 /* Silence uninitialized warnings. */
5286 specinfo = NULL;
5287 spec_dim = 0;
5288 }
5289
5290 if (info->shape)
5291 {
5292 /* The frontend has worked out the size for us. */
5293 if (!loopspec[n]
5294 || !specinfo->shape
5295 || !integer_zerop (specinfo->start[spec_dim]))
5296 /* Prefer zero-based descriptors if possible. */
5297 loopspec[n] = ss;
5298 continue;
5299 }
5300
5301 if (ss_type == GFC_SS_CONSTRUCTOR)
5302 {
5303 gfc_constructor_base base;
5304 /* An unknown size constructor will always be rank one.
5305 Higher rank constructors will either have known shape,
5306 or still be wrapped in a call to reshape. */
5307 gcc_assert (loop->dimen == 1);
5308
5309 /* Always prefer to use the constructor bounds if the size
5310 can be determined at compile time. Prefer not to otherwise,
5311 since the general case involves realloc, and it's better to
5312 avoid that overhead if possible. */
5313 base = ss->info->expr->value.constructor;
5314 dynamic[n] = gfc_get_array_constructor_size (&i, base);
5315 if (!dynamic[n] || !loopspec[n])
5316 loopspec[n] = ss;
5317 continue;
5318 }
5319
5320 /* Avoid using an allocatable lhs in an assignment, since
5321 there might be a reallocation coming. */
5322 if (loopspec[n] && ss->is_alloc_lhs)
5323 continue;
5324
5325 if (!loopspec[n])
5326 loopspec[n] = ss;
5327 /* Criteria for choosing a loop specifier (most important first):
5328 doesn't need realloc
5329 stride of one
5330 known stride
5331 known lower bound
5332 known upper bound
5333 */
5334 else if (loopspec[n]->info->type == GFC_SS_CONSTRUCTOR && dynamic[n])
5335 loopspec[n] = ss;
5336 else if (integer_onep (info->stride[dim])
5337 && !integer_onep (specinfo->stride[spec_dim]))
5338 loopspec[n] = ss;
5339 else if (INTEGER_CST_P (info->stride[dim])
5340 && !INTEGER_CST_P (specinfo->stride[spec_dim]))
5341 loopspec[n] = ss;
5342 else if (INTEGER_CST_P (info->start[dim])
5343 && !INTEGER_CST_P (specinfo->start[spec_dim])
5344 && integer_onep (info->stride[dim])
5345 == integer_onep (specinfo->stride[spec_dim])
5346 && INTEGER_CST_P (info->stride[dim])
5347 == INTEGER_CST_P (specinfo->stride[spec_dim]))
5348 loopspec[n] = ss;
5349 /* We don't work out the upper bound.
5350 else if (INTEGER_CST_P (info->finish[n])
5351 && ! INTEGER_CST_P (specinfo->finish[n]))
5352 loopspec[n] = ss; */
5353 }
5354
5355 /* We should have found the scalarization loop specifier. If not,
5356 that's bad news. */
5357 gcc_assert (loopspec[n]);
5358
5359 info = &loopspec[n]->info->data.array;
5360 dim = loopspec[n]->dim[n];
5361
5362 /* Set the extents of this range. */
5363 cshape = info->shape;
5364 if (cshape && INTEGER_CST_P (info->start[dim])
5365 && INTEGER_CST_P (info->stride[dim]))
5366 {
5367 loop->from[n] = info->start[dim];
5368 mpz_set (i, cshape[get_array_ref_dim_for_loop_dim (loopspec[n], n)]);
5369 mpz_sub_ui (i, i, 1);
5370 /* To = from + (size - 1) * stride. */
5371 tmp = gfc_conv_mpz_to_tree (i, gfc_index_integer_kind);
5372 if (!integer_onep (info->stride[dim]))
5373 tmp = fold_build2_loc (input_location, MULT_EXPR,
5374 gfc_array_index_type, tmp,
5375 info->stride[dim]);
5376 loop->to[n] = fold_build2_loc (input_location, PLUS_EXPR,
5377 gfc_array_index_type,
5378 loop->from[n], tmp);
5379 }
5380 else
5381 {
5382 loop->from[n] = info->start[dim];
5383 switch (loopspec[n]->info->type)
5384 {
5385 case GFC_SS_CONSTRUCTOR:
5386 /* The upper bound is calculated when we expand the
5387 constructor. */
5388 gcc_assert (loop->to[n] == NULL_TREE);
5389 break;
5390
5391 case GFC_SS_SECTION:
5392 /* Use the end expression if it exists and is not constant,
5393 so that it is only evaluated once. */
5394 loop->to[n] = info->end[dim];
5395 break;
5396
5397 case GFC_SS_FUNCTION:
5398 /* The loop bound will be set when we generate the call. */
5399 gcc_assert (loop->to[n] == NULL_TREE);
5400 break;
5401
5402 case GFC_SS_INTRINSIC:
5403 {
5404 gfc_expr *expr = loopspec[n]->info->expr;
5405
5406 /* The {l,u}bound of an assumed rank. */
5407 if (expr->value.function.isym->id == GFC_ISYM_SHAPE)
5408 gcc_assert (expr->value.function.actual->expr->rank == -1);
5409 else
5410 gcc_assert ((expr->value.function.isym->id == GFC_ISYM_LBOUND
5411 || expr->value.function.isym->id == GFC_ISYM_UBOUND)
5412 && expr->value.function.actual->next->expr == NULL
5413 && expr->value.function.actual->expr->rank == -1);
5414
5415 loop->to[n] = info->end[dim];
5416 break;
5417 }
5418
5419 case GFC_SS_COMPONENT:
5420 {
5421 if (info->end[dim] != NULL_TREE)
5422 {
5423 loop->to[n] = info->end[dim];
5424 break;
5425 }
5426 else
5427 gcc_unreachable ();
5428 }
5429
5430 default:
5431 gcc_unreachable ();
5432 }
5433 }
5434
5435 /* Transform everything so we have a simple incrementing variable. */
5436 if (integer_onep (info->stride[dim]))
5437 info->delta[dim] = gfc_index_zero_node;
5438 else
5439 {
5440 /* Set the delta for this section. */
5441 info->delta[dim] = gfc_evaluate_now (loop->from[n], &outer_loop->pre);
5442 /* Number of iterations is (end - start + step) / step.
5443 with start = 0, this simplifies to
5444 last = end / step;
5445 for (i = 0; i<=last; i++){...}; */
5446 tmp = fold_build2_loc (input_location, MINUS_EXPR,
5447 gfc_array_index_type, loop->to[n],
5448 loop->from[n]);
5449 tmp = fold_build2_loc (input_location, FLOOR_DIV_EXPR,
5450 gfc_array_index_type, tmp, info->stride[dim]);
5451 tmp = fold_build2_loc (input_location, MAX_EXPR, gfc_array_index_type,
5452 tmp, build_int_cst (gfc_array_index_type, -1));
5453 loop->to[n] = gfc_evaluate_now (tmp, &outer_loop->pre);
5454 /* Make the loop variable start at 0. */
5455 loop->from[n] = gfc_index_zero_node;
5456 }
5457 }
5458 mpz_clear (i);
5459
5460 for (loop = loop->nested; loop; loop = loop->next)
5461 set_loop_bounds (loop);
5462 }
5463
5464
5465 /* Initialize the scalarization loop. Creates the loop variables. Determines
5466 the range of the loop variables. Creates a temporary if required.
5467 Also generates code for scalar expressions which have been
5468 moved outside the loop. */
5469
5470 void
gfc_conv_loop_setup(gfc_loopinfo * loop,locus * where)5471 gfc_conv_loop_setup (gfc_loopinfo * loop, locus * where)
5472 {
5473 gfc_ss *tmp_ss;
5474 tree tmp;
5475
5476 set_loop_bounds (loop);
5477
5478 /* Add all the scalar code that can be taken out of the loops.
5479 This may include calculating the loop bounds, so do it before
5480 allocating the temporary. */
5481 gfc_add_loop_ss_code (loop, loop->ss, false, where);
5482
5483 tmp_ss = loop->temp_ss;
5484 /* If we want a temporary then create it. */
5485 if (tmp_ss != NULL)
5486 {
5487 gfc_ss_info *tmp_ss_info;
5488
5489 tmp_ss_info = tmp_ss->info;
5490 gcc_assert (tmp_ss_info->type == GFC_SS_TEMP);
5491 gcc_assert (loop->parent == NULL);
5492
5493 /* Make absolutely sure that this is a complete type. */
5494 if (tmp_ss_info->string_length)
5495 tmp_ss_info->data.temp.type
5496 = gfc_get_character_type_len_for_eltype
5497 (TREE_TYPE (tmp_ss_info->data.temp.type),
5498 tmp_ss_info->string_length);
5499
5500 tmp = tmp_ss_info->data.temp.type;
5501 memset (&tmp_ss_info->data.array, 0, sizeof (gfc_array_info));
5502 tmp_ss_info->type = GFC_SS_SECTION;
5503
5504 gcc_assert (tmp_ss->dimen != 0);
5505
5506 gfc_trans_create_temp_array (&loop->pre, &loop->post, tmp_ss, tmp,
5507 NULL_TREE, false, true, false, where);
5508 }
5509
5510 /* For array parameters we don't have loop variables, so don't calculate the
5511 translations. */
5512 if (!loop->array_parameter)
5513 gfc_set_delta (loop);
5514 }
5515
5516
5517 /* Calculates how to transform from loop variables to array indices for each
5518 array: once loop bounds are chosen, sets the difference (DELTA field) between
5519 loop bounds and array reference bounds, for each array info. */
5520
5521 void
gfc_set_delta(gfc_loopinfo * loop)5522 gfc_set_delta (gfc_loopinfo *loop)
5523 {
5524 gfc_ss *ss, **loopspec;
5525 gfc_array_info *info;
5526 tree tmp;
5527 int n, dim;
5528
5529 gfc_loopinfo * const outer_loop = outermost_loop (loop);
5530
5531 loopspec = loop->specloop;
5532
5533 /* Calculate the translation from loop variables to array indices. */
5534 for (ss = loop->ss; ss != gfc_ss_terminator; ss = ss->loop_chain)
5535 {
5536 gfc_ss_type ss_type;
5537
5538 ss_type = ss->info->type;
5539 if (ss_type != GFC_SS_SECTION
5540 && ss_type != GFC_SS_COMPONENT
5541 && ss_type != GFC_SS_CONSTRUCTOR)
5542 continue;
5543
5544 info = &ss->info->data.array;
5545
5546 for (n = 0; n < ss->dimen; n++)
5547 {
5548 /* If we are specifying the range the delta is already set. */
5549 if (loopspec[n] != ss)
5550 {
5551 dim = ss->dim[n];
5552
5553 /* Calculate the offset relative to the loop variable.
5554 First multiply by the stride. */
5555 tmp = loop->from[n];
5556 if (!integer_onep (info->stride[dim]))
5557 tmp = fold_build2_loc (input_location, MULT_EXPR,
5558 gfc_array_index_type,
5559 tmp, info->stride[dim]);
5560
5561 /* Then subtract this from our starting value. */
5562 tmp = fold_build2_loc (input_location, MINUS_EXPR,
5563 gfc_array_index_type,
5564 info->start[dim], tmp);
5565
5566 info->delta[dim] = gfc_evaluate_now (tmp, &outer_loop->pre);
5567 }
5568 }
5569 }
5570
5571 for (loop = loop->nested; loop; loop = loop->next)
5572 gfc_set_delta (loop);
5573 }
5574
5575
5576 /* Calculate the size of a given array dimension from the bounds. This
5577 is simply (ubound - lbound + 1) if this expression is positive
5578 or 0 if it is negative (pick either one if it is zero). Optionally
5579 (if or_expr is present) OR the (expression != 0) condition to it. */
5580
5581 tree
gfc_conv_array_extent_dim(tree lbound,tree ubound,tree * or_expr)5582 gfc_conv_array_extent_dim (tree lbound, tree ubound, tree* or_expr)
5583 {
5584 tree res;
5585 tree cond;
5586
5587 /* Calculate (ubound - lbound + 1). */
5588 res = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
5589 ubound, lbound);
5590 res = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type, res,
5591 gfc_index_one_node);
5592
5593 /* Check whether the size for this dimension is negative. */
5594 cond = fold_build2_loc (input_location, LE_EXPR, logical_type_node, res,
5595 gfc_index_zero_node);
5596 res = fold_build3_loc (input_location, COND_EXPR, gfc_array_index_type, cond,
5597 gfc_index_zero_node, res);
5598
5599 /* Build OR expression. */
5600 if (or_expr)
5601 *or_expr = fold_build2_loc (input_location, TRUTH_OR_EXPR,
5602 logical_type_node, *or_expr, cond);
5603
5604 return res;
5605 }
5606
5607
5608 /* For an array descriptor, get the total number of elements. This is just
5609 the product of the extents along from_dim to to_dim. */
5610
5611 static tree
gfc_conv_descriptor_size_1(tree desc,int from_dim,int to_dim)5612 gfc_conv_descriptor_size_1 (tree desc, int from_dim, int to_dim)
5613 {
5614 tree res;
5615 int dim;
5616
5617 res = gfc_index_one_node;
5618
5619 for (dim = from_dim; dim < to_dim; ++dim)
5620 {
5621 tree lbound;
5622 tree ubound;
5623 tree extent;
5624
5625 lbound = gfc_conv_descriptor_lbound_get (desc, gfc_rank_cst[dim]);
5626 ubound = gfc_conv_descriptor_ubound_get (desc, gfc_rank_cst[dim]);
5627
5628 extent = gfc_conv_array_extent_dim (lbound, ubound, NULL);
5629 res = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
5630 res, extent);
5631 }
5632
5633 return res;
5634 }
5635
5636
5637 /* Full size of an array. */
5638
5639 tree
gfc_conv_descriptor_size(tree desc,int rank)5640 gfc_conv_descriptor_size (tree desc, int rank)
5641 {
5642 return gfc_conv_descriptor_size_1 (desc, 0, rank);
5643 }
5644
5645
5646 /* Size of a coarray for all dimensions but the last. */
5647
5648 tree
gfc_conv_descriptor_cosize(tree desc,int rank,int corank)5649 gfc_conv_descriptor_cosize (tree desc, int rank, int corank)
5650 {
5651 return gfc_conv_descriptor_size_1 (desc, rank, rank + corank - 1);
5652 }
5653
5654
5655 /* Fills in an array descriptor, and returns the size of the array.
5656 The size will be a simple_val, ie a variable or a constant. Also
5657 calculates the offset of the base. The pointer argument overflow,
5658 which should be of integer type, will increase in value if overflow
5659 occurs during the size calculation. Returns the size of the array.
5660 {
5661 stride = 1;
5662 offset = 0;
5663 for (n = 0; n < rank; n++)
5664 {
5665 a.lbound[n] = specified_lower_bound;
5666 offset = offset + a.lbond[n] * stride;
5667 size = 1 - lbound;
5668 a.ubound[n] = specified_upper_bound;
5669 a.stride[n] = stride;
5670 size = size >= 0 ? ubound + size : 0; //size = ubound + 1 - lbound
5671 overflow += size == 0 ? 0: (MAX/size < stride ? 1: 0);
5672 stride = stride * size;
5673 }
5674 for (n = rank; n < rank+corank; n++)
5675 (Set lcobound/ucobound as above.)
5676 element_size = sizeof (array element);
5677 if (!rank)
5678 return element_size
5679 stride = (size_t) stride;
5680 overflow += element_size == 0 ? 0: (MAX/element_size < stride ? 1: 0);
5681 stride = stride * element_size;
5682 return (stride);
5683 } */
5684 /*GCC ARRAYS*/
5685
5686 static tree
gfc_array_init_size(tree descriptor,int rank,int corank,tree * poffset,gfc_expr ** lower,gfc_expr ** upper,stmtblock_t * pblock,stmtblock_t * descriptor_block,tree * overflow,tree expr3_elem_size,tree * nelems,gfc_expr * expr3,tree expr3_desc,bool e3_has_nodescriptor,gfc_expr * expr,tree * element_size)5687 gfc_array_init_size (tree descriptor, int rank, int corank, tree * poffset,
5688 gfc_expr ** lower, gfc_expr ** upper, stmtblock_t * pblock,
5689 stmtblock_t * descriptor_block, tree * overflow,
5690 tree expr3_elem_size, tree *nelems, gfc_expr *expr3,
5691 tree expr3_desc, bool e3_has_nodescriptor, gfc_expr *expr,
5692 tree *element_size)
5693 {
5694 tree type;
5695 tree tmp;
5696 tree size;
5697 tree offset;
5698 tree stride;
5699 tree or_expr;
5700 tree thencase;
5701 tree elsecase;
5702 tree cond;
5703 tree var;
5704 stmtblock_t thenblock;
5705 stmtblock_t elseblock;
5706 gfc_expr *ubound;
5707 gfc_se se;
5708 int n;
5709
5710 type = TREE_TYPE (descriptor);
5711
5712 stride = gfc_index_one_node;
5713 offset = gfc_index_zero_node;
5714
5715 /* Set the dtype before the alloc, because registration of coarrays needs
5716 it initialized. */
5717 if (expr->ts.type == BT_CHARACTER
5718 && expr->ts.deferred
5719 && VAR_P (expr->ts.u.cl->backend_decl))
5720 {
5721 type = gfc_typenode_for_spec (&expr->ts);
5722 tmp = gfc_conv_descriptor_dtype (descriptor);
5723 gfc_add_modify (pblock, tmp, gfc_get_dtype_rank_type (rank, type));
5724 }
5725 else if (expr->ts.type == BT_CHARACTER
5726 && expr->ts.deferred
5727 && TREE_CODE (descriptor) == COMPONENT_REF)
5728 {
5729 /* Deferred character components have their string length tucked away
5730 in a hidden field of the derived type. Obtain that and use it to
5731 set the dtype. The charlen backend decl is zero because the field
5732 type is zero length. */
5733 gfc_ref *ref;
5734 tmp = NULL_TREE;
5735 for (ref = expr->ref; ref; ref = ref->next)
5736 if (ref->type == REF_COMPONENT
5737 && gfc_deferred_strlen (ref->u.c.component, &tmp))
5738 break;
5739 gcc_assert (tmp != NULL_TREE);
5740 tmp = fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (tmp),
5741 TREE_OPERAND (descriptor, 0), tmp, NULL_TREE);
5742 tmp = fold_convert (gfc_charlen_type_node, tmp);
5743 type = gfc_get_character_type_len (expr->ts.kind, tmp);
5744 tmp = gfc_conv_descriptor_dtype (descriptor);
5745 gfc_add_modify (pblock, tmp, gfc_get_dtype_rank_type (rank, type));
5746 }
5747 else
5748 {
5749 tmp = gfc_conv_descriptor_dtype (descriptor);
5750 gfc_add_modify (pblock, tmp, gfc_get_dtype (type));
5751 }
5752
5753 or_expr = logical_false_node;
5754
5755 for (n = 0; n < rank; n++)
5756 {
5757 tree conv_lbound;
5758 tree conv_ubound;
5759
5760 /* We have 3 possibilities for determining the size of the array:
5761 lower == NULL => lbound = 1, ubound = upper[n]
5762 upper[n] = NULL => lbound = 1, ubound = lower[n]
5763 upper[n] != NULL => lbound = lower[n], ubound = upper[n] */
5764 ubound = upper[n];
5765
5766 /* Set lower bound. */
5767 gfc_init_se (&se, NULL);
5768 if (expr3_desc != NULL_TREE)
5769 {
5770 if (e3_has_nodescriptor)
5771 /* The lbound of nondescriptor arrays like array constructors,
5772 nonallocatable/nonpointer function results/variables,
5773 start at zero, but when allocating it, the standard expects
5774 the array to start at one. */
5775 se.expr = gfc_index_one_node;
5776 else
5777 se.expr = gfc_conv_descriptor_lbound_get (expr3_desc,
5778 gfc_rank_cst[n]);
5779 }
5780 else if (lower == NULL)
5781 se.expr = gfc_index_one_node;
5782 else
5783 {
5784 gcc_assert (lower[n]);
5785 if (ubound)
5786 {
5787 gfc_conv_expr_type (&se, lower[n], gfc_array_index_type);
5788 gfc_add_block_to_block (pblock, &se.pre);
5789 }
5790 else
5791 {
5792 se.expr = gfc_index_one_node;
5793 ubound = lower[n];
5794 }
5795 }
5796 gfc_conv_descriptor_lbound_set (descriptor_block, descriptor,
5797 gfc_rank_cst[n], se.expr);
5798 conv_lbound = se.expr;
5799
5800 /* Work out the offset for this component. */
5801 tmp = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
5802 se.expr, stride);
5803 offset = fold_build2_loc (input_location, MINUS_EXPR,
5804 gfc_array_index_type, offset, tmp);
5805
5806 /* Set upper bound. */
5807 gfc_init_se (&se, NULL);
5808 if (expr3_desc != NULL_TREE)
5809 {
5810 if (e3_has_nodescriptor)
5811 {
5812 /* The lbound of nondescriptor arrays like array constructors,
5813 nonallocatable/nonpointer function results/variables,
5814 start at zero, but when allocating it, the standard expects
5815 the array to start at one. Therefore fix the upper bound to be
5816 (desc.ubound - desc.lbound) + 1. */
5817 tmp = fold_build2_loc (input_location, MINUS_EXPR,
5818 gfc_array_index_type,
5819 gfc_conv_descriptor_ubound_get (
5820 expr3_desc, gfc_rank_cst[n]),
5821 gfc_conv_descriptor_lbound_get (
5822 expr3_desc, gfc_rank_cst[n]));
5823 tmp = fold_build2_loc (input_location, PLUS_EXPR,
5824 gfc_array_index_type, tmp,
5825 gfc_index_one_node);
5826 se.expr = gfc_evaluate_now (tmp, pblock);
5827 }
5828 else
5829 se.expr = gfc_conv_descriptor_ubound_get (expr3_desc,
5830 gfc_rank_cst[n]);
5831 }
5832 else
5833 {
5834 gcc_assert (ubound);
5835 gfc_conv_expr_type (&se, ubound, gfc_array_index_type);
5836 gfc_add_block_to_block (pblock, &se.pre);
5837 if (ubound->expr_type == EXPR_FUNCTION)
5838 se.expr = gfc_evaluate_now (se.expr, pblock);
5839 }
5840 gfc_conv_descriptor_ubound_set (descriptor_block, descriptor,
5841 gfc_rank_cst[n], se.expr);
5842 conv_ubound = se.expr;
5843
5844 /* Store the stride. */
5845 gfc_conv_descriptor_stride_set (descriptor_block, descriptor,
5846 gfc_rank_cst[n], stride);
5847
5848 /* Calculate size and check whether extent is negative. */
5849 size = gfc_conv_array_extent_dim (conv_lbound, conv_ubound, &or_expr);
5850 size = gfc_evaluate_now (size, pblock);
5851
5852 /* Check whether multiplying the stride by the number of
5853 elements in this dimension would overflow. We must also check
5854 whether the current dimension has zero size in order to avoid
5855 division by zero.
5856 */
5857 tmp = fold_build2_loc (input_location, TRUNC_DIV_EXPR,
5858 gfc_array_index_type,
5859 fold_convert (gfc_array_index_type,
5860 TYPE_MAX_VALUE (gfc_array_index_type)),
5861 size);
5862 cond = gfc_unlikely (fold_build2_loc (input_location, LT_EXPR,
5863 logical_type_node, tmp, stride),
5864 PRED_FORTRAN_OVERFLOW);
5865 tmp = fold_build3_loc (input_location, COND_EXPR, integer_type_node, cond,
5866 integer_one_node, integer_zero_node);
5867 cond = gfc_unlikely (fold_build2_loc (input_location, EQ_EXPR,
5868 logical_type_node, size,
5869 gfc_index_zero_node),
5870 PRED_FORTRAN_SIZE_ZERO);
5871 tmp = fold_build3_loc (input_location, COND_EXPR, integer_type_node, cond,
5872 integer_zero_node, tmp);
5873 tmp = fold_build2_loc (input_location, PLUS_EXPR, integer_type_node,
5874 *overflow, tmp);
5875 *overflow = gfc_evaluate_now (tmp, pblock);
5876
5877 /* Multiply the stride by the number of elements in this dimension. */
5878 stride = fold_build2_loc (input_location, MULT_EXPR,
5879 gfc_array_index_type, stride, size);
5880 stride = gfc_evaluate_now (stride, pblock);
5881 }
5882
5883 for (n = rank; n < rank + corank; n++)
5884 {
5885 ubound = upper[n];
5886
5887 /* Set lower bound. */
5888 gfc_init_se (&se, NULL);
5889 if (lower == NULL || lower[n] == NULL)
5890 {
5891 gcc_assert (n == rank + corank - 1);
5892 se.expr = gfc_index_one_node;
5893 }
5894 else
5895 {
5896 if (ubound || n == rank + corank - 1)
5897 {
5898 gfc_conv_expr_type (&se, lower[n], gfc_array_index_type);
5899 gfc_add_block_to_block (pblock, &se.pre);
5900 }
5901 else
5902 {
5903 se.expr = gfc_index_one_node;
5904 ubound = lower[n];
5905 }
5906 }
5907 gfc_conv_descriptor_lbound_set (descriptor_block, descriptor,
5908 gfc_rank_cst[n], se.expr);
5909
5910 if (n < rank + corank - 1)
5911 {
5912 gfc_init_se (&se, NULL);
5913 gcc_assert (ubound);
5914 gfc_conv_expr_type (&se, ubound, gfc_array_index_type);
5915 gfc_add_block_to_block (pblock, &se.pre);
5916 gfc_conv_descriptor_ubound_set (descriptor_block, descriptor,
5917 gfc_rank_cst[n], se.expr);
5918 }
5919 }
5920
5921 /* The stride is the number of elements in the array, so multiply by the
5922 size of an element to get the total size. Obviously, if there is a
5923 SOURCE expression (expr3) we must use its element size. */
5924 if (expr3_elem_size != NULL_TREE)
5925 tmp = expr3_elem_size;
5926 else if (expr3 != NULL)
5927 {
5928 if (expr3->ts.type == BT_CLASS)
5929 {
5930 gfc_se se_sz;
5931 gfc_expr *sz = gfc_copy_expr (expr3);
5932 gfc_add_vptr_component (sz);
5933 gfc_add_size_component (sz);
5934 gfc_init_se (&se_sz, NULL);
5935 gfc_conv_expr (&se_sz, sz);
5936 gfc_free_expr (sz);
5937 tmp = se_sz.expr;
5938 }
5939 else
5940 {
5941 tmp = gfc_typenode_for_spec (&expr3->ts);
5942 tmp = TYPE_SIZE_UNIT (tmp);
5943 }
5944 }
5945 else
5946 tmp = TYPE_SIZE_UNIT (gfc_get_element_type (type));
5947
5948 /* Convert to size_t. */
5949 *element_size = fold_convert (size_type_node, tmp);
5950
5951 if (rank == 0)
5952 return *element_size;
5953
5954 *nelems = gfc_evaluate_now (stride, pblock);
5955 stride = fold_convert (size_type_node, stride);
5956
5957 /* First check for overflow. Since an array of type character can
5958 have zero element_size, we must check for that before
5959 dividing. */
5960 tmp = fold_build2_loc (input_location, TRUNC_DIV_EXPR,
5961 size_type_node,
5962 TYPE_MAX_VALUE (size_type_node), *element_size);
5963 cond = gfc_unlikely (fold_build2_loc (input_location, LT_EXPR,
5964 logical_type_node, tmp, stride),
5965 PRED_FORTRAN_OVERFLOW);
5966 tmp = fold_build3_loc (input_location, COND_EXPR, integer_type_node, cond,
5967 integer_one_node, integer_zero_node);
5968 cond = gfc_unlikely (fold_build2_loc (input_location, EQ_EXPR,
5969 logical_type_node, *element_size,
5970 build_int_cst (size_type_node, 0)),
5971 PRED_FORTRAN_SIZE_ZERO);
5972 tmp = fold_build3_loc (input_location, COND_EXPR, integer_type_node, cond,
5973 integer_zero_node, tmp);
5974 tmp = fold_build2_loc (input_location, PLUS_EXPR, integer_type_node,
5975 *overflow, tmp);
5976 *overflow = gfc_evaluate_now (tmp, pblock);
5977
5978 size = fold_build2_loc (input_location, MULT_EXPR, size_type_node,
5979 stride, *element_size);
5980
5981 if (poffset != NULL)
5982 {
5983 offset = gfc_evaluate_now (offset, pblock);
5984 *poffset = offset;
5985 }
5986
5987 if (integer_zerop (or_expr))
5988 return size;
5989 if (integer_onep (or_expr))
5990 return build_int_cst (size_type_node, 0);
5991
5992 var = gfc_create_var (TREE_TYPE (size), "size");
5993 gfc_start_block (&thenblock);
5994 gfc_add_modify (&thenblock, var, build_int_cst (size_type_node, 0));
5995 thencase = gfc_finish_block (&thenblock);
5996
5997 gfc_start_block (&elseblock);
5998 gfc_add_modify (&elseblock, var, size);
5999 elsecase = gfc_finish_block (&elseblock);
6000
6001 tmp = gfc_evaluate_now (or_expr, pblock);
6002 tmp = build3_v (COND_EXPR, tmp, thencase, elsecase);
6003 gfc_add_expr_to_block (pblock, tmp);
6004
6005 return var;
6006 }
6007
6008
6009 /* Retrieve the last ref from the chain. This routine is specific to
6010 gfc_array_allocate ()'s needs. */
6011
6012 bool
retrieve_last_ref(gfc_ref ** ref_in,gfc_ref ** prev_ref_in)6013 retrieve_last_ref (gfc_ref **ref_in, gfc_ref **prev_ref_in)
6014 {
6015 gfc_ref *ref, *prev_ref;
6016
6017 ref = *ref_in;
6018 /* Prevent warnings for uninitialized variables. */
6019 prev_ref = *prev_ref_in;
6020 while (ref && ref->next != NULL)
6021 {
6022 gcc_assert (ref->type != REF_ARRAY || ref->u.ar.type == AR_ELEMENT
6023 || (ref->u.ar.dimen == 0 && ref->u.ar.codimen > 0));
6024 prev_ref = ref;
6025 ref = ref->next;
6026 }
6027
6028 if (ref == NULL || ref->type != REF_ARRAY)
6029 return false;
6030
6031 *ref_in = ref;
6032 *prev_ref_in = prev_ref;
6033 return true;
6034 }
6035
6036 /* Initializes the descriptor and generates a call to _gfor_allocate. Does
6037 the work for an ALLOCATE statement. */
6038 /*GCC ARRAYS*/
6039
6040 bool
gfc_array_allocate(gfc_se * se,gfc_expr * expr,tree status,tree errmsg,tree errlen,tree label_finish,tree expr3_elem_size,tree * nelems,gfc_expr * expr3,tree e3_arr_desc,bool e3_has_nodescriptor)6041 gfc_array_allocate (gfc_se * se, gfc_expr * expr, tree status, tree errmsg,
6042 tree errlen, tree label_finish, tree expr3_elem_size,
6043 tree *nelems, gfc_expr *expr3, tree e3_arr_desc,
6044 bool e3_has_nodescriptor)
6045 {
6046 tree tmp;
6047 tree pointer;
6048 tree offset = NULL_TREE;
6049 tree token = NULL_TREE;
6050 tree size;
6051 tree msg;
6052 tree error = NULL_TREE;
6053 tree overflow; /* Boolean storing whether size calculation overflows. */
6054 tree var_overflow = NULL_TREE;
6055 tree cond;
6056 tree set_descriptor;
6057 tree not_prev_allocated = NULL_TREE;
6058 tree element_size = NULL_TREE;
6059 stmtblock_t set_descriptor_block;
6060 stmtblock_t elseblock;
6061 gfc_expr **lower;
6062 gfc_expr **upper;
6063 gfc_ref *ref, *prev_ref = NULL, *coref;
6064 bool allocatable, coarray, dimension, alloc_w_e3_arr_spec = false,
6065 non_ulimate_coarray_ptr_comp;
6066
6067 ref = expr->ref;
6068
6069 /* Find the last reference in the chain. */
6070 if (!retrieve_last_ref (&ref, &prev_ref))
6071 return false;
6072
6073 /* Take the allocatable and coarray properties solely from the expr-ref's
6074 attributes and not from source=-expression. */
6075 if (!prev_ref)
6076 {
6077 allocatable = expr->symtree->n.sym->attr.allocatable;
6078 dimension = expr->symtree->n.sym->attr.dimension;
6079 non_ulimate_coarray_ptr_comp = false;
6080 }
6081 else
6082 {
6083 allocatable = prev_ref->u.c.component->attr.allocatable;
6084 /* Pointer components in coarrayed derived types must be treated
6085 specially in that they are registered without a check if the are
6086 already associated. This does not hold for ultimate coarray
6087 pointers. */
6088 non_ulimate_coarray_ptr_comp = (prev_ref->u.c.component->attr.pointer
6089 && !prev_ref->u.c.component->attr.codimension);
6090 dimension = prev_ref->u.c.component->attr.dimension;
6091 }
6092
6093 /* For allocatable/pointer arrays in derived types, one of the refs has to be
6094 a coarray. In this case it does not matter whether we are on this_image
6095 or not. */
6096 coarray = false;
6097 for (coref = expr->ref; coref; coref = coref->next)
6098 if (coref->type == REF_ARRAY && coref->u.ar.codimen > 0)
6099 {
6100 coarray = true;
6101 break;
6102 }
6103
6104 if (!dimension)
6105 gcc_assert (coarray);
6106
6107 if (ref->u.ar.type == AR_FULL && expr3 != NULL)
6108 {
6109 gfc_ref *old_ref = ref;
6110 /* F08:C633: Array shape from expr3. */
6111 ref = expr3->ref;
6112
6113 /* Find the last reference in the chain. */
6114 if (!retrieve_last_ref (&ref, &prev_ref))
6115 {
6116 if (expr3->expr_type == EXPR_FUNCTION
6117 && gfc_expr_attr (expr3).dimension)
6118 ref = old_ref;
6119 else
6120 return false;
6121 }
6122 alloc_w_e3_arr_spec = true;
6123 }
6124
6125 /* Figure out the size of the array. */
6126 switch (ref->u.ar.type)
6127 {
6128 case AR_ELEMENT:
6129 if (!coarray)
6130 {
6131 lower = NULL;
6132 upper = ref->u.ar.start;
6133 break;
6134 }
6135 /* Fall through. */
6136
6137 case AR_SECTION:
6138 lower = ref->u.ar.start;
6139 upper = ref->u.ar.end;
6140 break;
6141
6142 case AR_FULL:
6143 gcc_assert (ref->u.ar.as->type == AS_EXPLICIT
6144 || alloc_w_e3_arr_spec);
6145
6146 lower = ref->u.ar.as->lower;
6147 upper = ref->u.ar.as->upper;
6148 break;
6149
6150 default:
6151 gcc_unreachable ();
6152 break;
6153 }
6154
6155 overflow = integer_zero_node;
6156
6157 if (expr->ts.type == BT_CHARACTER
6158 && TREE_CODE (se->string_length) == COMPONENT_REF
6159 && expr->ts.u.cl->backend_decl != se->string_length
6160 && VAR_P (expr->ts.u.cl->backend_decl))
6161 gfc_add_modify (&se->pre, expr->ts.u.cl->backend_decl,
6162 fold_convert (TREE_TYPE (expr->ts.u.cl->backend_decl),
6163 se->string_length));
6164
6165 gfc_init_block (&set_descriptor_block);
6166 /* Take the corank only from the actual ref and not from the coref. The
6167 later will mislead the generation of the array dimensions for allocatable/
6168 pointer components in derived types. */
6169 size = gfc_array_init_size (se->expr, alloc_w_e3_arr_spec ? expr->rank
6170 : ref->u.ar.as->rank,
6171 coarray ? ref->u.ar.as->corank : 0,
6172 &offset, lower, upper,
6173 &se->pre, &set_descriptor_block, &overflow,
6174 expr3_elem_size, nelems, expr3, e3_arr_desc,
6175 e3_has_nodescriptor, expr, &element_size);
6176
6177 if (dimension)
6178 {
6179 var_overflow = gfc_create_var (integer_type_node, "overflow");
6180 gfc_add_modify (&se->pre, var_overflow, overflow);
6181
6182 if (status == NULL_TREE)
6183 {
6184 /* Generate the block of code handling overflow. */
6185 msg = gfc_build_addr_expr (pchar_type_node,
6186 gfc_build_localized_cstring_const
6187 ("Integer overflow when calculating the amount of "
6188 "memory to allocate"));
6189 error = build_call_expr_loc (input_location,
6190 gfor_fndecl_runtime_error, 1, msg);
6191 }
6192 else
6193 {
6194 tree status_type = TREE_TYPE (status);
6195 stmtblock_t set_status_block;
6196
6197 gfc_start_block (&set_status_block);
6198 gfc_add_modify (&set_status_block, status,
6199 build_int_cst (status_type, LIBERROR_ALLOCATION));
6200 error = gfc_finish_block (&set_status_block);
6201 }
6202 }
6203
6204 /* Allocate memory to store the data. */
6205 if (POINTER_TYPE_P (TREE_TYPE (se->expr)))
6206 se->expr = build_fold_indirect_ref_loc (input_location, se->expr);
6207
6208 if (coarray && flag_coarray == GFC_FCOARRAY_LIB)
6209 {
6210 pointer = non_ulimate_coarray_ptr_comp ? se->expr
6211 : gfc_conv_descriptor_data_get (se->expr);
6212 token = gfc_conv_descriptor_token (se->expr);
6213 token = gfc_build_addr_expr (NULL_TREE, token);
6214 }
6215 else
6216 pointer = gfc_conv_descriptor_data_get (se->expr);
6217 STRIP_NOPS (pointer);
6218
6219 if (allocatable)
6220 {
6221 not_prev_allocated = gfc_create_var (logical_type_node,
6222 "not_prev_allocated");
6223 tmp = fold_build2_loc (input_location, EQ_EXPR,
6224 logical_type_node, pointer,
6225 build_int_cst (TREE_TYPE (pointer), 0));
6226
6227 gfc_add_modify (&se->pre, not_prev_allocated, tmp);
6228 }
6229
6230 gfc_start_block (&elseblock);
6231
6232 /* The allocatable variant takes the old pointer as first argument. */
6233 if (allocatable)
6234 gfc_allocate_allocatable (&elseblock, pointer, size, token,
6235 status, errmsg, errlen, label_finish, expr,
6236 coref != NULL ? coref->u.ar.as->corank : 0);
6237 else if (non_ulimate_coarray_ptr_comp && token)
6238 /* The token is set only for GFC_FCOARRAY_LIB mode. */
6239 gfc_allocate_using_caf_lib (&elseblock, pointer, size, token, status,
6240 errmsg, errlen,
6241 GFC_CAF_COARRAY_ALLOC_ALLOCATE_ONLY);
6242 else
6243 gfc_allocate_using_malloc (&elseblock, pointer, size, status);
6244
6245 if (dimension)
6246 {
6247 cond = gfc_unlikely (fold_build2_loc (input_location, NE_EXPR,
6248 logical_type_node, var_overflow, integer_zero_node),
6249 PRED_FORTRAN_OVERFLOW);
6250 tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node, cond,
6251 error, gfc_finish_block (&elseblock));
6252 }
6253 else
6254 tmp = gfc_finish_block (&elseblock);
6255
6256 gfc_add_expr_to_block (&se->pre, tmp);
6257
6258 /* Update the array descriptor with the offset and the span. */
6259 if (dimension)
6260 {
6261 gfc_conv_descriptor_offset_set (&set_descriptor_block, se->expr, offset);
6262 tmp = fold_convert (gfc_array_index_type, element_size);
6263 gfc_conv_descriptor_span_set (&set_descriptor_block, se->expr, tmp);
6264 }
6265
6266 set_descriptor = gfc_finish_block (&set_descriptor_block);
6267 if (status != NULL_TREE)
6268 {
6269 cond = fold_build2_loc (input_location, EQ_EXPR,
6270 logical_type_node, status,
6271 build_int_cst (TREE_TYPE (status), 0));
6272
6273 if (not_prev_allocated != NULL_TREE)
6274 cond = fold_build2_loc (input_location, TRUTH_OR_EXPR,
6275 logical_type_node, cond, not_prev_allocated);
6276
6277 gfc_add_expr_to_block (&se->pre,
6278 fold_build3_loc (input_location, COND_EXPR, void_type_node,
6279 cond,
6280 set_descriptor,
6281 build_empty_stmt (input_location)));
6282 }
6283 else
6284 gfc_add_expr_to_block (&se->pre, set_descriptor);
6285
6286 return true;
6287 }
6288
6289
6290 /* Create an array constructor from an initialization expression.
6291 We assume the frontend already did any expansions and conversions. */
6292
6293 tree
gfc_conv_array_initializer(tree type,gfc_expr * expr)6294 gfc_conv_array_initializer (tree type, gfc_expr * expr)
6295 {
6296 gfc_constructor *c;
6297 tree tmp;
6298 gfc_se se;
6299 tree index, range;
6300 vec<constructor_elt, va_gc> *v = NULL;
6301
6302 if (expr->expr_type == EXPR_VARIABLE
6303 && expr->symtree->n.sym->attr.flavor == FL_PARAMETER
6304 && expr->symtree->n.sym->value)
6305 expr = expr->symtree->n.sym->value;
6306
6307 switch (expr->expr_type)
6308 {
6309 case EXPR_CONSTANT:
6310 case EXPR_STRUCTURE:
6311 /* A single scalar or derived type value. Create an array with all
6312 elements equal to that value. */
6313 gfc_init_se (&se, NULL);
6314
6315 if (expr->expr_type == EXPR_CONSTANT)
6316 gfc_conv_constant (&se, expr);
6317 else
6318 gfc_conv_structure (&se, expr, 1);
6319
6320 if (tree_int_cst_lt (TYPE_MAX_VALUE (TYPE_DOMAIN (type)),
6321 TYPE_MIN_VALUE (TYPE_DOMAIN (type))))
6322 break;
6323 else if (tree_int_cst_equal (TYPE_MIN_VALUE (TYPE_DOMAIN (type)),
6324 TYPE_MAX_VALUE (TYPE_DOMAIN (type))))
6325 range = TYPE_MIN_VALUE (TYPE_DOMAIN (type));
6326 else
6327 range = build2 (RANGE_EXPR, gfc_array_index_type,
6328 TYPE_MIN_VALUE (TYPE_DOMAIN (type)),
6329 TYPE_MAX_VALUE (TYPE_DOMAIN (type)));
6330 CONSTRUCTOR_APPEND_ELT (v, range, se.expr);
6331 break;
6332
6333 case EXPR_ARRAY:
6334 /* Create a vector of all the elements. */
6335 for (c = gfc_constructor_first (expr->value.constructor);
6336 c && c->expr; c = gfc_constructor_next (c))
6337 {
6338 if (c->iterator)
6339 {
6340 /* Problems occur when we get something like
6341 integer :: a(lots) = (/(i, i=1, lots)/) */
6342 gfc_fatal_error ("The number of elements in the array "
6343 "constructor at %L requires an increase of "
6344 "the allowed %d upper limit. See "
6345 "%<-fmax-array-constructor%> option",
6346 &expr->where, flag_max_array_constructor);
6347 return NULL_TREE;
6348 }
6349 if (mpz_cmp_si (c->offset, 0) != 0)
6350 index = gfc_conv_mpz_to_tree (c->offset, gfc_index_integer_kind);
6351 else
6352 index = NULL_TREE;
6353
6354 if (mpz_cmp_si (c->repeat, 1) > 0)
6355 {
6356 tree tmp1, tmp2;
6357 mpz_t maxval;
6358
6359 mpz_init (maxval);
6360 mpz_add (maxval, c->offset, c->repeat);
6361 mpz_sub_ui (maxval, maxval, 1);
6362 tmp2 = gfc_conv_mpz_to_tree (maxval, gfc_index_integer_kind);
6363 if (mpz_cmp_si (c->offset, 0) != 0)
6364 {
6365 mpz_add_ui (maxval, c->offset, 1);
6366 tmp1 = gfc_conv_mpz_to_tree (maxval, gfc_index_integer_kind);
6367 }
6368 else
6369 tmp1 = gfc_conv_mpz_to_tree (c->offset, gfc_index_integer_kind);
6370
6371 range = fold_build2 (RANGE_EXPR, gfc_array_index_type, tmp1, tmp2);
6372 mpz_clear (maxval);
6373 }
6374 else
6375 range = NULL;
6376
6377 gfc_init_se (&se, NULL);
6378 switch (c->expr->expr_type)
6379 {
6380 case EXPR_CONSTANT:
6381 gfc_conv_constant (&se, c->expr);
6382
6383 /* See gfortran.dg/charlen_15.f90 for instance. */
6384 if (TREE_CODE (se.expr) == STRING_CST
6385 && TREE_CODE (type) == ARRAY_TYPE)
6386 {
6387 tree atype = type;
6388 while (TREE_CODE (TREE_TYPE (atype)) == ARRAY_TYPE)
6389 atype = TREE_TYPE (atype);
6390 gcc_checking_assert (TREE_CODE (TREE_TYPE (atype))
6391 == INTEGER_TYPE);
6392 gcc_checking_assert (TREE_TYPE (TREE_TYPE (se.expr))
6393 == TREE_TYPE (atype));
6394 if (tree_to_uhwi (TYPE_SIZE_UNIT (TREE_TYPE (se.expr)))
6395 > tree_to_uhwi (TYPE_SIZE_UNIT (atype)))
6396 {
6397 unsigned HOST_WIDE_INT size
6398 = tree_to_uhwi (TYPE_SIZE_UNIT (atype));
6399 const char *p = TREE_STRING_POINTER (se.expr);
6400
6401 se.expr = build_string (size, p);
6402 }
6403 TREE_TYPE (se.expr) = atype;
6404 }
6405 break;
6406
6407 case EXPR_STRUCTURE:
6408 gfc_conv_structure (&se, c->expr, 1);
6409 break;
6410
6411 default:
6412 /* Catch those occasional beasts that do not simplify
6413 for one reason or another, assuming that if they are
6414 standard defying the frontend will catch them. */
6415 gfc_conv_expr (&se, c->expr);
6416 break;
6417 }
6418
6419 if (range == NULL_TREE)
6420 CONSTRUCTOR_APPEND_ELT (v, index, se.expr);
6421 else
6422 {
6423 if (index != NULL_TREE)
6424 CONSTRUCTOR_APPEND_ELT (v, index, se.expr);
6425 CONSTRUCTOR_APPEND_ELT (v, range, se.expr);
6426 }
6427 }
6428 break;
6429
6430 case EXPR_NULL:
6431 return gfc_build_null_descriptor (type);
6432
6433 default:
6434 gcc_unreachable ();
6435 }
6436
6437 /* Create a constructor from the list of elements. */
6438 tmp = build_constructor (type, v);
6439 TREE_CONSTANT (tmp) = 1;
6440 return tmp;
6441 }
6442
6443
6444 /* Generate code to evaluate non-constant coarray cobounds. */
6445
6446 void
gfc_trans_array_cobounds(tree type,stmtblock_t * pblock,const gfc_symbol * sym)6447 gfc_trans_array_cobounds (tree type, stmtblock_t * pblock,
6448 const gfc_symbol *sym)
6449 {
6450 int dim;
6451 tree ubound;
6452 tree lbound;
6453 gfc_se se;
6454 gfc_array_spec *as;
6455
6456 as = IS_CLASS_ARRAY (sym) ? CLASS_DATA (sym)->as : sym->as;
6457
6458 for (dim = as->rank; dim < as->rank + as->corank; dim++)
6459 {
6460 /* Evaluate non-constant array bound expressions. */
6461 lbound = GFC_TYPE_ARRAY_LBOUND (type, dim);
6462 if (as->lower[dim] && !INTEGER_CST_P (lbound))
6463 {
6464 gfc_init_se (&se, NULL);
6465 gfc_conv_expr_type (&se, as->lower[dim], gfc_array_index_type);
6466 gfc_add_block_to_block (pblock, &se.pre);
6467 gfc_add_modify (pblock, lbound, se.expr);
6468 }
6469 ubound = GFC_TYPE_ARRAY_UBOUND (type, dim);
6470 if (as->upper[dim] && !INTEGER_CST_P (ubound))
6471 {
6472 gfc_init_se (&se, NULL);
6473 gfc_conv_expr_type (&se, as->upper[dim], gfc_array_index_type);
6474 gfc_add_block_to_block (pblock, &se.pre);
6475 gfc_add_modify (pblock, ubound, se.expr);
6476 }
6477 }
6478 }
6479
6480
6481 /* Generate code to evaluate non-constant array bounds. Sets *poffset and
6482 returns the size (in elements) of the array. */
6483
6484 tree
gfc_trans_array_bounds(tree type,gfc_symbol * sym,tree * poffset,stmtblock_t * pblock)6485 gfc_trans_array_bounds (tree type, gfc_symbol * sym, tree * poffset,
6486 stmtblock_t * pblock)
6487 {
6488 gfc_array_spec *as;
6489 tree size;
6490 tree stride;
6491 tree offset;
6492 tree ubound;
6493 tree lbound;
6494 tree tmp;
6495 gfc_se se;
6496
6497 int dim;
6498
6499 as = IS_CLASS_ARRAY (sym) ? CLASS_DATA (sym)->as : sym->as;
6500
6501 size = gfc_index_one_node;
6502 offset = gfc_index_zero_node;
6503 for (dim = 0; dim < as->rank; dim++)
6504 {
6505 /* Evaluate non-constant array bound expressions. */
6506 lbound = GFC_TYPE_ARRAY_LBOUND (type, dim);
6507 if (as->lower[dim] && !INTEGER_CST_P (lbound))
6508 {
6509 gfc_init_se (&se, NULL);
6510 gfc_conv_expr_type (&se, as->lower[dim], gfc_array_index_type);
6511 gfc_add_block_to_block (pblock, &se.pre);
6512 gfc_add_modify (pblock, lbound, se.expr);
6513 }
6514 ubound = GFC_TYPE_ARRAY_UBOUND (type, dim);
6515 if (as->upper[dim] && !INTEGER_CST_P (ubound))
6516 {
6517 gfc_init_se (&se, NULL);
6518 gfc_conv_expr_type (&se, as->upper[dim], gfc_array_index_type);
6519 gfc_add_block_to_block (pblock, &se.pre);
6520 gfc_add_modify (pblock, ubound, se.expr);
6521 }
6522 /* The offset of this dimension. offset = offset - lbound * stride. */
6523 tmp = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
6524 lbound, size);
6525 offset = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
6526 offset, tmp);
6527
6528 /* The size of this dimension, and the stride of the next. */
6529 if (dim + 1 < as->rank)
6530 stride = GFC_TYPE_ARRAY_STRIDE (type, dim + 1);
6531 else
6532 stride = GFC_TYPE_ARRAY_SIZE (type);
6533
6534 if (ubound != NULL_TREE && !(stride && INTEGER_CST_P (stride)))
6535 {
6536 /* Calculate stride = size * (ubound + 1 - lbound). */
6537 tmp = fold_build2_loc (input_location, MINUS_EXPR,
6538 gfc_array_index_type,
6539 gfc_index_one_node, lbound);
6540 tmp = fold_build2_loc (input_location, PLUS_EXPR,
6541 gfc_array_index_type, ubound, tmp);
6542 tmp = fold_build2_loc (input_location, MULT_EXPR,
6543 gfc_array_index_type, size, tmp);
6544 if (stride)
6545 gfc_add_modify (pblock, stride, tmp);
6546 else
6547 stride = gfc_evaluate_now (tmp, pblock);
6548
6549 /* Make sure that negative size arrays are translated
6550 to being zero size. */
6551 tmp = fold_build2_loc (input_location, GE_EXPR, logical_type_node,
6552 stride, gfc_index_zero_node);
6553 tmp = fold_build3_loc (input_location, COND_EXPR,
6554 gfc_array_index_type, tmp,
6555 stride, gfc_index_zero_node);
6556 gfc_add_modify (pblock, stride, tmp);
6557 }
6558
6559 size = stride;
6560 }
6561
6562 gfc_trans_array_cobounds (type, pblock, sym);
6563 gfc_trans_vla_type_sizes (sym, pblock);
6564
6565 *poffset = offset;
6566 return size;
6567 }
6568
6569
6570 /* Generate code to initialize/allocate an array variable. */
6571
6572 void
gfc_trans_auto_array_allocation(tree decl,gfc_symbol * sym,gfc_wrapped_block * block)6573 gfc_trans_auto_array_allocation (tree decl, gfc_symbol * sym,
6574 gfc_wrapped_block * block)
6575 {
6576 stmtblock_t init;
6577 tree type;
6578 tree tmp = NULL_TREE;
6579 tree size;
6580 tree offset;
6581 tree space;
6582 tree inittree;
6583 bool onstack;
6584
6585 gcc_assert (!(sym->attr.pointer || sym->attr.allocatable));
6586
6587 /* Do nothing for USEd variables. */
6588 if (sym->attr.use_assoc)
6589 return;
6590
6591 type = TREE_TYPE (decl);
6592 gcc_assert (GFC_ARRAY_TYPE_P (type));
6593 onstack = TREE_CODE (type) != POINTER_TYPE;
6594
6595 gfc_init_block (&init);
6596
6597 /* Evaluate character string length. */
6598 if (sym->ts.type == BT_CHARACTER
6599 && onstack && !INTEGER_CST_P (sym->ts.u.cl->backend_decl))
6600 {
6601 gfc_conv_string_length (sym->ts.u.cl, NULL, &init);
6602
6603 gfc_trans_vla_type_sizes (sym, &init);
6604
6605 /* Emit a DECL_EXPR for this variable, which will cause the
6606 gimplifier to allocate storage, and all that good stuff. */
6607 tmp = fold_build1_loc (input_location, DECL_EXPR, TREE_TYPE (decl), decl);
6608 gfc_add_expr_to_block (&init, tmp);
6609 }
6610
6611 if (onstack)
6612 {
6613 gfc_add_init_cleanup (block, gfc_finish_block (&init), NULL_TREE);
6614 return;
6615 }
6616
6617 type = TREE_TYPE (type);
6618
6619 gcc_assert (!sym->attr.use_assoc);
6620 gcc_assert (!sym->module);
6621
6622 if (sym->ts.type == BT_CHARACTER
6623 && !INTEGER_CST_P (sym->ts.u.cl->backend_decl))
6624 gfc_conv_string_length (sym->ts.u.cl, NULL, &init);
6625
6626 size = gfc_trans_array_bounds (type, sym, &offset, &init);
6627
6628 /* Don't actually allocate space for Cray Pointees. */
6629 if (sym->attr.cray_pointee)
6630 {
6631 if (VAR_P (GFC_TYPE_ARRAY_OFFSET (type)))
6632 gfc_add_modify (&init, GFC_TYPE_ARRAY_OFFSET (type), offset);
6633
6634 gfc_add_init_cleanup (block, gfc_finish_block (&init), NULL_TREE);
6635 return;
6636 }
6637
6638 if (flag_stack_arrays)
6639 {
6640 gcc_assert (TREE_CODE (TREE_TYPE (decl)) == POINTER_TYPE);
6641 space = build_decl (gfc_get_location (&sym->declared_at),
6642 VAR_DECL, create_tmp_var_name ("A"),
6643 TREE_TYPE (TREE_TYPE (decl)));
6644 gfc_trans_vla_type_sizes (sym, &init);
6645 }
6646 else
6647 {
6648 /* The size is the number of elements in the array, so multiply by the
6649 size of an element to get the total size. */
6650 tmp = TYPE_SIZE_UNIT (gfc_get_element_type (type));
6651 size = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
6652 size, fold_convert (gfc_array_index_type, tmp));
6653
6654 /* Allocate memory to hold the data. */
6655 tmp = gfc_call_malloc (&init, TREE_TYPE (decl), size);
6656 gfc_add_modify (&init, decl, tmp);
6657
6658 /* Free the temporary. */
6659 tmp = gfc_call_free (decl);
6660 space = NULL_TREE;
6661 }
6662
6663 /* Set offset of the array. */
6664 if (VAR_P (GFC_TYPE_ARRAY_OFFSET (type)))
6665 gfc_add_modify (&init, GFC_TYPE_ARRAY_OFFSET (type), offset);
6666
6667 /* Automatic arrays should not have initializers. */
6668 gcc_assert (!sym->value);
6669
6670 inittree = gfc_finish_block (&init);
6671
6672 if (space)
6673 {
6674 tree addr;
6675 pushdecl (space);
6676
6677 /* Don't create new scope, emit the DECL_EXPR in exactly the scope
6678 where also space is located. */
6679 gfc_init_block (&init);
6680 tmp = fold_build1_loc (input_location, DECL_EXPR,
6681 TREE_TYPE (space), space);
6682 gfc_add_expr_to_block (&init, tmp);
6683 addr = fold_build1_loc (gfc_get_location (&sym->declared_at),
6684 ADDR_EXPR, TREE_TYPE (decl), space);
6685 gfc_add_modify (&init, decl, addr);
6686 gfc_add_init_cleanup (block, gfc_finish_block (&init), NULL_TREE);
6687 tmp = NULL_TREE;
6688 }
6689 gfc_add_init_cleanup (block, inittree, tmp);
6690 }
6691
6692
6693 /* Generate entry and exit code for g77 calling convention arrays. */
6694
6695 void
gfc_trans_g77_array(gfc_symbol * sym,gfc_wrapped_block * block)6696 gfc_trans_g77_array (gfc_symbol * sym, gfc_wrapped_block * block)
6697 {
6698 tree parm;
6699 tree type;
6700 locus loc;
6701 tree offset;
6702 tree tmp;
6703 tree stmt;
6704 stmtblock_t init;
6705
6706 gfc_save_backend_locus (&loc);
6707 gfc_set_backend_locus (&sym->declared_at);
6708
6709 /* Descriptor type. */
6710 parm = sym->backend_decl;
6711 type = TREE_TYPE (parm);
6712 gcc_assert (GFC_ARRAY_TYPE_P (type));
6713
6714 gfc_start_block (&init);
6715
6716 if (sym->ts.type == BT_CHARACTER
6717 && VAR_P (sym->ts.u.cl->backend_decl))
6718 gfc_conv_string_length (sym->ts.u.cl, NULL, &init);
6719
6720 /* Evaluate the bounds of the array. */
6721 gfc_trans_array_bounds (type, sym, &offset, &init);
6722
6723 /* Set the offset. */
6724 if (VAR_P (GFC_TYPE_ARRAY_OFFSET (type)))
6725 gfc_add_modify (&init, GFC_TYPE_ARRAY_OFFSET (type), offset);
6726
6727 /* Set the pointer itself if we aren't using the parameter directly. */
6728 if (TREE_CODE (parm) != PARM_DECL)
6729 {
6730 tmp = GFC_DECL_SAVED_DESCRIPTOR (parm);
6731 if (sym->ts.type == BT_CLASS)
6732 {
6733 tmp = build_fold_indirect_ref_loc (input_location, tmp);
6734 tmp = gfc_class_data_get (tmp);
6735 tmp = gfc_conv_descriptor_data_get (tmp);
6736 }
6737 tmp = convert (TREE_TYPE (parm), tmp);
6738 gfc_add_modify (&init, parm, tmp);
6739 }
6740 stmt = gfc_finish_block (&init);
6741
6742 gfc_restore_backend_locus (&loc);
6743
6744 /* Add the initialization code to the start of the function. */
6745
6746 if ((sym->ts.type == BT_CLASS && CLASS_DATA (sym)->attr.optional)
6747 || sym->attr.optional
6748 || sym->attr.not_always_present)
6749 {
6750 tree nullify;
6751 if (TREE_CODE (parm) != PARM_DECL)
6752 nullify = fold_build2_loc (input_location, MODIFY_EXPR, void_type_node,
6753 parm, null_pointer_node);
6754 else
6755 nullify = build_empty_stmt (input_location);
6756 tmp = gfc_conv_expr_present (sym, true);
6757 stmt = build3_v (COND_EXPR, tmp, stmt, nullify);
6758 }
6759
6760 gfc_add_init_cleanup (block, stmt, NULL_TREE);
6761 }
6762
6763
6764 /* Modify the descriptor of an array parameter so that it has the
6765 correct lower bound. Also move the upper bound accordingly.
6766 If the array is not packed, it will be copied into a temporary.
6767 For each dimension we set the new lower and upper bounds. Then we copy the
6768 stride and calculate the offset for this dimension. We also work out
6769 what the stride of a packed array would be, and see it the two match.
6770 If the array need repacking, we set the stride to the values we just
6771 calculated, recalculate the offset and copy the array data.
6772 Code is also added to copy the data back at the end of the function.
6773 */
6774
6775 void
gfc_trans_dummy_array_bias(gfc_symbol * sym,tree tmpdesc,gfc_wrapped_block * block)6776 gfc_trans_dummy_array_bias (gfc_symbol * sym, tree tmpdesc,
6777 gfc_wrapped_block * block)
6778 {
6779 tree size;
6780 tree type;
6781 tree offset;
6782 locus loc;
6783 stmtblock_t init;
6784 tree stmtInit, stmtCleanup;
6785 tree lbound;
6786 tree ubound;
6787 tree dubound;
6788 tree dlbound;
6789 tree dumdesc;
6790 tree tmp;
6791 tree stride, stride2;
6792 tree stmt_packed;
6793 tree stmt_unpacked;
6794 tree partial;
6795 gfc_se se;
6796 int n;
6797 int checkparm;
6798 int no_repack;
6799 bool optional_arg;
6800 gfc_array_spec *as;
6801 bool is_classarray = IS_CLASS_ARRAY (sym);
6802
6803 /* Do nothing for pointer and allocatable arrays. */
6804 if ((sym->ts.type != BT_CLASS && sym->attr.pointer)
6805 || (sym->ts.type == BT_CLASS && CLASS_DATA (sym)->attr.class_pointer)
6806 || sym->attr.allocatable
6807 || (is_classarray && CLASS_DATA (sym)->attr.allocatable))
6808 return;
6809
6810 if (!is_classarray && sym->attr.dummy && gfc_is_nodesc_array (sym))
6811 {
6812 gfc_trans_g77_array (sym, block);
6813 return;
6814 }
6815
6816 loc.nextc = NULL;
6817 gfc_save_backend_locus (&loc);
6818 /* loc.nextc is not set by save_backend_locus but the location routines
6819 depend on it. */
6820 if (loc.nextc == NULL)
6821 loc.nextc = loc.lb->line;
6822 gfc_set_backend_locus (&sym->declared_at);
6823
6824 /* Descriptor type. */
6825 type = TREE_TYPE (tmpdesc);
6826 gcc_assert (GFC_ARRAY_TYPE_P (type));
6827 dumdesc = GFC_DECL_SAVED_DESCRIPTOR (tmpdesc);
6828 if (is_classarray)
6829 /* For a class array the dummy array descriptor is in the _class
6830 component. */
6831 dumdesc = gfc_class_data_get (dumdesc);
6832 else
6833 dumdesc = build_fold_indirect_ref_loc (input_location, dumdesc);
6834 as = IS_CLASS_ARRAY (sym) ? CLASS_DATA (sym)->as : sym->as;
6835 gfc_start_block (&init);
6836
6837 if (sym->ts.type == BT_CHARACTER
6838 && VAR_P (sym->ts.u.cl->backend_decl))
6839 gfc_conv_string_length (sym->ts.u.cl, NULL, &init);
6840
6841 /* TODO: Fix the exclusion of class arrays from extent checking. */
6842 checkparm = (as->type == AS_EXPLICIT && !is_classarray
6843 && (gfc_option.rtcheck & GFC_RTCHECK_BOUNDS));
6844
6845 no_repack = !(GFC_DECL_PACKED_ARRAY (tmpdesc)
6846 || GFC_DECL_PARTIAL_PACKED_ARRAY (tmpdesc));
6847
6848 if (GFC_DECL_PARTIAL_PACKED_ARRAY (tmpdesc))
6849 {
6850 /* For non-constant shape arrays we only check if the first dimension
6851 is contiguous. Repacking higher dimensions wouldn't gain us
6852 anything as we still don't know the array stride. */
6853 partial = gfc_create_var (logical_type_node, "partial");
6854 TREE_USED (partial) = 1;
6855 tmp = gfc_conv_descriptor_stride_get (dumdesc, gfc_rank_cst[0]);
6856 tmp = fold_build2_loc (input_location, EQ_EXPR, logical_type_node, tmp,
6857 gfc_index_one_node);
6858 gfc_add_modify (&init, partial, tmp);
6859 }
6860 else
6861 partial = NULL_TREE;
6862
6863 /* The naming of stmt_unpacked and stmt_packed may be counter-intuitive
6864 here, however I think it does the right thing. */
6865 if (no_repack)
6866 {
6867 /* Set the first stride. */
6868 stride = gfc_conv_descriptor_stride_get (dumdesc, gfc_rank_cst[0]);
6869 stride = gfc_evaluate_now (stride, &init);
6870
6871 tmp = fold_build2_loc (input_location, EQ_EXPR, logical_type_node,
6872 stride, gfc_index_zero_node);
6873 tmp = fold_build3_loc (input_location, COND_EXPR, gfc_array_index_type,
6874 tmp, gfc_index_one_node, stride);
6875 stride = GFC_TYPE_ARRAY_STRIDE (type, 0);
6876 gfc_add_modify (&init, stride, tmp);
6877
6878 /* Allow the user to disable array repacking. */
6879 stmt_unpacked = NULL_TREE;
6880 }
6881 else
6882 {
6883 gcc_assert (integer_onep (GFC_TYPE_ARRAY_STRIDE (type, 0)));
6884 /* A library call to repack the array if necessary. */
6885 tmp = GFC_DECL_SAVED_DESCRIPTOR (tmpdesc);
6886 stmt_unpacked = build_call_expr_loc (input_location,
6887 gfor_fndecl_in_pack, 1, tmp);
6888
6889 stride = gfc_index_one_node;
6890
6891 if (warn_array_temporaries)
6892 gfc_warning (OPT_Warray_temporaries,
6893 "Creating array temporary at %L", &loc);
6894 }
6895
6896 /* This is for the case where the array data is used directly without
6897 calling the repack function. */
6898 if (no_repack || partial != NULL_TREE)
6899 stmt_packed = gfc_conv_descriptor_data_get (dumdesc);
6900 else
6901 stmt_packed = NULL_TREE;
6902
6903 /* Assign the data pointer. */
6904 if (stmt_packed != NULL_TREE && stmt_unpacked != NULL_TREE)
6905 {
6906 /* Don't repack unknown shape arrays when the first stride is 1. */
6907 tmp = fold_build3_loc (input_location, COND_EXPR, TREE_TYPE (stmt_packed),
6908 partial, stmt_packed, stmt_unpacked);
6909 }
6910 else
6911 tmp = stmt_packed != NULL_TREE ? stmt_packed : stmt_unpacked;
6912 gfc_add_modify (&init, tmpdesc, fold_convert (type, tmp));
6913
6914 offset = gfc_index_zero_node;
6915 size = gfc_index_one_node;
6916
6917 /* Evaluate the bounds of the array. */
6918 for (n = 0; n < as->rank; n++)
6919 {
6920 if (checkparm || !as->upper[n])
6921 {
6922 /* Get the bounds of the actual parameter. */
6923 dubound = gfc_conv_descriptor_ubound_get (dumdesc, gfc_rank_cst[n]);
6924 dlbound = gfc_conv_descriptor_lbound_get (dumdesc, gfc_rank_cst[n]);
6925 }
6926 else
6927 {
6928 dubound = NULL_TREE;
6929 dlbound = NULL_TREE;
6930 }
6931
6932 lbound = GFC_TYPE_ARRAY_LBOUND (type, n);
6933 if (!INTEGER_CST_P (lbound))
6934 {
6935 gfc_init_se (&se, NULL);
6936 gfc_conv_expr_type (&se, as->lower[n],
6937 gfc_array_index_type);
6938 gfc_add_block_to_block (&init, &se.pre);
6939 gfc_add_modify (&init, lbound, se.expr);
6940 }
6941
6942 ubound = GFC_TYPE_ARRAY_UBOUND (type, n);
6943 /* Set the desired upper bound. */
6944 if (as->upper[n])
6945 {
6946 /* We know what we want the upper bound to be. */
6947 if (!INTEGER_CST_P (ubound))
6948 {
6949 gfc_init_se (&se, NULL);
6950 gfc_conv_expr_type (&se, as->upper[n],
6951 gfc_array_index_type);
6952 gfc_add_block_to_block (&init, &se.pre);
6953 gfc_add_modify (&init, ubound, se.expr);
6954 }
6955
6956 /* Check the sizes match. */
6957 if (checkparm)
6958 {
6959 /* Check (ubound(a) - lbound(a) == ubound(b) - lbound(b)). */
6960 char * msg;
6961 tree temp;
6962
6963 temp = fold_build2_loc (input_location, MINUS_EXPR,
6964 gfc_array_index_type, ubound, lbound);
6965 temp = fold_build2_loc (input_location, PLUS_EXPR,
6966 gfc_array_index_type,
6967 gfc_index_one_node, temp);
6968 stride2 = fold_build2_loc (input_location, MINUS_EXPR,
6969 gfc_array_index_type, dubound,
6970 dlbound);
6971 stride2 = fold_build2_loc (input_location, PLUS_EXPR,
6972 gfc_array_index_type,
6973 gfc_index_one_node, stride2);
6974 tmp = fold_build2_loc (input_location, NE_EXPR,
6975 gfc_array_index_type, temp, stride2);
6976 msg = xasprintf ("Dimension %d of array '%s' has extent "
6977 "%%ld instead of %%ld", n+1, sym->name);
6978
6979 gfc_trans_runtime_check (true, false, tmp, &init, &loc, msg,
6980 fold_convert (long_integer_type_node, temp),
6981 fold_convert (long_integer_type_node, stride2));
6982
6983 free (msg);
6984 }
6985 }
6986 else
6987 {
6988 /* For assumed shape arrays move the upper bound by the same amount
6989 as the lower bound. */
6990 tmp = fold_build2_loc (input_location, MINUS_EXPR,
6991 gfc_array_index_type, dubound, dlbound);
6992 tmp = fold_build2_loc (input_location, PLUS_EXPR,
6993 gfc_array_index_type, tmp, lbound);
6994 gfc_add_modify (&init, ubound, tmp);
6995 }
6996 /* The offset of this dimension. offset = offset - lbound * stride. */
6997 tmp = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
6998 lbound, stride);
6999 offset = fold_build2_loc (input_location, MINUS_EXPR,
7000 gfc_array_index_type, offset, tmp);
7001
7002 /* The size of this dimension, and the stride of the next. */
7003 if (n + 1 < as->rank)
7004 {
7005 stride = GFC_TYPE_ARRAY_STRIDE (type, n + 1);
7006
7007 if (no_repack || partial != NULL_TREE)
7008 stmt_unpacked =
7009 gfc_conv_descriptor_stride_get (dumdesc, gfc_rank_cst[n+1]);
7010
7011 /* Figure out the stride if not a known constant. */
7012 if (!INTEGER_CST_P (stride))
7013 {
7014 if (no_repack)
7015 stmt_packed = NULL_TREE;
7016 else
7017 {
7018 /* Calculate stride = size * (ubound + 1 - lbound). */
7019 tmp = fold_build2_loc (input_location, MINUS_EXPR,
7020 gfc_array_index_type,
7021 gfc_index_one_node, lbound);
7022 tmp = fold_build2_loc (input_location, PLUS_EXPR,
7023 gfc_array_index_type, ubound, tmp);
7024 size = fold_build2_loc (input_location, MULT_EXPR,
7025 gfc_array_index_type, size, tmp);
7026 stmt_packed = size;
7027 }
7028
7029 /* Assign the stride. */
7030 if (stmt_packed != NULL_TREE && stmt_unpacked != NULL_TREE)
7031 tmp = fold_build3_loc (input_location, COND_EXPR,
7032 gfc_array_index_type, partial,
7033 stmt_unpacked, stmt_packed);
7034 else
7035 tmp = (stmt_packed != NULL_TREE) ? stmt_packed : stmt_unpacked;
7036 gfc_add_modify (&init, stride, tmp);
7037 }
7038 }
7039 else
7040 {
7041 stride = GFC_TYPE_ARRAY_SIZE (type);
7042
7043 if (stride && !INTEGER_CST_P (stride))
7044 {
7045 /* Calculate size = stride * (ubound + 1 - lbound). */
7046 tmp = fold_build2_loc (input_location, MINUS_EXPR,
7047 gfc_array_index_type,
7048 gfc_index_one_node, lbound);
7049 tmp = fold_build2_loc (input_location, PLUS_EXPR,
7050 gfc_array_index_type,
7051 ubound, tmp);
7052 tmp = fold_build2_loc (input_location, MULT_EXPR,
7053 gfc_array_index_type,
7054 GFC_TYPE_ARRAY_STRIDE (type, n), tmp);
7055 gfc_add_modify (&init, stride, tmp);
7056 }
7057 }
7058 }
7059
7060 gfc_trans_array_cobounds (type, &init, sym);
7061
7062 /* Set the offset. */
7063 if (VAR_P (GFC_TYPE_ARRAY_OFFSET (type)))
7064 gfc_add_modify (&init, GFC_TYPE_ARRAY_OFFSET (type), offset);
7065
7066 gfc_trans_vla_type_sizes (sym, &init);
7067
7068 stmtInit = gfc_finish_block (&init);
7069
7070 /* Only do the entry/initialization code if the arg is present. */
7071 dumdesc = GFC_DECL_SAVED_DESCRIPTOR (tmpdesc);
7072 optional_arg = (sym->attr.optional
7073 || (sym->ns->proc_name->attr.entry_master
7074 && sym->attr.dummy));
7075 if (optional_arg)
7076 {
7077 tree zero_init = fold_convert (TREE_TYPE (tmpdesc), null_pointer_node);
7078 zero_init = fold_build2_loc (input_location, MODIFY_EXPR, void_type_node,
7079 tmpdesc, zero_init);
7080 tmp = gfc_conv_expr_present (sym, true);
7081 stmtInit = build3_v (COND_EXPR, tmp, stmtInit, zero_init);
7082 }
7083
7084 /* Cleanup code. */
7085 if (no_repack)
7086 stmtCleanup = NULL_TREE;
7087 else
7088 {
7089 stmtblock_t cleanup;
7090 gfc_start_block (&cleanup);
7091
7092 if (sym->attr.intent != INTENT_IN)
7093 {
7094 /* Copy the data back. */
7095 tmp = build_call_expr_loc (input_location,
7096 gfor_fndecl_in_unpack, 2, dumdesc, tmpdesc);
7097 gfc_add_expr_to_block (&cleanup, tmp);
7098 }
7099
7100 /* Free the temporary. */
7101 tmp = gfc_call_free (tmpdesc);
7102 gfc_add_expr_to_block (&cleanup, tmp);
7103
7104 stmtCleanup = gfc_finish_block (&cleanup);
7105
7106 /* Only do the cleanup if the array was repacked. */
7107 if (is_classarray)
7108 /* For a class array the dummy array descriptor is in the _class
7109 component. */
7110 tmp = gfc_class_data_get (dumdesc);
7111 else
7112 tmp = build_fold_indirect_ref_loc (input_location, dumdesc);
7113 tmp = gfc_conv_descriptor_data_get (tmp);
7114 tmp = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
7115 tmp, tmpdesc);
7116 stmtCleanup = build3_v (COND_EXPR, tmp, stmtCleanup,
7117 build_empty_stmt (input_location));
7118
7119 if (optional_arg)
7120 {
7121 tmp = gfc_conv_expr_present (sym);
7122 stmtCleanup = build3_v (COND_EXPR, tmp, stmtCleanup,
7123 build_empty_stmt (input_location));
7124 }
7125 }
7126
7127 /* We don't need to free any memory allocated by internal_pack as it will
7128 be freed at the end of the function by pop_context. */
7129 gfc_add_init_cleanup (block, stmtInit, stmtCleanup);
7130
7131 gfc_restore_backend_locus (&loc);
7132 }
7133
7134
7135 /* Calculate the overall offset, including subreferences. */
7136 void
gfc_get_dataptr_offset(stmtblock_t * block,tree parm,tree desc,tree offset,bool subref,gfc_expr * expr)7137 gfc_get_dataptr_offset (stmtblock_t *block, tree parm, tree desc, tree offset,
7138 bool subref, gfc_expr *expr)
7139 {
7140 tree tmp;
7141 tree field;
7142 tree stride;
7143 tree index;
7144 gfc_ref *ref;
7145 gfc_se start;
7146 int n;
7147
7148 /* If offset is NULL and this is not a subreferenced array, there is
7149 nothing to do. */
7150 if (offset == NULL_TREE)
7151 {
7152 if (subref)
7153 offset = gfc_index_zero_node;
7154 else
7155 return;
7156 }
7157
7158 tmp = build_array_ref (desc, offset, NULL, NULL);
7159
7160 /* Offset the data pointer for pointer assignments from arrays with
7161 subreferences; e.g. my_integer => my_type(:)%integer_component. */
7162 if (subref)
7163 {
7164 /* Go past the array reference. */
7165 for (ref = expr->ref; ref; ref = ref->next)
7166 if (ref->type == REF_ARRAY &&
7167 ref->u.ar.type != AR_ELEMENT)
7168 {
7169 ref = ref->next;
7170 break;
7171 }
7172
7173 /* Calculate the offset for each subsequent subreference. */
7174 for (; ref; ref = ref->next)
7175 {
7176 switch (ref->type)
7177 {
7178 case REF_COMPONENT:
7179 field = ref->u.c.component->backend_decl;
7180 gcc_assert (field && TREE_CODE (field) == FIELD_DECL);
7181 tmp = fold_build3_loc (input_location, COMPONENT_REF,
7182 TREE_TYPE (field),
7183 tmp, field, NULL_TREE);
7184 break;
7185
7186 case REF_SUBSTRING:
7187 gcc_assert (TREE_CODE (TREE_TYPE (tmp)) == ARRAY_TYPE);
7188 gfc_init_se (&start, NULL);
7189 gfc_conv_expr_type (&start, ref->u.ss.start, gfc_charlen_type_node);
7190 gfc_add_block_to_block (block, &start.pre);
7191 tmp = gfc_build_array_ref (tmp, start.expr, NULL);
7192 break;
7193
7194 case REF_ARRAY:
7195 gcc_assert (TREE_CODE (TREE_TYPE (tmp)) == ARRAY_TYPE
7196 && ref->u.ar.type == AR_ELEMENT);
7197
7198 /* TODO - Add bounds checking. */
7199 stride = gfc_index_one_node;
7200 index = gfc_index_zero_node;
7201 for (n = 0; n < ref->u.ar.dimen; n++)
7202 {
7203 tree itmp;
7204 tree jtmp;
7205
7206 /* Update the index. */
7207 gfc_init_se (&start, NULL);
7208 gfc_conv_expr_type (&start, ref->u.ar.start[n], gfc_array_index_type);
7209 itmp = gfc_evaluate_now (start.expr, block);
7210 gfc_init_se (&start, NULL);
7211 gfc_conv_expr_type (&start, ref->u.ar.as->lower[n], gfc_array_index_type);
7212 jtmp = gfc_evaluate_now (start.expr, block);
7213 itmp = fold_build2_loc (input_location, MINUS_EXPR,
7214 gfc_array_index_type, itmp, jtmp);
7215 itmp = fold_build2_loc (input_location, MULT_EXPR,
7216 gfc_array_index_type, itmp, stride);
7217 index = fold_build2_loc (input_location, PLUS_EXPR,
7218 gfc_array_index_type, itmp, index);
7219 index = gfc_evaluate_now (index, block);
7220
7221 /* Update the stride. */
7222 gfc_init_se (&start, NULL);
7223 gfc_conv_expr_type (&start, ref->u.ar.as->upper[n], gfc_array_index_type);
7224 itmp = fold_build2_loc (input_location, MINUS_EXPR,
7225 gfc_array_index_type, start.expr,
7226 jtmp);
7227 itmp = fold_build2_loc (input_location, PLUS_EXPR,
7228 gfc_array_index_type,
7229 gfc_index_one_node, itmp);
7230 stride = fold_build2_loc (input_location, MULT_EXPR,
7231 gfc_array_index_type, stride, itmp);
7232 stride = gfc_evaluate_now (stride, block);
7233 }
7234
7235 /* Apply the index to obtain the array element. */
7236 tmp = gfc_build_array_ref (tmp, index, NULL);
7237 break;
7238
7239 case REF_INQUIRY:
7240 switch (ref->u.i)
7241 {
7242 case INQUIRY_RE:
7243 tmp = fold_build1_loc (input_location, REALPART_EXPR,
7244 TREE_TYPE (TREE_TYPE (tmp)), tmp);
7245 break;
7246
7247 case INQUIRY_IM:
7248 tmp = fold_build1_loc (input_location, IMAGPART_EXPR,
7249 TREE_TYPE (TREE_TYPE (tmp)), tmp);
7250 break;
7251
7252 default:
7253 break;
7254 }
7255 break;
7256
7257 default:
7258 gcc_unreachable ();
7259 break;
7260 }
7261 }
7262 }
7263
7264 /* Set the target data pointer. */
7265 offset = gfc_build_addr_expr (gfc_array_dataptr_type (desc), tmp);
7266 gfc_conv_descriptor_data_set (block, parm, offset);
7267 }
7268
7269
7270 /* gfc_conv_expr_descriptor needs the string length an expression
7271 so that the size of the temporary can be obtained. This is done
7272 by adding up the string lengths of all the elements in the
7273 expression. Function with non-constant expressions have their
7274 string lengths mapped onto the actual arguments using the
7275 interface mapping machinery in trans-expr.cc. */
7276 static void
get_array_charlen(gfc_expr * expr,gfc_se * se)7277 get_array_charlen (gfc_expr *expr, gfc_se *se)
7278 {
7279 gfc_interface_mapping mapping;
7280 gfc_formal_arglist *formal;
7281 gfc_actual_arglist *arg;
7282 gfc_se tse;
7283 gfc_expr *e;
7284
7285 if (expr->ts.u.cl->length
7286 && gfc_is_constant_expr (expr->ts.u.cl->length))
7287 {
7288 if (!expr->ts.u.cl->backend_decl)
7289 gfc_conv_string_length (expr->ts.u.cl, expr, &se->pre);
7290 return;
7291 }
7292
7293 switch (expr->expr_type)
7294 {
7295 case EXPR_ARRAY:
7296
7297 /* This is somewhat brutal. The expression for the first
7298 element of the array is evaluated and assigned to a
7299 new string length for the original expression. */
7300 e = gfc_constructor_first (expr->value.constructor)->expr;
7301
7302 gfc_init_se (&tse, NULL);
7303
7304 /* Avoid evaluating trailing array references since all we need is
7305 the string length. */
7306 if (e->rank)
7307 tse.descriptor_only = 1;
7308 if (e->rank && e->expr_type != EXPR_VARIABLE)
7309 gfc_conv_expr_descriptor (&tse, e);
7310 else
7311 gfc_conv_expr (&tse, e);
7312
7313 gfc_add_block_to_block (&se->pre, &tse.pre);
7314 gfc_add_block_to_block (&se->post, &tse.post);
7315
7316 if (!expr->ts.u.cl->backend_decl || !VAR_P (expr->ts.u.cl->backend_decl))
7317 {
7318 expr->ts.u.cl = gfc_new_charlen (gfc_current_ns, NULL);
7319 expr->ts.u.cl->backend_decl =
7320 gfc_create_var (gfc_charlen_type_node, "sln");
7321 }
7322
7323 gfc_add_modify (&se->pre, expr->ts.u.cl->backend_decl,
7324 tse.string_length);
7325
7326 /* Make sure that deferred length components point to the hidden
7327 string_length component. */
7328 if (TREE_CODE (tse.expr) == COMPONENT_REF
7329 && TREE_CODE (tse.string_length) == COMPONENT_REF
7330 && TREE_OPERAND (tse.expr, 0) == TREE_OPERAND (tse.string_length, 0))
7331 e->ts.u.cl->backend_decl = expr->ts.u.cl->backend_decl;
7332
7333 return;
7334
7335 case EXPR_OP:
7336 get_array_charlen (expr->value.op.op1, se);
7337
7338 /* For parentheses the expression ts.u.cl should be identical. */
7339 if (expr->value.op.op == INTRINSIC_PARENTHESES)
7340 {
7341 if (expr->value.op.op1->ts.u.cl != expr->ts.u.cl)
7342 expr->ts.u.cl->backend_decl
7343 = expr->value.op.op1->ts.u.cl->backend_decl;
7344 return;
7345 }
7346
7347 expr->ts.u.cl->backend_decl =
7348 gfc_create_var (gfc_charlen_type_node, "sln");
7349
7350 if (expr->value.op.op2)
7351 {
7352 get_array_charlen (expr->value.op.op2, se);
7353
7354 gcc_assert (expr->value.op.op == INTRINSIC_CONCAT);
7355
7356 /* Add the string lengths and assign them to the expression
7357 string length backend declaration. */
7358 gfc_add_modify (&se->pre, expr->ts.u.cl->backend_decl,
7359 fold_build2_loc (input_location, PLUS_EXPR,
7360 gfc_charlen_type_node,
7361 expr->value.op.op1->ts.u.cl->backend_decl,
7362 expr->value.op.op2->ts.u.cl->backend_decl));
7363 }
7364 else
7365 gfc_add_modify (&se->pre, expr->ts.u.cl->backend_decl,
7366 expr->value.op.op1->ts.u.cl->backend_decl);
7367 break;
7368
7369 case EXPR_FUNCTION:
7370 if (expr->value.function.esym == NULL
7371 || expr->ts.u.cl->length->expr_type == EXPR_CONSTANT)
7372 {
7373 gfc_conv_string_length (expr->ts.u.cl, expr, &se->pre);
7374 break;
7375 }
7376
7377 /* Map expressions involving the dummy arguments onto the actual
7378 argument expressions. */
7379 gfc_init_interface_mapping (&mapping);
7380 formal = gfc_sym_get_dummy_args (expr->symtree->n.sym);
7381 arg = expr->value.function.actual;
7382
7383 /* Set se = NULL in the calls to the interface mapping, to suppress any
7384 backend stuff. */
7385 for (; arg != NULL; arg = arg->next, formal = formal ? formal->next : NULL)
7386 {
7387 if (!arg->expr)
7388 continue;
7389 if (formal->sym)
7390 gfc_add_interface_mapping (&mapping, formal->sym, NULL, arg->expr);
7391 }
7392
7393 gfc_init_se (&tse, NULL);
7394
7395 /* Build the expression for the character length and convert it. */
7396 gfc_apply_interface_mapping (&mapping, &tse, expr->ts.u.cl->length);
7397
7398 gfc_add_block_to_block (&se->pre, &tse.pre);
7399 gfc_add_block_to_block (&se->post, &tse.post);
7400 tse.expr = fold_convert (gfc_charlen_type_node, tse.expr);
7401 tse.expr = fold_build2_loc (input_location, MAX_EXPR,
7402 TREE_TYPE (tse.expr), tse.expr,
7403 build_zero_cst (TREE_TYPE (tse.expr)));
7404 expr->ts.u.cl->backend_decl = tse.expr;
7405 gfc_free_interface_mapping (&mapping);
7406 break;
7407
7408 default:
7409 gfc_conv_string_length (expr->ts.u.cl, expr, &se->pre);
7410 break;
7411 }
7412 }
7413
7414
7415 /* Helper function to check dimensions. */
7416 static bool
transposed_dims(gfc_ss * ss)7417 transposed_dims (gfc_ss *ss)
7418 {
7419 int n;
7420
7421 for (n = 0; n < ss->dimen; n++)
7422 if (ss->dim[n] != n)
7423 return true;
7424 return false;
7425 }
7426
7427
7428 /* Convert the last ref of a scalar coarray from an AR_ELEMENT to an
7429 AR_FULL, suitable for the scalarizer. */
7430
7431 static gfc_ss *
walk_coarray(gfc_expr * e)7432 walk_coarray (gfc_expr *e)
7433 {
7434 gfc_ss *ss;
7435
7436 gcc_assert (gfc_get_corank (e) > 0);
7437
7438 ss = gfc_walk_expr (e);
7439
7440 /* Fix scalar coarray. */
7441 if (ss == gfc_ss_terminator)
7442 {
7443 gfc_ref *ref;
7444
7445 ref = e->ref;
7446 while (ref)
7447 {
7448 if (ref->type == REF_ARRAY
7449 && ref->u.ar.codimen > 0)
7450 break;
7451
7452 ref = ref->next;
7453 }
7454
7455 gcc_assert (ref != NULL);
7456 if (ref->u.ar.type == AR_ELEMENT)
7457 ref->u.ar.type = AR_SECTION;
7458 ss = gfc_reverse_ss (gfc_walk_array_ref (ss, e, ref));
7459 }
7460
7461 return ss;
7462 }
7463
7464
7465 /* Convert an array for passing as an actual argument. Expressions and
7466 vector subscripts are evaluated and stored in a temporary, which is then
7467 passed. For whole arrays the descriptor is passed. For array sections
7468 a modified copy of the descriptor is passed, but using the original data.
7469
7470 This function is also used for array pointer assignments, and there
7471 are three cases:
7472
7473 - se->want_pointer && !se->direct_byref
7474 EXPR is an actual argument. On exit, se->expr contains a
7475 pointer to the array descriptor.
7476
7477 - !se->want_pointer && !se->direct_byref
7478 EXPR is an actual argument to an intrinsic function or the
7479 left-hand side of a pointer assignment. On exit, se->expr
7480 contains the descriptor for EXPR.
7481
7482 - !se->want_pointer && se->direct_byref
7483 EXPR is the right-hand side of a pointer assignment and
7484 se->expr is the descriptor for the previously-evaluated
7485 left-hand side. The function creates an assignment from
7486 EXPR to se->expr.
7487
7488
7489 The se->force_tmp flag disables the non-copying descriptor optimization
7490 that is used for transpose. It may be used in cases where there is an
7491 alias between the transpose argument and another argument in the same
7492 function call. */
7493
7494 void
gfc_conv_expr_descriptor(gfc_se * se,gfc_expr * expr)7495 gfc_conv_expr_descriptor (gfc_se *se, gfc_expr *expr)
7496 {
7497 gfc_ss *ss;
7498 gfc_ss_type ss_type;
7499 gfc_ss_info *ss_info;
7500 gfc_loopinfo loop;
7501 gfc_array_info *info;
7502 int need_tmp;
7503 int n;
7504 tree tmp;
7505 tree desc;
7506 stmtblock_t block;
7507 tree start;
7508 int full;
7509 bool subref_array_target = false;
7510 bool deferred_array_component = false;
7511 gfc_expr *arg, *ss_expr;
7512
7513 if (se->want_coarray)
7514 ss = walk_coarray (expr);
7515 else
7516 ss = gfc_walk_expr (expr);
7517
7518 gcc_assert (ss != NULL);
7519 gcc_assert (ss != gfc_ss_terminator);
7520
7521 ss_info = ss->info;
7522 ss_type = ss_info->type;
7523 ss_expr = ss_info->expr;
7524
7525 /* Special case: TRANSPOSE which needs no temporary. */
7526 while (expr->expr_type == EXPR_FUNCTION && expr->value.function.isym
7527 && (arg = gfc_get_noncopying_intrinsic_argument (expr)) != NULL)
7528 {
7529 /* This is a call to transpose which has already been handled by the
7530 scalarizer, so that we just need to get its argument's descriptor. */
7531 gcc_assert (expr->value.function.isym->id == GFC_ISYM_TRANSPOSE);
7532 expr = expr->value.function.actual->expr;
7533 }
7534
7535 if (!se->direct_byref)
7536 se->unlimited_polymorphic = UNLIMITED_POLY (expr);
7537
7538 /* Special case things we know we can pass easily. */
7539 switch (expr->expr_type)
7540 {
7541 case EXPR_VARIABLE:
7542 /* If we have a linear array section, we can pass it directly.
7543 Otherwise we need to copy it into a temporary. */
7544
7545 gcc_assert (ss_type == GFC_SS_SECTION);
7546 gcc_assert (ss_expr == expr);
7547 info = &ss_info->data.array;
7548
7549 /* Get the descriptor for the array. */
7550 gfc_conv_ss_descriptor (&se->pre, ss, 0);
7551 desc = info->descriptor;
7552
7553 /* The charlen backend decl for deferred character components cannot
7554 be used because it is fixed at zero. Instead, the hidden string
7555 length component is used. */
7556 if (expr->ts.type == BT_CHARACTER
7557 && expr->ts.deferred
7558 && TREE_CODE (desc) == COMPONENT_REF)
7559 deferred_array_component = true;
7560
7561 subref_array_target = (is_subref_array (expr)
7562 && (se->direct_byref
7563 || expr->ts.type == BT_CHARACTER));
7564 need_tmp = (gfc_ref_needs_temporary_p (expr->ref)
7565 && !subref_array_target);
7566
7567 if (se->force_tmp)
7568 need_tmp = 1;
7569 else if (se->force_no_tmp)
7570 need_tmp = 0;
7571
7572 if (need_tmp)
7573 full = 0;
7574 else if (GFC_ARRAY_TYPE_P (TREE_TYPE (desc)))
7575 {
7576 /* Create a new descriptor if the array doesn't have one. */
7577 full = 0;
7578 }
7579 else if (info->ref->u.ar.type == AR_FULL || se->descriptor_only)
7580 full = 1;
7581 else if (se->direct_byref)
7582 full = 0;
7583 else if (info->ref->u.ar.dimen == 0 && !info->ref->next)
7584 full = 1;
7585 else if (info->ref->u.ar.type == AR_SECTION && se->want_pointer)
7586 full = 0;
7587 else
7588 full = gfc_full_array_ref_p (info->ref, NULL);
7589
7590 if (full && !transposed_dims (ss))
7591 {
7592 if (se->direct_byref && !se->byref_noassign)
7593 {
7594 /* Copy the descriptor for pointer assignments. */
7595 gfc_add_modify (&se->pre, se->expr, desc);
7596
7597 /* Add any offsets from subreferences. */
7598 gfc_get_dataptr_offset (&se->pre, se->expr, desc, NULL_TREE,
7599 subref_array_target, expr);
7600
7601 /* ....and set the span field. */
7602 tmp = gfc_conv_descriptor_span_get (desc);
7603 gfc_conv_descriptor_span_set (&se->pre, se->expr, tmp);
7604 }
7605 else if (se->want_pointer)
7606 {
7607 /* We pass full arrays directly. This means that pointers and
7608 allocatable arrays should also work. */
7609 se->expr = gfc_build_addr_expr (NULL_TREE, desc);
7610 }
7611 else
7612 {
7613 se->expr = desc;
7614 }
7615
7616 if (expr->ts.type == BT_CHARACTER && !deferred_array_component)
7617 se->string_length = gfc_get_expr_charlen (expr);
7618 /* The ss_info string length is returned set to the value of the
7619 hidden string length component. */
7620 else if (deferred_array_component)
7621 se->string_length = ss_info->string_length;
7622
7623 gfc_free_ss_chain (ss);
7624 return;
7625 }
7626 break;
7627
7628 case EXPR_FUNCTION:
7629 /* A transformational function return value will be a temporary
7630 array descriptor. We still need to go through the scalarizer
7631 to create the descriptor. Elemental functions are handled as
7632 arbitrary expressions, i.e. copy to a temporary. */
7633
7634 if (se->direct_byref)
7635 {
7636 gcc_assert (ss_type == GFC_SS_FUNCTION && ss_expr == expr);
7637
7638 /* For pointer assignments pass the descriptor directly. */
7639 if (se->ss == NULL)
7640 se->ss = ss;
7641 else
7642 gcc_assert (se->ss == ss);
7643
7644 if (!is_pointer_array (se->expr))
7645 {
7646 tmp = gfc_get_element_type (TREE_TYPE (se->expr));
7647 tmp = fold_convert (gfc_array_index_type,
7648 size_in_bytes (tmp));
7649 gfc_conv_descriptor_span_set (&se->pre, se->expr, tmp);
7650 }
7651
7652 se->expr = gfc_build_addr_expr (NULL_TREE, se->expr);
7653 gfc_conv_expr (se, expr);
7654
7655 gfc_free_ss_chain (ss);
7656 return;
7657 }
7658
7659 if (ss_expr != expr || ss_type != GFC_SS_FUNCTION)
7660 {
7661 if (ss_expr != expr)
7662 /* Elemental function. */
7663 gcc_assert ((expr->value.function.esym != NULL
7664 && expr->value.function.esym->attr.elemental)
7665 || (expr->value.function.isym != NULL
7666 && expr->value.function.isym->elemental)
7667 || (gfc_expr_attr (expr).proc_pointer
7668 && gfc_expr_attr (expr).elemental)
7669 || gfc_inline_intrinsic_function_p (expr));
7670
7671 need_tmp = 1;
7672 if (expr->ts.type == BT_CHARACTER
7673 && expr->ts.u.cl->length->expr_type != EXPR_CONSTANT)
7674 get_array_charlen (expr, se);
7675
7676 info = NULL;
7677 }
7678 else
7679 {
7680 /* Transformational function. */
7681 info = &ss_info->data.array;
7682 need_tmp = 0;
7683 }
7684 break;
7685
7686 case EXPR_ARRAY:
7687 /* Constant array constructors don't need a temporary. */
7688 if (ss_type == GFC_SS_CONSTRUCTOR
7689 && expr->ts.type != BT_CHARACTER
7690 && gfc_constant_array_constructor_p (expr->value.constructor))
7691 {
7692 need_tmp = 0;
7693 info = &ss_info->data.array;
7694 }
7695 else
7696 {
7697 need_tmp = 1;
7698 info = NULL;
7699 }
7700 break;
7701
7702 default:
7703 /* Something complicated. Copy it into a temporary. */
7704 need_tmp = 1;
7705 info = NULL;
7706 break;
7707 }
7708
7709 /* If we are creating a temporary, we don't need to bother about aliases
7710 anymore. */
7711 if (need_tmp)
7712 se->force_tmp = 0;
7713
7714 gfc_init_loopinfo (&loop);
7715
7716 /* Associate the SS with the loop. */
7717 gfc_add_ss_to_loop (&loop, ss);
7718
7719 /* Tell the scalarizer not to bother creating loop variables, etc. */
7720 if (!need_tmp)
7721 loop.array_parameter = 1;
7722 else
7723 /* The right-hand side of a pointer assignment mustn't use a temporary. */
7724 gcc_assert (!se->direct_byref);
7725
7726 /* Do we need bounds checking or not? */
7727 ss->no_bounds_check = expr->no_bounds_check;
7728
7729 /* Setup the scalarizing loops and bounds. */
7730 gfc_conv_ss_startstride (&loop);
7731
7732 if (need_tmp)
7733 {
7734 if (expr->ts.type == BT_CHARACTER
7735 && (!expr->ts.u.cl->backend_decl || expr->expr_type == EXPR_ARRAY))
7736 get_array_charlen (expr, se);
7737
7738 /* Tell the scalarizer to make a temporary. */
7739 loop.temp_ss = gfc_get_temp_ss (gfc_typenode_for_spec (&expr->ts),
7740 ((expr->ts.type == BT_CHARACTER)
7741 ? expr->ts.u.cl->backend_decl
7742 : NULL),
7743 loop.dimen);
7744
7745 se->string_length = loop.temp_ss->info->string_length;
7746 gcc_assert (loop.temp_ss->dimen == loop.dimen);
7747 gfc_add_ss_to_loop (&loop, loop.temp_ss);
7748 }
7749
7750 gfc_conv_loop_setup (&loop, & expr->where);
7751
7752 if (need_tmp)
7753 {
7754 /* Copy into a temporary and pass that. We don't need to copy the data
7755 back because expressions and vector subscripts must be INTENT_IN. */
7756 /* TODO: Optimize passing function return values. */
7757 gfc_se lse;
7758 gfc_se rse;
7759 bool deep_copy;
7760
7761 /* Start the copying loops. */
7762 gfc_mark_ss_chain_used (loop.temp_ss, 1);
7763 gfc_mark_ss_chain_used (ss, 1);
7764 gfc_start_scalarized_body (&loop, &block);
7765
7766 /* Copy each data element. */
7767 gfc_init_se (&lse, NULL);
7768 gfc_copy_loopinfo_to_se (&lse, &loop);
7769 gfc_init_se (&rse, NULL);
7770 gfc_copy_loopinfo_to_se (&rse, &loop);
7771
7772 lse.ss = loop.temp_ss;
7773 rse.ss = ss;
7774
7775 gfc_conv_tmp_array_ref (&lse);
7776 if (expr->ts.type == BT_CHARACTER)
7777 {
7778 gfc_conv_expr (&rse, expr);
7779 if (POINTER_TYPE_P (TREE_TYPE (rse.expr)))
7780 rse.expr = build_fold_indirect_ref_loc (input_location,
7781 rse.expr);
7782 }
7783 else
7784 gfc_conv_expr_val (&rse, expr);
7785
7786 gfc_add_block_to_block (&block, &rse.pre);
7787 gfc_add_block_to_block (&block, &lse.pre);
7788
7789 lse.string_length = rse.string_length;
7790
7791 deep_copy = !se->data_not_needed
7792 && (expr->expr_type == EXPR_VARIABLE
7793 || expr->expr_type == EXPR_ARRAY);
7794 tmp = gfc_trans_scalar_assign (&lse, &rse, expr->ts,
7795 deep_copy, false);
7796 gfc_add_expr_to_block (&block, tmp);
7797
7798 /* Finish the copying loops. */
7799 gfc_trans_scalarizing_loops (&loop, &block);
7800
7801 desc = loop.temp_ss->info->data.array.descriptor;
7802 }
7803 else if (expr->expr_type == EXPR_FUNCTION && !transposed_dims (ss))
7804 {
7805 desc = info->descriptor;
7806 se->string_length = ss_info->string_length;
7807 }
7808 else
7809 {
7810 /* We pass sections without copying to a temporary. Make a new
7811 descriptor and point it at the section we want. The loop variable
7812 limits will be the limits of the section.
7813 A function may decide to repack the array to speed up access, but
7814 we're not bothered about that here. */
7815 int dim, ndim, codim;
7816 tree parm;
7817 tree parmtype;
7818 tree dtype;
7819 tree stride;
7820 tree from;
7821 tree to;
7822 tree base;
7823 tree offset;
7824
7825 ndim = info->ref ? info->ref->u.ar.dimen : ss->dimen;
7826
7827 if (se->want_coarray)
7828 {
7829 gfc_array_ref *ar = &info->ref->u.ar;
7830
7831 codim = gfc_get_corank (expr);
7832 for (n = 0; n < codim - 1; n++)
7833 {
7834 /* Make sure we are not lost somehow. */
7835 gcc_assert (ar->dimen_type[n + ndim] == DIMEN_THIS_IMAGE);
7836
7837 /* Make sure the call to gfc_conv_section_startstride won't
7838 generate unnecessary code to calculate stride. */
7839 gcc_assert (ar->stride[n + ndim] == NULL);
7840
7841 gfc_conv_section_startstride (&loop.pre, ss, n + ndim);
7842 loop.from[n + loop.dimen] = info->start[n + ndim];
7843 loop.to[n + loop.dimen] = info->end[n + ndim];
7844 }
7845
7846 gcc_assert (n == codim - 1);
7847 evaluate_bound (&loop.pre, info->start, ar->start,
7848 info->descriptor, n + ndim, true,
7849 ar->as->type == AS_DEFERRED);
7850 loop.from[n + loop.dimen] = info->start[n + ndim];
7851 }
7852 else
7853 codim = 0;
7854
7855 /* Set the string_length for a character array. */
7856 if (expr->ts.type == BT_CHARACTER)
7857 {
7858 if (deferred_array_component)
7859 se->string_length = ss_info->string_length;
7860 else
7861 se->string_length = gfc_get_expr_charlen (expr);
7862
7863 if (VAR_P (se->string_length)
7864 && expr->ts.u.cl->backend_decl == se->string_length)
7865 tmp = ss_info->string_length;
7866 else
7867 tmp = se->string_length;
7868
7869 if (expr->ts.deferred && VAR_P (expr->ts.u.cl->backend_decl))
7870 gfc_add_modify (&se->pre, expr->ts.u.cl->backend_decl, tmp);
7871 else
7872 expr->ts.u.cl->backend_decl = tmp;
7873 }
7874
7875 /* If we have an array section, are assigning or passing an array
7876 section argument make sure that the lower bound is 1. References
7877 to the full array should otherwise keep the original bounds. */
7878 if (!info->ref || info->ref->u.ar.type != AR_FULL)
7879 for (dim = 0; dim < loop.dimen; dim++)
7880 if (!integer_onep (loop.from[dim]))
7881 {
7882 tmp = fold_build2_loc (input_location, MINUS_EXPR,
7883 gfc_array_index_type, gfc_index_one_node,
7884 loop.from[dim]);
7885 loop.to[dim] = fold_build2_loc (input_location, PLUS_EXPR,
7886 gfc_array_index_type,
7887 loop.to[dim], tmp);
7888 loop.from[dim] = gfc_index_one_node;
7889 }
7890
7891 desc = info->descriptor;
7892 if (se->direct_byref && !se->byref_noassign)
7893 {
7894 /* For pointer assignments we fill in the destination. */
7895 parm = se->expr;
7896 parmtype = TREE_TYPE (parm);
7897 }
7898 else
7899 {
7900 /* Otherwise make a new one. */
7901 if (expr->ts.type == BT_CHARACTER)
7902 parmtype = gfc_typenode_for_spec (&expr->ts);
7903 else
7904 parmtype = gfc_get_element_type (TREE_TYPE (desc));
7905
7906 parmtype = gfc_get_array_type_bounds (parmtype, loop.dimen, codim,
7907 loop.from, loop.to, 0,
7908 GFC_ARRAY_UNKNOWN, false);
7909 parm = gfc_create_var (parmtype, "parm");
7910
7911 /* When expression is a class object, then add the class' handle to
7912 the parm_decl. */
7913 if (expr->ts.type == BT_CLASS && expr->expr_type == EXPR_VARIABLE)
7914 {
7915 gfc_expr *class_expr = gfc_find_and_cut_at_last_class_ref (expr);
7916 gfc_se classse;
7917
7918 /* class_expr can be NULL, when no _class ref is in expr.
7919 We must not fix this here with a gfc_fix_class_ref (). */
7920 if (class_expr)
7921 {
7922 gfc_init_se (&classse, NULL);
7923 gfc_conv_expr (&classse, class_expr);
7924 gfc_free_expr (class_expr);
7925
7926 gcc_assert (classse.pre.head == NULL_TREE
7927 && classse.post.head == NULL_TREE);
7928 gfc_allocate_lang_decl (parm);
7929 GFC_DECL_SAVED_DESCRIPTOR (parm) = classse.expr;
7930 }
7931 }
7932 }
7933
7934 /* Set the span field. */
7935 tmp = gfc_get_array_span (desc, expr);
7936 if (tmp)
7937 gfc_conv_descriptor_span_set (&loop.pre, parm, tmp);
7938
7939 /* The following can be somewhat confusing. We have two
7940 descriptors, a new one and the original array.
7941 {parm, parmtype, dim} refer to the new one.
7942 {desc, type, n, loop} refer to the original, which maybe
7943 a descriptorless array.
7944 The bounds of the scalarization are the bounds of the section.
7945 We don't have to worry about numeric overflows when calculating
7946 the offsets because all elements are within the array data. */
7947
7948 /* Set the dtype. */
7949 tmp = gfc_conv_descriptor_dtype (parm);
7950 if (se->unlimited_polymorphic)
7951 dtype = gfc_get_dtype (TREE_TYPE (desc), &loop.dimen);
7952 else if (expr->ts.type == BT_ASSUMED)
7953 {
7954 tree tmp2 = desc;
7955 if (DECL_LANG_SPECIFIC (tmp2) && GFC_DECL_SAVED_DESCRIPTOR (tmp2))
7956 tmp2 = GFC_DECL_SAVED_DESCRIPTOR (tmp2);
7957 if (POINTER_TYPE_P (TREE_TYPE (tmp2)))
7958 tmp2 = build_fold_indirect_ref_loc (input_location, tmp2);
7959 dtype = gfc_conv_descriptor_dtype (tmp2);
7960 }
7961 else
7962 dtype = gfc_get_dtype (parmtype);
7963 gfc_add_modify (&loop.pre, tmp, dtype);
7964
7965 /* The 1st element in the section. */
7966 base = gfc_index_zero_node;
7967
7968 /* The offset from the 1st element in the section. */
7969 offset = gfc_index_zero_node;
7970
7971 for (n = 0; n < ndim; n++)
7972 {
7973 stride = gfc_conv_array_stride (desc, n);
7974
7975 /* Work out the 1st element in the section. */
7976 if (info->ref
7977 && info->ref->u.ar.dimen_type[n] == DIMEN_ELEMENT)
7978 {
7979 gcc_assert (info->subscript[n]
7980 && info->subscript[n]->info->type == GFC_SS_SCALAR);
7981 start = info->subscript[n]->info->data.scalar.value;
7982 }
7983 else
7984 {
7985 /* Evaluate and remember the start of the section. */
7986 start = info->start[n];
7987 stride = gfc_evaluate_now (stride, &loop.pre);
7988 }
7989
7990 tmp = gfc_conv_array_lbound (desc, n);
7991 tmp = fold_build2_loc (input_location, MINUS_EXPR, TREE_TYPE (tmp),
7992 start, tmp);
7993 tmp = fold_build2_loc (input_location, MULT_EXPR, TREE_TYPE (tmp),
7994 tmp, stride);
7995 base = fold_build2_loc (input_location, PLUS_EXPR, TREE_TYPE (tmp),
7996 base, tmp);
7997
7998 if (info->ref
7999 && info->ref->u.ar.dimen_type[n] == DIMEN_ELEMENT)
8000 {
8001 /* For elemental dimensions, we only need the 1st
8002 element in the section. */
8003 continue;
8004 }
8005
8006 /* Vector subscripts need copying and are handled elsewhere. */
8007 if (info->ref)
8008 gcc_assert (info->ref->u.ar.dimen_type[n] == DIMEN_RANGE);
8009
8010 /* look for the corresponding scalarizer dimension: dim. */
8011 for (dim = 0; dim < ndim; dim++)
8012 if (ss->dim[dim] == n)
8013 break;
8014
8015 /* loop exited early: the DIM being looked for has been found. */
8016 gcc_assert (dim < ndim);
8017
8018 /* Set the new lower bound. */
8019 from = loop.from[dim];
8020 to = loop.to[dim];
8021
8022 gfc_conv_descriptor_lbound_set (&loop.pre, parm,
8023 gfc_rank_cst[dim], from);
8024
8025 /* Set the new upper bound. */
8026 gfc_conv_descriptor_ubound_set (&loop.pre, parm,
8027 gfc_rank_cst[dim], to);
8028
8029 /* Multiply the stride by the section stride to get the
8030 total stride. */
8031 stride = fold_build2_loc (input_location, MULT_EXPR,
8032 gfc_array_index_type,
8033 stride, info->stride[n]);
8034
8035 tmp = fold_build2_loc (input_location, MULT_EXPR,
8036 TREE_TYPE (offset), stride, from);
8037 offset = fold_build2_loc (input_location, MINUS_EXPR,
8038 TREE_TYPE (offset), offset, tmp);
8039
8040 /* Store the new stride. */
8041 gfc_conv_descriptor_stride_set (&loop.pre, parm,
8042 gfc_rank_cst[dim], stride);
8043 }
8044
8045 for (n = loop.dimen; n < loop.dimen + codim; n++)
8046 {
8047 from = loop.from[n];
8048 to = loop.to[n];
8049 gfc_conv_descriptor_lbound_set (&loop.pre, parm,
8050 gfc_rank_cst[n], from);
8051 if (n < loop.dimen + codim - 1)
8052 gfc_conv_descriptor_ubound_set (&loop.pre, parm,
8053 gfc_rank_cst[n], to);
8054 }
8055
8056 if (se->data_not_needed)
8057 gfc_conv_descriptor_data_set (&loop.pre, parm,
8058 gfc_index_zero_node);
8059 else
8060 /* Point the data pointer at the 1st element in the section. */
8061 gfc_get_dataptr_offset (&loop.pre, parm, desc, base,
8062 subref_array_target, expr);
8063
8064 gfc_conv_descriptor_offset_set (&loop.pre, parm, offset);
8065
8066 desc = parm;
8067 }
8068
8069 /* For class arrays add the class tree into the saved descriptor to
8070 enable getting of _vptr and the like. */
8071 if (expr->expr_type == EXPR_VARIABLE && VAR_P (desc)
8072 && IS_CLASS_ARRAY (expr->symtree->n.sym))
8073 {
8074 gfc_allocate_lang_decl (desc);
8075 GFC_DECL_SAVED_DESCRIPTOR (desc) =
8076 DECL_LANG_SPECIFIC (expr->symtree->n.sym->backend_decl) ?
8077 GFC_DECL_SAVED_DESCRIPTOR (expr->symtree->n.sym->backend_decl)
8078 : expr->symtree->n.sym->backend_decl;
8079 }
8080 else if (expr->expr_type == EXPR_ARRAY && VAR_P (desc)
8081 && IS_CLASS_ARRAY (expr))
8082 {
8083 tree vtype;
8084 gfc_allocate_lang_decl (desc);
8085 tmp = gfc_create_var (expr->ts.u.derived->backend_decl, "class");
8086 GFC_DECL_SAVED_DESCRIPTOR (desc) = tmp;
8087 vtype = gfc_class_vptr_get (tmp);
8088 gfc_add_modify (&se->pre, vtype,
8089 gfc_build_addr_expr (TREE_TYPE (vtype),
8090 gfc_find_vtab (&expr->ts)->backend_decl));
8091 }
8092 if (!se->direct_byref || se->byref_noassign)
8093 {
8094 /* Get a pointer to the new descriptor. */
8095 if (se->want_pointer)
8096 se->expr = gfc_build_addr_expr (NULL_TREE, desc);
8097 else
8098 se->expr = desc;
8099 }
8100
8101 gfc_add_block_to_block (&se->pre, &loop.pre);
8102 gfc_add_block_to_block (&se->post, &loop.post);
8103
8104 /* Cleanup the scalarizer. */
8105 gfc_cleanup_loop (&loop);
8106 }
8107
8108
8109 /* Calculate the array size (number of elements); if dim != NULL_TREE,
8110 return size for that dim (dim=0..rank-1; only for GFC_DESCRIPTOR_TYPE_P). */
8111 tree
gfc_tree_array_size(stmtblock_t * block,tree desc,gfc_expr * expr,tree dim)8112 gfc_tree_array_size (stmtblock_t *block, tree desc, gfc_expr *expr, tree dim)
8113 {
8114 if (GFC_ARRAY_TYPE_P (TREE_TYPE (desc)))
8115 {
8116 gcc_assert (dim == NULL_TREE);
8117 return GFC_TYPE_ARRAY_SIZE (TREE_TYPE (desc));
8118 }
8119 tree size, tmp, rank = NULL_TREE, cond = NULL_TREE;
8120 symbol_attribute attr = gfc_expr_attr (expr);
8121 gfc_array_spec *as = gfc_get_full_arrayspec_from_expr (expr);
8122 gcc_assert (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (desc)));
8123 if ((!attr.pointer && !attr.allocatable && as && as->type == AS_ASSUMED_RANK)
8124 || !dim)
8125 {
8126 if (expr->rank < 0)
8127 rank = fold_convert (signed_char_type_node,
8128 gfc_conv_descriptor_rank (desc));
8129 else
8130 rank = build_int_cst (signed_char_type_node, expr->rank);
8131 }
8132
8133 if (dim || expr->rank == 1)
8134 {
8135 if (!dim)
8136 dim = gfc_index_zero_node;
8137 tree ubound = gfc_conv_descriptor_ubound_get (desc, dim);
8138 tree lbound = gfc_conv_descriptor_lbound_get (desc, dim);
8139
8140 size = fold_build2_loc (input_location, MINUS_EXPR,
8141 gfc_array_index_type, ubound, lbound);
8142 size = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
8143 size, gfc_index_one_node);
8144 /* if (!allocatable && !pointer && assumed rank)
8145 size = (idx == rank && ubound[rank-1] == -1 ? -1 : size;
8146 else
8147 size = max (0, size); */
8148 size = fold_build2_loc (input_location, MAX_EXPR, gfc_array_index_type,
8149 size, gfc_index_zero_node);
8150 if (!attr.pointer && !attr.allocatable
8151 && as && as->type == AS_ASSUMED_RANK)
8152 {
8153 tmp = fold_build2_loc (input_location, MINUS_EXPR, signed_char_type_node,
8154 rank, build_int_cst (signed_char_type_node, 1));
8155 cond = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node,
8156 fold_convert (signed_char_type_node, dim),
8157 tmp);
8158 tmp = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node,
8159 gfc_conv_descriptor_ubound_get (desc, dim),
8160 build_int_cst (gfc_array_index_type, -1));
8161 cond = fold_build2_loc (input_location, TRUTH_AND_EXPR, boolean_type_node,
8162 cond, tmp);
8163 tmp = build_int_cst (gfc_array_index_type, -1);
8164 size = build3_loc (input_location, COND_EXPR, gfc_array_index_type,
8165 cond, tmp, size);
8166 }
8167 return size;
8168 }
8169
8170 /* size = 1. */
8171 size = gfc_create_var (gfc_array_index_type, "size");
8172 gfc_add_modify (block, size, build_int_cst (TREE_TYPE (size), 1));
8173 tree extent = gfc_create_var (gfc_array_index_type, "extent");
8174
8175 stmtblock_t cond_block, loop_body;
8176 gfc_init_block (&cond_block);
8177 gfc_init_block (&loop_body);
8178
8179 /* Loop: for (i = 0; i < rank; ++i). */
8180 tree idx = gfc_create_var (signed_char_type_node, "idx");
8181 /* Loop body. */
8182 /* #if (assumed-rank + !allocatable && !pointer)
8183 if (idx == rank - 1 && dim[idx].ubound == -1)
8184 extent = -1;
8185 else
8186 #endif
8187 extent = gfc->dim[i].ubound - gfc->dim[i].lbound + 1
8188 if (extent < 0)
8189 extent = 0
8190 size *= extent. */
8191 cond = NULL_TREE;
8192 if (!attr.pointer && !attr.allocatable && as && as->type == AS_ASSUMED_RANK)
8193 {
8194 tmp = fold_build2_loc (input_location, MINUS_EXPR, signed_char_type_node,
8195 rank, build_int_cst (signed_char_type_node, 1));
8196 cond = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node,
8197 idx, tmp);
8198 tmp = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node,
8199 gfc_conv_descriptor_ubound_get (desc, idx),
8200 build_int_cst (gfc_array_index_type, -1));
8201 cond = fold_build2_loc (input_location, TRUTH_AND_EXPR, boolean_type_node,
8202 cond, tmp);
8203 }
8204 tmp = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
8205 gfc_conv_descriptor_ubound_get (desc, idx),
8206 gfc_conv_descriptor_lbound_get (desc, idx));
8207 tmp = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
8208 tmp, gfc_index_one_node);
8209 gfc_add_modify (&cond_block, extent, tmp);
8210 tmp = fold_build2_loc (input_location, LT_EXPR, boolean_type_node,
8211 extent, gfc_index_zero_node);
8212 tmp = build3_v (COND_EXPR, tmp,
8213 fold_build2_loc (input_location, MODIFY_EXPR,
8214 gfc_array_index_type,
8215 extent, gfc_index_zero_node),
8216 build_empty_stmt (input_location));
8217 gfc_add_expr_to_block (&cond_block, tmp);
8218 tmp = gfc_finish_block (&cond_block);
8219 if (cond)
8220 tmp = build3_v (COND_EXPR, cond,
8221 fold_build2_loc (input_location, MODIFY_EXPR,
8222 gfc_array_index_type, extent,
8223 build_int_cst (gfc_array_index_type, -1)),
8224 tmp);
8225 gfc_add_expr_to_block (&loop_body, tmp);
8226 /* size *= extent. */
8227 gfc_add_modify (&loop_body, size,
8228 fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
8229 size, extent));
8230 /* Generate loop. */
8231 gfc_simple_for_loop (block, idx, build_int_cst (TREE_TYPE (idx), 0), rank, LT_EXPR,
8232 build_int_cst (TREE_TYPE (idx), 1),
8233 gfc_finish_block (&loop_body));
8234 return size;
8235 }
8236
8237 /* Helper function for gfc_conv_array_parameter if array size needs to be
8238 computed. */
8239
8240 static void
array_parameter_size(stmtblock_t * block,tree desc,gfc_expr * expr,tree * size)8241 array_parameter_size (stmtblock_t *block, tree desc, gfc_expr *expr, tree *size)
8242 {
8243 tree elem;
8244 *size = gfc_tree_array_size (block, desc, expr, NULL);
8245 elem = TYPE_SIZE_UNIT (gfc_get_element_type (TREE_TYPE (desc)));
8246 *size = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
8247 *size, fold_convert (gfc_array_index_type, elem));
8248 }
8249
8250 /* Helper function - return true if the argument is a pointer. */
8251
8252 static bool
is_pointer(gfc_expr * e)8253 is_pointer (gfc_expr *e)
8254 {
8255 gfc_symbol *sym;
8256
8257 if (e->expr_type != EXPR_VARIABLE || e->symtree == NULL)
8258 return false;
8259
8260 sym = e->symtree->n.sym;
8261 if (sym == NULL)
8262 return false;
8263
8264 return sym->attr.pointer || sym->attr.proc_pointer;
8265 }
8266
8267 /* Convert an array for passing as an actual parameter. */
8268
8269 void
gfc_conv_array_parameter(gfc_se * se,gfc_expr * expr,bool g77,const gfc_symbol * fsym,const char * proc_name,tree * size)8270 gfc_conv_array_parameter (gfc_se * se, gfc_expr * expr, bool g77,
8271 const gfc_symbol *fsym, const char *proc_name,
8272 tree *size)
8273 {
8274 tree ptr;
8275 tree desc;
8276 tree tmp = NULL_TREE;
8277 tree stmt;
8278 tree parent = DECL_CONTEXT (current_function_decl);
8279 bool full_array_var;
8280 bool this_array_result;
8281 bool contiguous;
8282 bool no_pack;
8283 bool array_constructor;
8284 bool good_allocatable;
8285 bool ultimate_ptr_comp;
8286 bool ultimate_alloc_comp;
8287 gfc_symbol *sym;
8288 stmtblock_t block;
8289 gfc_ref *ref;
8290
8291 ultimate_ptr_comp = false;
8292 ultimate_alloc_comp = false;
8293
8294 for (ref = expr->ref; ref; ref = ref->next)
8295 {
8296 if (ref->next == NULL)
8297 break;
8298
8299 if (ref->type == REF_COMPONENT)
8300 {
8301 ultimate_ptr_comp = ref->u.c.component->attr.pointer;
8302 ultimate_alloc_comp = ref->u.c.component->attr.allocatable;
8303 }
8304 }
8305
8306 full_array_var = false;
8307 contiguous = false;
8308
8309 if (expr->expr_type == EXPR_VARIABLE && ref && !ultimate_ptr_comp)
8310 full_array_var = gfc_full_array_ref_p (ref, &contiguous);
8311
8312 sym = full_array_var ? expr->symtree->n.sym : NULL;
8313
8314 /* The symbol should have an array specification. */
8315 gcc_assert (!sym || sym->as || ref->u.ar.as);
8316
8317 if (expr->expr_type == EXPR_ARRAY && expr->ts.type == BT_CHARACTER)
8318 {
8319 get_array_ctor_strlen (&se->pre, expr->value.constructor, &tmp);
8320 expr->ts.u.cl->backend_decl = tmp;
8321 se->string_length = tmp;
8322 }
8323
8324 /* Is this the result of the enclosing procedure? */
8325 this_array_result = (full_array_var && sym->attr.flavor == FL_PROCEDURE);
8326 if (this_array_result
8327 && (sym->backend_decl != current_function_decl)
8328 && (sym->backend_decl != parent))
8329 this_array_result = false;
8330
8331 /* Passing address of the array if it is not pointer or assumed-shape. */
8332 if (full_array_var && g77 && !this_array_result
8333 && sym->ts.type != BT_DERIVED && sym->ts.type != BT_CLASS)
8334 {
8335 tmp = gfc_get_symbol_decl (sym);
8336
8337 if (sym->ts.type == BT_CHARACTER)
8338 se->string_length = sym->ts.u.cl->backend_decl;
8339
8340 if (!sym->attr.pointer
8341 && sym->as
8342 && sym->as->type != AS_ASSUMED_SHAPE
8343 && sym->as->type != AS_DEFERRED
8344 && sym->as->type != AS_ASSUMED_RANK
8345 && !sym->attr.allocatable)
8346 {
8347 /* Some variables are declared directly, others are declared as
8348 pointers and allocated on the heap. */
8349 if (sym->attr.dummy || POINTER_TYPE_P (TREE_TYPE (tmp)))
8350 se->expr = tmp;
8351 else
8352 se->expr = gfc_build_addr_expr (NULL_TREE, tmp);
8353 if (size)
8354 array_parameter_size (&se->pre, tmp, expr, size);
8355 return;
8356 }
8357
8358 if (sym->attr.allocatable)
8359 {
8360 if (sym->attr.dummy || sym->attr.result)
8361 {
8362 gfc_conv_expr_descriptor (se, expr);
8363 tmp = se->expr;
8364 }
8365 if (size)
8366 array_parameter_size (&se->pre, tmp, expr, size);
8367 se->expr = gfc_conv_array_data (tmp);
8368 return;
8369 }
8370 }
8371
8372 /* A convenient reduction in scope. */
8373 contiguous = g77 && !this_array_result && contiguous;
8374
8375 /* There is no need to pack and unpack the array, if it is contiguous
8376 and not a deferred- or assumed-shape array, or if it is simply
8377 contiguous. */
8378 no_pack = ((sym && sym->as
8379 && !sym->attr.pointer
8380 && sym->as->type != AS_DEFERRED
8381 && sym->as->type != AS_ASSUMED_RANK
8382 && sym->as->type != AS_ASSUMED_SHAPE)
8383 ||
8384 (ref && ref->u.ar.as
8385 && ref->u.ar.as->type != AS_DEFERRED
8386 && ref->u.ar.as->type != AS_ASSUMED_RANK
8387 && ref->u.ar.as->type != AS_ASSUMED_SHAPE)
8388 ||
8389 gfc_is_simply_contiguous (expr, false, true));
8390
8391 no_pack = contiguous && no_pack;
8392
8393 /* If we have an EXPR_OP or a function returning an explicit-shaped
8394 or allocatable array, an array temporary will be generated which
8395 does not need to be packed / unpacked if passed to an
8396 explicit-shape dummy array. */
8397
8398 if (g77)
8399 {
8400 if (expr->expr_type == EXPR_OP)
8401 no_pack = 1;
8402 else if (expr->expr_type == EXPR_FUNCTION && expr->value.function.esym)
8403 {
8404 gfc_symbol *result = expr->value.function.esym->result;
8405 if (result->attr.dimension
8406 && (result->as->type == AS_EXPLICIT
8407 || result->attr.allocatable
8408 || result->attr.contiguous))
8409 no_pack = 1;
8410 }
8411 }
8412
8413 /* Array constructors are always contiguous and do not need packing. */
8414 array_constructor = g77 && !this_array_result && expr->expr_type == EXPR_ARRAY;
8415
8416 /* Same is true of contiguous sections from allocatable variables. */
8417 good_allocatable = contiguous
8418 && expr->symtree
8419 && expr->symtree->n.sym->attr.allocatable;
8420
8421 /* Or ultimate allocatable components. */
8422 ultimate_alloc_comp = contiguous && ultimate_alloc_comp;
8423
8424 if (no_pack || array_constructor || good_allocatable || ultimate_alloc_comp)
8425 {
8426 gfc_conv_expr_descriptor (se, expr);
8427 /* Deallocate the allocatable components of structures that are
8428 not variable. */
8429 if ((expr->ts.type == BT_DERIVED || expr->ts.type == BT_CLASS)
8430 && expr->ts.u.derived->attr.alloc_comp
8431 && expr->expr_type != EXPR_VARIABLE)
8432 {
8433 tmp = gfc_deallocate_alloc_comp (expr->ts.u.derived, se->expr, expr->rank);
8434
8435 /* The components shall be deallocated before their containing entity. */
8436 gfc_prepend_expr_to_block (&se->post, tmp);
8437 }
8438 if (expr->ts.type == BT_CHARACTER && expr->expr_type != EXPR_FUNCTION)
8439 se->string_length = expr->ts.u.cl->backend_decl;
8440 if (size)
8441 array_parameter_size (&se->pre, se->expr, expr, size);
8442 se->expr = gfc_conv_array_data (se->expr);
8443 return;
8444 }
8445
8446 if (this_array_result)
8447 {
8448 /* Result of the enclosing function. */
8449 gfc_conv_expr_descriptor (se, expr);
8450 if (size)
8451 array_parameter_size (&se->pre, se->expr, expr, size);
8452 se->expr = gfc_build_addr_expr (NULL_TREE, se->expr);
8453
8454 if (g77 && TREE_TYPE (TREE_TYPE (se->expr)) != NULL_TREE
8455 && GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (TREE_TYPE (se->expr))))
8456 se->expr = gfc_conv_array_data (build_fold_indirect_ref_loc (input_location,
8457 se->expr));
8458
8459 return;
8460 }
8461 else
8462 {
8463 /* Every other type of array. */
8464 se->want_pointer = 1;
8465 gfc_conv_expr_descriptor (se, expr);
8466
8467 if (size)
8468 array_parameter_size (&se->pre,
8469 build_fold_indirect_ref_loc (input_location,
8470 se->expr),
8471 expr, size);
8472 }
8473
8474 /* Deallocate the allocatable components of structures that are
8475 not variable, for descriptorless arguments.
8476 Arguments with a descriptor are handled in gfc_conv_procedure_call. */
8477 if (g77 && (expr->ts.type == BT_DERIVED || expr->ts.type == BT_CLASS)
8478 && expr->ts.u.derived->attr.alloc_comp
8479 && expr->expr_type != EXPR_VARIABLE)
8480 {
8481 tmp = build_fold_indirect_ref_loc (input_location, se->expr);
8482 tmp = gfc_deallocate_alloc_comp (expr->ts.u.derived, tmp, expr->rank);
8483
8484 /* The components shall be deallocated before their containing entity. */
8485 gfc_prepend_expr_to_block (&se->post, tmp);
8486 }
8487
8488 if (g77 || (fsym && fsym->attr.contiguous
8489 && !gfc_is_simply_contiguous (expr, false, true)))
8490 {
8491 tree origptr = NULL_TREE;
8492
8493 desc = se->expr;
8494
8495 /* For contiguous arrays, save the original value of the descriptor. */
8496 if (!g77)
8497 {
8498 origptr = gfc_create_var (pvoid_type_node, "origptr");
8499 tmp = build_fold_indirect_ref_loc (input_location, desc);
8500 tmp = gfc_conv_array_data (tmp);
8501 tmp = fold_build2_loc (input_location, MODIFY_EXPR,
8502 TREE_TYPE (origptr), origptr,
8503 fold_convert (TREE_TYPE (origptr), tmp));
8504 gfc_add_expr_to_block (&se->pre, tmp);
8505 }
8506
8507 /* Repack the array. */
8508 if (warn_array_temporaries)
8509 {
8510 if (fsym)
8511 gfc_warning (OPT_Warray_temporaries,
8512 "Creating array temporary at %L for argument %qs",
8513 &expr->where, fsym->name);
8514 else
8515 gfc_warning (OPT_Warray_temporaries,
8516 "Creating array temporary at %L", &expr->where);
8517 }
8518
8519 /* When optmizing, we can use gfc_conv_subref_array_arg for
8520 making the packing and unpacking operation visible to the
8521 optimizers. */
8522
8523 if (g77 && flag_inline_arg_packing && expr->expr_type == EXPR_VARIABLE
8524 && !is_pointer (expr) && ! gfc_has_dimen_vector_ref (expr)
8525 && !(expr->symtree->n.sym->as
8526 && expr->symtree->n.sym->as->type == AS_ASSUMED_RANK)
8527 && (fsym == NULL || fsym->ts.type != BT_ASSUMED))
8528 {
8529 gfc_conv_subref_array_arg (se, expr, g77,
8530 fsym ? fsym->attr.intent : INTENT_INOUT,
8531 false, fsym, proc_name, sym, true);
8532 return;
8533 }
8534
8535 ptr = build_call_expr_loc (input_location,
8536 gfor_fndecl_in_pack, 1, desc);
8537
8538 if (fsym && fsym->attr.optional && sym && sym->attr.optional)
8539 {
8540 tmp = gfc_conv_expr_present (sym);
8541 ptr = build3_loc (input_location, COND_EXPR, TREE_TYPE (se->expr),
8542 tmp, fold_convert (TREE_TYPE (se->expr), ptr),
8543 fold_convert (TREE_TYPE (se->expr), null_pointer_node));
8544 }
8545
8546 ptr = gfc_evaluate_now (ptr, &se->pre);
8547
8548 /* Use the packed data for the actual argument, except for contiguous arrays,
8549 where the descriptor's data component is set. */
8550 if (g77)
8551 se->expr = ptr;
8552 else
8553 {
8554 tmp = build_fold_indirect_ref_loc (input_location, desc);
8555
8556 gfc_ss * ss = gfc_walk_expr (expr);
8557 if (!transposed_dims (ss))
8558 gfc_conv_descriptor_data_set (&se->pre, tmp, ptr);
8559 else
8560 {
8561 tree old_field, new_field;
8562
8563 /* The original descriptor has transposed dims so we can't reuse
8564 it directly; we have to create a new one. */
8565 tree old_desc = tmp;
8566 tree new_desc = gfc_create_var (TREE_TYPE (old_desc), "arg_desc");
8567
8568 old_field = gfc_conv_descriptor_dtype (old_desc);
8569 new_field = gfc_conv_descriptor_dtype (new_desc);
8570 gfc_add_modify (&se->pre, new_field, old_field);
8571
8572 old_field = gfc_conv_descriptor_offset (old_desc);
8573 new_field = gfc_conv_descriptor_offset (new_desc);
8574 gfc_add_modify (&se->pre, new_field, old_field);
8575
8576 for (int i = 0; i < expr->rank; i++)
8577 {
8578 old_field = gfc_conv_descriptor_dimension (old_desc,
8579 gfc_rank_cst[get_array_ref_dim_for_loop_dim (ss, i)]);
8580 new_field = gfc_conv_descriptor_dimension (new_desc,
8581 gfc_rank_cst[i]);
8582 gfc_add_modify (&se->pre, new_field, old_field);
8583 }
8584
8585 if (flag_coarray == GFC_FCOARRAY_LIB
8586 && GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (old_desc))
8587 && GFC_TYPE_ARRAY_AKIND (TREE_TYPE (old_desc))
8588 == GFC_ARRAY_ALLOCATABLE)
8589 {
8590 old_field = gfc_conv_descriptor_token (old_desc);
8591 new_field = gfc_conv_descriptor_token (new_desc);
8592 gfc_add_modify (&se->pre, new_field, old_field);
8593 }
8594
8595 gfc_conv_descriptor_data_set (&se->pre, new_desc, ptr);
8596 se->expr = gfc_build_addr_expr (NULL_TREE, new_desc);
8597 }
8598 gfc_free_ss (ss);
8599 }
8600
8601 if (gfc_option.rtcheck & GFC_RTCHECK_ARRAY_TEMPS)
8602 {
8603 char * msg;
8604
8605 if (fsym && proc_name)
8606 msg = xasprintf ("An array temporary was created for argument "
8607 "'%s' of procedure '%s'", fsym->name, proc_name);
8608 else
8609 msg = xasprintf ("An array temporary was created");
8610
8611 tmp = build_fold_indirect_ref_loc (input_location,
8612 desc);
8613 tmp = gfc_conv_array_data (tmp);
8614 tmp = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
8615 fold_convert (TREE_TYPE (tmp), ptr), tmp);
8616
8617 if (fsym && fsym->attr.optional && sym && sym->attr.optional)
8618 tmp = fold_build2_loc (input_location, TRUTH_AND_EXPR,
8619 logical_type_node,
8620 gfc_conv_expr_present (sym), tmp);
8621
8622 gfc_trans_runtime_check (false, true, tmp, &se->pre,
8623 &expr->where, msg);
8624 free (msg);
8625 }
8626
8627 gfc_start_block (&block);
8628
8629 /* Copy the data back. */
8630 if (fsym == NULL || fsym->attr.intent != INTENT_IN)
8631 {
8632 tmp = build_call_expr_loc (input_location,
8633 gfor_fndecl_in_unpack, 2, desc, ptr);
8634 gfc_add_expr_to_block (&block, tmp);
8635 }
8636
8637 /* Free the temporary. */
8638 tmp = gfc_call_free (ptr);
8639 gfc_add_expr_to_block (&block, tmp);
8640
8641 stmt = gfc_finish_block (&block);
8642
8643 gfc_init_block (&block);
8644 /* Only if it was repacked. This code needs to be executed before the
8645 loop cleanup code. */
8646 tmp = build_fold_indirect_ref_loc (input_location,
8647 desc);
8648 tmp = gfc_conv_array_data (tmp);
8649 tmp = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
8650 fold_convert (TREE_TYPE (tmp), ptr), tmp);
8651
8652 if (fsym && fsym->attr.optional && sym && sym->attr.optional)
8653 tmp = fold_build2_loc (input_location, TRUTH_AND_EXPR,
8654 logical_type_node,
8655 gfc_conv_expr_present (sym), tmp);
8656
8657 tmp = build3_v (COND_EXPR, tmp, stmt, build_empty_stmt (input_location));
8658
8659 gfc_add_expr_to_block (&block, tmp);
8660 gfc_add_block_to_block (&block, &se->post);
8661
8662 gfc_init_block (&se->post);
8663
8664 /* Reset the descriptor pointer. */
8665 if (!g77)
8666 {
8667 tmp = build_fold_indirect_ref_loc (input_location, desc);
8668 gfc_conv_descriptor_data_set (&se->post, tmp, origptr);
8669 }
8670
8671 gfc_add_block_to_block (&se->post, &block);
8672 }
8673 }
8674
8675
8676 /* This helper function calculates the size in words of a full array. */
8677
8678 tree
gfc_full_array_size(stmtblock_t * block,tree decl,int rank)8679 gfc_full_array_size (stmtblock_t *block, tree decl, int rank)
8680 {
8681 tree idx;
8682 tree nelems;
8683 tree tmp;
8684 idx = gfc_rank_cst[rank - 1];
8685 nelems = gfc_conv_descriptor_ubound_get (decl, idx);
8686 tmp = gfc_conv_descriptor_lbound_get (decl, idx);
8687 tmp = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
8688 nelems, tmp);
8689 tmp = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
8690 tmp, gfc_index_one_node);
8691 tmp = gfc_evaluate_now (tmp, block);
8692
8693 nelems = gfc_conv_descriptor_stride_get (decl, idx);
8694 tmp = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
8695 nelems, tmp);
8696 return gfc_evaluate_now (tmp, block);
8697 }
8698
8699
8700 /* Allocate dest to the same size as src, and copy src -> dest.
8701 If no_malloc is set, only the copy is done. */
8702
8703 static tree
duplicate_allocatable(tree dest,tree src,tree type,int rank,bool no_malloc,bool no_memcpy,tree str_sz,tree add_when_allocated)8704 duplicate_allocatable (tree dest, tree src, tree type, int rank,
8705 bool no_malloc, bool no_memcpy, tree str_sz,
8706 tree add_when_allocated)
8707 {
8708 tree tmp;
8709 tree size;
8710 tree nelems;
8711 tree null_cond;
8712 tree null_data;
8713 stmtblock_t block;
8714
8715 /* If the source is null, set the destination to null. Then,
8716 allocate memory to the destination. */
8717 gfc_init_block (&block);
8718
8719 if (!GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (dest)))
8720 {
8721 gfc_add_modify (&block, dest, fold_convert (type, null_pointer_node));
8722 null_data = gfc_finish_block (&block);
8723
8724 gfc_init_block (&block);
8725 if (str_sz != NULL_TREE)
8726 size = str_sz;
8727 else
8728 size = TYPE_SIZE_UNIT (TREE_TYPE (type));
8729
8730 if (!no_malloc)
8731 {
8732 tmp = gfc_call_malloc (&block, type, size);
8733 gfc_add_modify (&block, dest, fold_convert (type, tmp));
8734 }
8735
8736 if (!no_memcpy)
8737 {
8738 tmp = builtin_decl_explicit (BUILT_IN_MEMCPY);
8739 tmp = build_call_expr_loc (input_location, tmp, 3, dest, src,
8740 fold_convert (size_type_node, size));
8741 gfc_add_expr_to_block (&block, tmp);
8742 }
8743 }
8744 else
8745 {
8746 gfc_conv_descriptor_data_set (&block, dest, null_pointer_node);
8747 null_data = gfc_finish_block (&block);
8748
8749 gfc_init_block (&block);
8750 if (rank)
8751 nelems = gfc_full_array_size (&block, src, rank);
8752 else
8753 nelems = gfc_index_one_node;
8754
8755 if (str_sz != NULL_TREE)
8756 tmp = fold_convert (gfc_array_index_type, str_sz);
8757 else
8758 tmp = fold_convert (gfc_array_index_type,
8759 TYPE_SIZE_UNIT (gfc_get_element_type (type)));
8760 size = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
8761 nelems, tmp);
8762 if (!no_malloc)
8763 {
8764 tmp = TREE_TYPE (gfc_conv_descriptor_data_get (src));
8765 tmp = gfc_call_malloc (&block, tmp, size);
8766 gfc_conv_descriptor_data_set (&block, dest, tmp);
8767 }
8768
8769 /* We know the temporary and the value will be the same length,
8770 so can use memcpy. */
8771 if (!no_memcpy)
8772 {
8773 tmp = builtin_decl_explicit (BUILT_IN_MEMCPY);
8774 tmp = build_call_expr_loc (input_location, tmp, 3,
8775 gfc_conv_descriptor_data_get (dest),
8776 gfc_conv_descriptor_data_get (src),
8777 fold_convert (size_type_node, size));
8778 gfc_add_expr_to_block (&block, tmp);
8779 }
8780 }
8781
8782 gfc_add_expr_to_block (&block, add_when_allocated);
8783 tmp = gfc_finish_block (&block);
8784
8785 /* Null the destination if the source is null; otherwise do
8786 the allocate and copy. */
8787 if (!GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (src)))
8788 null_cond = src;
8789 else
8790 null_cond = gfc_conv_descriptor_data_get (src);
8791
8792 null_cond = convert (pvoid_type_node, null_cond);
8793 null_cond = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
8794 null_cond, null_pointer_node);
8795 return build3_v (COND_EXPR, null_cond, tmp, null_data);
8796 }
8797
8798
8799 /* Allocate dest to the same size as src, and copy data src -> dest. */
8800
8801 tree
gfc_duplicate_allocatable(tree dest,tree src,tree type,int rank,tree add_when_allocated)8802 gfc_duplicate_allocatable (tree dest, tree src, tree type, int rank,
8803 tree add_when_allocated)
8804 {
8805 return duplicate_allocatable (dest, src, type, rank, false, false,
8806 NULL_TREE, add_when_allocated);
8807 }
8808
8809
8810 /* Copy data src -> dest. */
8811
8812 tree
gfc_copy_allocatable_data(tree dest,tree src,tree type,int rank)8813 gfc_copy_allocatable_data (tree dest, tree src, tree type, int rank)
8814 {
8815 return duplicate_allocatable (dest, src, type, rank, true, false,
8816 NULL_TREE, NULL_TREE);
8817 }
8818
8819 /* Allocate dest to the same size as src, but don't copy anything. */
8820
8821 tree
gfc_duplicate_allocatable_nocopy(tree dest,tree src,tree type,int rank)8822 gfc_duplicate_allocatable_nocopy (tree dest, tree src, tree type, int rank)
8823 {
8824 return duplicate_allocatable (dest, src, type, rank, false, true,
8825 NULL_TREE, NULL_TREE);
8826 }
8827
8828
8829 static tree
duplicate_allocatable_coarray(tree dest,tree dest_tok,tree src,tree type,int rank)8830 duplicate_allocatable_coarray (tree dest, tree dest_tok, tree src,
8831 tree type, int rank)
8832 {
8833 tree tmp;
8834 tree size;
8835 tree nelems;
8836 tree null_cond;
8837 tree null_data;
8838 stmtblock_t block, globalblock;
8839
8840 /* If the source is null, set the destination to null. Then,
8841 allocate memory to the destination. */
8842 gfc_init_block (&block);
8843 gfc_init_block (&globalblock);
8844
8845 if (!GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (dest)))
8846 {
8847 gfc_se se;
8848 symbol_attribute attr;
8849 tree dummy_desc;
8850
8851 gfc_init_se (&se, NULL);
8852 gfc_clear_attr (&attr);
8853 attr.allocatable = 1;
8854 dummy_desc = gfc_conv_scalar_to_descriptor (&se, dest, attr);
8855 gfc_add_block_to_block (&globalblock, &se.pre);
8856 size = TYPE_SIZE_UNIT (TREE_TYPE (type));
8857
8858 gfc_add_modify (&block, dest, fold_convert (type, null_pointer_node));
8859 gfc_allocate_using_caf_lib (&block, dummy_desc, size,
8860 gfc_build_addr_expr (NULL_TREE, dest_tok),
8861 NULL_TREE, NULL_TREE, NULL_TREE,
8862 GFC_CAF_COARRAY_ALLOC_REGISTER_ONLY);
8863 null_data = gfc_finish_block (&block);
8864
8865 gfc_init_block (&block);
8866
8867 gfc_allocate_using_caf_lib (&block, dummy_desc,
8868 fold_convert (size_type_node, size),
8869 gfc_build_addr_expr (NULL_TREE, dest_tok),
8870 NULL_TREE, NULL_TREE, NULL_TREE,
8871 GFC_CAF_COARRAY_ALLOC);
8872
8873 tmp = builtin_decl_explicit (BUILT_IN_MEMCPY);
8874 tmp = build_call_expr_loc (input_location, tmp, 3, dest, src,
8875 fold_convert (size_type_node, size));
8876 gfc_add_expr_to_block (&block, tmp);
8877 }
8878 else
8879 {
8880 /* Set the rank or unitialized memory access may be reported. */
8881 tmp = gfc_conv_descriptor_rank (dest);
8882 gfc_add_modify (&globalblock, tmp, build_int_cst (TREE_TYPE (tmp), rank));
8883
8884 if (rank)
8885 nelems = gfc_full_array_size (&block, src, rank);
8886 else
8887 nelems = integer_one_node;
8888
8889 tmp = fold_convert (size_type_node,
8890 TYPE_SIZE_UNIT (gfc_get_element_type (type)));
8891 size = fold_build2_loc (input_location, MULT_EXPR, size_type_node,
8892 fold_convert (size_type_node, nelems), tmp);
8893
8894 gfc_conv_descriptor_data_set (&block, dest, null_pointer_node);
8895 gfc_allocate_using_caf_lib (&block, dest, fold_convert (size_type_node,
8896 size),
8897 gfc_build_addr_expr (NULL_TREE, dest_tok),
8898 NULL_TREE, NULL_TREE, NULL_TREE,
8899 GFC_CAF_COARRAY_ALLOC_REGISTER_ONLY);
8900 null_data = gfc_finish_block (&block);
8901
8902 gfc_init_block (&block);
8903 gfc_allocate_using_caf_lib (&block, dest,
8904 fold_convert (size_type_node, size),
8905 gfc_build_addr_expr (NULL_TREE, dest_tok),
8906 NULL_TREE, NULL_TREE, NULL_TREE,
8907 GFC_CAF_COARRAY_ALLOC);
8908
8909 tmp = builtin_decl_explicit (BUILT_IN_MEMCPY);
8910 tmp = build_call_expr_loc (input_location, tmp, 3,
8911 gfc_conv_descriptor_data_get (dest),
8912 gfc_conv_descriptor_data_get (src),
8913 fold_convert (size_type_node, size));
8914 gfc_add_expr_to_block (&block, tmp);
8915 }
8916
8917 tmp = gfc_finish_block (&block);
8918
8919 /* Null the destination if the source is null; otherwise do
8920 the register and copy. */
8921 if (!GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (src)))
8922 null_cond = src;
8923 else
8924 null_cond = gfc_conv_descriptor_data_get (src);
8925
8926 null_cond = convert (pvoid_type_node, null_cond);
8927 null_cond = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
8928 null_cond, null_pointer_node);
8929 gfc_add_expr_to_block (&globalblock, build3_v (COND_EXPR, null_cond, tmp,
8930 null_data));
8931 return gfc_finish_block (&globalblock);
8932 }
8933
8934
8935 /* Helper function to abstract whether coarray processing is enabled. */
8936
8937 static bool
caf_enabled(int caf_mode)8938 caf_enabled (int caf_mode)
8939 {
8940 return (caf_mode & GFC_STRUCTURE_CAF_MODE_ENABLE_COARRAY)
8941 == GFC_STRUCTURE_CAF_MODE_ENABLE_COARRAY;
8942 }
8943
8944
8945 /* Helper function to abstract whether coarray processing is enabled
8946 and we are in a derived type coarray. */
8947
8948 static bool
caf_in_coarray(int caf_mode)8949 caf_in_coarray (int caf_mode)
8950 {
8951 static const int pat = GFC_STRUCTURE_CAF_MODE_ENABLE_COARRAY
8952 | GFC_STRUCTURE_CAF_MODE_IN_COARRAY;
8953 return (caf_mode & pat) == pat;
8954 }
8955
8956
8957 /* Helper function to abstract whether coarray is to deallocate only. */
8958
8959 bool
gfc_caf_is_dealloc_only(int caf_mode)8960 gfc_caf_is_dealloc_only (int caf_mode)
8961 {
8962 return (caf_mode & GFC_STRUCTURE_CAF_MODE_DEALLOC_ONLY)
8963 == GFC_STRUCTURE_CAF_MODE_DEALLOC_ONLY;
8964 }
8965
8966
8967 /* Recursively traverse an object of derived type, generating code to
8968 deallocate, nullify or copy allocatable components. This is the work horse
8969 function for the functions named in this enum. */
8970
8971 enum {DEALLOCATE_ALLOC_COMP = 1, NULLIFY_ALLOC_COMP,
8972 COPY_ALLOC_COMP, COPY_ONLY_ALLOC_COMP, REASSIGN_CAF_COMP,
8973 ALLOCATE_PDT_COMP, DEALLOCATE_PDT_COMP, CHECK_PDT_DUMMY,
8974 BCAST_ALLOC_COMP};
8975
8976 static gfc_actual_arglist *pdt_param_list;
8977
8978 static tree
structure_alloc_comps(gfc_symbol * der_type,tree decl,tree dest,int rank,int purpose,int caf_mode,gfc_co_subroutines_args * args)8979 structure_alloc_comps (gfc_symbol * der_type, tree decl,
8980 tree dest, int rank, int purpose, int caf_mode,
8981 gfc_co_subroutines_args *args)
8982 {
8983 gfc_component *c;
8984 gfc_loopinfo loop;
8985 stmtblock_t fnblock;
8986 stmtblock_t loopbody;
8987 stmtblock_t tmpblock;
8988 tree decl_type;
8989 tree tmp;
8990 tree comp;
8991 tree dcmp;
8992 tree nelems;
8993 tree index;
8994 tree var;
8995 tree cdecl;
8996 tree ctype;
8997 tree vref, dref;
8998 tree null_cond = NULL_TREE;
8999 tree add_when_allocated;
9000 tree dealloc_fndecl;
9001 tree caf_token;
9002 gfc_symbol *vtab;
9003 int caf_dereg_mode;
9004 symbol_attribute *attr;
9005 bool deallocate_called;
9006
9007 gfc_init_block (&fnblock);
9008
9009 decl_type = TREE_TYPE (decl);
9010
9011 if ((POINTER_TYPE_P (decl_type))
9012 || (TREE_CODE (decl_type) == REFERENCE_TYPE && rank == 0))
9013 {
9014 decl = build_fold_indirect_ref_loc (input_location, decl);
9015 /* Deref dest in sync with decl, but only when it is not NULL. */
9016 if (dest)
9017 dest = build_fold_indirect_ref_loc (input_location, dest);
9018
9019 /* Update the decl_type because it got dereferenced. */
9020 decl_type = TREE_TYPE (decl);
9021 }
9022
9023 /* If this is an array of derived types with allocatable components
9024 build a loop and recursively call this function. */
9025 if (TREE_CODE (decl_type) == ARRAY_TYPE
9026 || (GFC_DESCRIPTOR_TYPE_P (decl_type) && rank != 0))
9027 {
9028 tmp = gfc_conv_array_data (decl);
9029 var = build_fold_indirect_ref_loc (input_location, tmp);
9030
9031 /* Get the number of elements - 1 and set the counter. */
9032 if (GFC_DESCRIPTOR_TYPE_P (decl_type))
9033 {
9034 /* Use the descriptor for an allocatable array. Since this
9035 is a full array reference, we only need the descriptor
9036 information from dimension = rank. */
9037 tmp = gfc_full_array_size (&fnblock, decl, rank);
9038 tmp = fold_build2_loc (input_location, MINUS_EXPR,
9039 gfc_array_index_type, tmp,
9040 gfc_index_one_node);
9041
9042 null_cond = gfc_conv_descriptor_data_get (decl);
9043 null_cond = fold_build2_loc (input_location, NE_EXPR,
9044 logical_type_node, null_cond,
9045 build_int_cst (TREE_TYPE (null_cond), 0));
9046 }
9047 else
9048 {
9049 /* Otherwise use the TYPE_DOMAIN information. */
9050 tmp = array_type_nelts (decl_type);
9051 tmp = fold_convert (gfc_array_index_type, tmp);
9052 }
9053
9054 /* Remember that this is, in fact, the no. of elements - 1. */
9055 nelems = gfc_evaluate_now (tmp, &fnblock);
9056 index = gfc_create_var (gfc_array_index_type, "S");
9057
9058 /* Build the body of the loop. */
9059 gfc_init_block (&loopbody);
9060
9061 vref = gfc_build_array_ref (var, index, NULL);
9062
9063 if (purpose == COPY_ALLOC_COMP || purpose == COPY_ONLY_ALLOC_COMP)
9064 {
9065 tmp = build_fold_indirect_ref_loc (input_location,
9066 gfc_conv_array_data (dest));
9067 dref = gfc_build_array_ref (tmp, index, NULL);
9068 tmp = structure_alloc_comps (der_type, vref, dref, rank,
9069 COPY_ALLOC_COMP, caf_mode, args);
9070 }
9071 else
9072 tmp = structure_alloc_comps (der_type, vref, NULL_TREE, rank, purpose,
9073 caf_mode, args);
9074
9075 gfc_add_expr_to_block (&loopbody, tmp);
9076
9077 /* Build the loop and return. */
9078 gfc_init_loopinfo (&loop);
9079 loop.dimen = 1;
9080 loop.from[0] = gfc_index_zero_node;
9081 loop.loopvar[0] = index;
9082 loop.to[0] = nelems;
9083 gfc_trans_scalarizing_loops (&loop, &loopbody);
9084 gfc_add_block_to_block (&fnblock, &loop.pre);
9085
9086 tmp = gfc_finish_block (&fnblock);
9087 /* When copying allocateable components, the above implements the
9088 deep copy. Nevertheless is a deep copy only allowed, when the current
9089 component is allocated, for which code will be generated in
9090 gfc_duplicate_allocatable (), where the deep copy code is just added
9091 into the if's body, by adding tmp (the deep copy code) as last
9092 argument to gfc_duplicate_allocatable (). */
9093 if (purpose == COPY_ALLOC_COMP
9094 && GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (dest)))
9095 tmp = gfc_duplicate_allocatable (dest, decl, decl_type, rank,
9096 tmp);
9097 else if (null_cond != NULL_TREE)
9098 tmp = build3_v (COND_EXPR, null_cond, tmp,
9099 build_empty_stmt (input_location));
9100
9101 return tmp;
9102 }
9103
9104 if (purpose == DEALLOCATE_ALLOC_COMP && der_type->attr.pdt_type)
9105 {
9106 tmp = structure_alloc_comps (der_type, decl, NULL_TREE, rank,
9107 DEALLOCATE_PDT_COMP, 0, args);
9108 gfc_add_expr_to_block (&fnblock, tmp);
9109 }
9110 else if (purpose == ALLOCATE_PDT_COMP && der_type->attr.alloc_comp)
9111 {
9112 tmp = structure_alloc_comps (der_type, decl, NULL_TREE, rank,
9113 NULLIFY_ALLOC_COMP, 0, args);
9114 gfc_add_expr_to_block (&fnblock, tmp);
9115 }
9116
9117 /* Otherwise, act on the components or recursively call self to
9118 act on a chain of components. */
9119 for (c = der_type->components; c; c = c->next)
9120 {
9121 bool cmp_has_alloc_comps = (c->ts.type == BT_DERIVED
9122 || c->ts.type == BT_CLASS)
9123 && c->ts.u.derived->attr.alloc_comp;
9124 bool same_type = (c->ts.type == BT_DERIVED && der_type == c->ts.u.derived)
9125 || (c->ts.type == BT_CLASS && der_type == CLASS_DATA (c)->ts.u.derived);
9126
9127 bool is_pdt_type = c->ts.type == BT_DERIVED
9128 && c->ts.u.derived->attr.pdt_type;
9129
9130 cdecl = c->backend_decl;
9131 ctype = TREE_TYPE (cdecl);
9132
9133 switch (purpose)
9134 {
9135
9136 case BCAST_ALLOC_COMP:
9137
9138 tree ubound;
9139 tree cdesc;
9140 stmtblock_t derived_type_block;
9141
9142 gfc_init_block (&tmpblock);
9143
9144 comp = fold_build3_loc (input_location, COMPONENT_REF, ctype,
9145 decl, cdecl, NULL_TREE);
9146
9147 /* Shortcut to get the attributes of the component. */
9148 if (c->ts.type == BT_CLASS)
9149 {
9150 attr = &CLASS_DATA (c)->attr;
9151 if (attr->class_pointer)
9152 continue;
9153 }
9154 else
9155 {
9156 attr = &c->attr;
9157 if (attr->pointer)
9158 continue;
9159 }
9160
9161 /* Do not broadcast a caf_token. These are local to the image. */
9162 if (attr->caf_token)
9163 continue;
9164
9165 add_when_allocated = NULL_TREE;
9166 if (cmp_has_alloc_comps
9167 && !c->attr.pointer && !c->attr.proc_pointer)
9168 {
9169 if (c->ts.type == BT_CLASS)
9170 {
9171 rank = CLASS_DATA (c)->as ? CLASS_DATA (c)->as->rank : 0;
9172 add_when_allocated
9173 = structure_alloc_comps (CLASS_DATA (c)->ts.u.derived,
9174 comp, NULL_TREE, rank, purpose,
9175 caf_mode, args);
9176 }
9177 else
9178 {
9179 rank = c->as ? c->as->rank : 0;
9180 add_when_allocated = structure_alloc_comps (c->ts.u.derived,
9181 comp, NULL_TREE,
9182 rank, purpose,
9183 caf_mode, args);
9184 }
9185 }
9186
9187 gfc_init_block (&derived_type_block);
9188 if (add_when_allocated)
9189 gfc_add_expr_to_block (&derived_type_block, add_when_allocated);
9190 tmp = gfc_finish_block (&derived_type_block);
9191 gfc_add_expr_to_block (&tmpblock, tmp);
9192
9193 /* Convert the component into a rank 1 descriptor type. */
9194 if (attr->dimension)
9195 {
9196 tmp = gfc_get_element_type (TREE_TYPE (comp));
9197 if (!GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (comp)))
9198 ubound = GFC_TYPE_ARRAY_SIZE (TREE_TYPE (comp));
9199 else
9200 ubound = gfc_full_array_size (&tmpblock, comp,
9201 c->ts.type == BT_CLASS
9202 ? CLASS_DATA (c)->as->rank
9203 : c->as->rank);
9204 }
9205 else
9206 {
9207 tmp = TREE_TYPE (comp);
9208 ubound = build_int_cst (gfc_array_index_type, 1);
9209 }
9210
9211 /* Treat strings like arrays. Or the other way around, do not
9212 * generate an additional array layer for scalar components. */
9213 if (attr->dimension || c->ts.type == BT_CHARACTER)
9214 {
9215 cdesc = gfc_get_array_type_bounds (tmp, 1, 0, &gfc_index_one_node,
9216 &ubound, 1,
9217 GFC_ARRAY_ALLOCATABLE, false);
9218
9219 cdesc = gfc_create_var (cdesc, "cdesc");
9220 DECL_ARTIFICIAL (cdesc) = 1;
9221
9222 gfc_add_modify (&tmpblock, gfc_conv_descriptor_dtype (cdesc),
9223 gfc_get_dtype_rank_type (1, tmp));
9224 gfc_conv_descriptor_lbound_set (&tmpblock, cdesc,
9225 gfc_index_zero_node,
9226 gfc_index_one_node);
9227 gfc_conv_descriptor_stride_set (&tmpblock, cdesc,
9228 gfc_index_zero_node,
9229 gfc_index_one_node);
9230 gfc_conv_descriptor_ubound_set (&tmpblock, cdesc,
9231 gfc_index_zero_node, ubound);
9232 }
9233 else
9234 /* Prevent warning. */
9235 cdesc = NULL_TREE;
9236
9237 if (attr->dimension)
9238 {
9239 if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (comp)))
9240 comp = gfc_conv_descriptor_data_get (comp);
9241 else
9242 comp = gfc_build_addr_expr (NULL_TREE, comp);
9243 }
9244 else
9245 {
9246 gfc_se se;
9247
9248 gfc_init_se (&se, NULL);
9249
9250 comp = gfc_conv_scalar_to_descriptor (&se, comp,
9251 c->ts.type == BT_CLASS
9252 ? CLASS_DATA (c)->attr
9253 : c->attr);
9254 if (c->ts.type == BT_CHARACTER)
9255 comp = gfc_build_addr_expr (NULL_TREE, comp);
9256 gfc_add_block_to_block (&tmpblock, &se.pre);
9257 }
9258
9259 if (attr->dimension || c->ts.type == BT_CHARACTER)
9260 gfc_conv_descriptor_data_set (&tmpblock, cdesc, comp);
9261 else
9262 cdesc = comp;
9263
9264 tree fndecl;
9265
9266 fndecl = build_call_expr_loc (input_location,
9267 gfor_fndecl_co_broadcast, 5,
9268 gfc_build_addr_expr (pvoid_type_node,cdesc),
9269 args->image_index,
9270 null_pointer_node, null_pointer_node,
9271 null_pointer_node);
9272
9273 gfc_add_expr_to_block (&tmpblock, fndecl);
9274 gfc_add_block_to_block (&fnblock, &tmpblock);
9275
9276 break;
9277
9278 case DEALLOCATE_ALLOC_COMP:
9279
9280 gfc_init_block (&tmpblock);
9281
9282 comp = fold_build3_loc (input_location, COMPONENT_REF, ctype,
9283 decl, cdecl, NULL_TREE);
9284
9285 /* Shortcut to get the attributes of the component. */
9286 if (c->ts.type == BT_CLASS)
9287 {
9288 attr = &CLASS_DATA (c)->attr;
9289 if (attr->class_pointer)
9290 continue;
9291 }
9292 else
9293 {
9294 attr = &c->attr;
9295 if (attr->pointer)
9296 continue;
9297 }
9298
9299 if ((c->ts.type == BT_DERIVED && !c->attr.pointer)
9300 || (c->ts.type == BT_CLASS && !CLASS_DATA (c)->attr.class_pointer))
9301 /* Call the finalizer, which will free the memory and nullify the
9302 pointer of an array. */
9303 deallocate_called = gfc_add_comp_finalizer_call (&tmpblock, comp, c,
9304 caf_enabled (caf_mode))
9305 && attr->dimension;
9306 else
9307 deallocate_called = false;
9308
9309 /* Add the _class ref for classes. */
9310 if (c->ts.type == BT_CLASS && attr->allocatable)
9311 comp = gfc_class_data_get (comp);
9312
9313 add_when_allocated = NULL_TREE;
9314 if (cmp_has_alloc_comps
9315 && !c->attr.pointer && !c->attr.proc_pointer
9316 && !same_type
9317 && !deallocate_called)
9318 {
9319 /* Add checked deallocation of the components. This code is
9320 obviously added because the finalizer is not trusted to free
9321 all memory. */
9322 if (c->ts.type == BT_CLASS)
9323 {
9324 rank = CLASS_DATA (c)->as ? CLASS_DATA (c)->as->rank : 0;
9325 add_when_allocated
9326 = structure_alloc_comps (CLASS_DATA (c)->ts.u.derived,
9327 comp, NULL_TREE, rank, purpose,
9328 caf_mode, args);
9329 }
9330 else
9331 {
9332 rank = c->as ? c->as->rank : 0;
9333 add_when_allocated = structure_alloc_comps (c->ts.u.derived,
9334 comp, NULL_TREE,
9335 rank, purpose,
9336 caf_mode, args);
9337 }
9338 }
9339
9340 if (attr->allocatable && !same_type
9341 && (!attr->codimension || caf_enabled (caf_mode)))
9342 {
9343 /* Handle all types of components besides components of the
9344 same_type as the current one, because those would create an
9345 endless loop. */
9346 caf_dereg_mode
9347 = (caf_in_coarray (caf_mode) || attr->codimension)
9348 ? (gfc_caf_is_dealloc_only (caf_mode)
9349 ? GFC_CAF_COARRAY_DEALLOCATE_ONLY
9350 : GFC_CAF_COARRAY_DEREGISTER)
9351 : GFC_CAF_COARRAY_NOCOARRAY;
9352
9353 caf_token = NULL_TREE;
9354 /* Coarray components are handled directly by
9355 deallocate_with_status. */
9356 if (!attr->codimension
9357 && caf_dereg_mode != GFC_CAF_COARRAY_NOCOARRAY)
9358 {
9359 if (c->caf_token)
9360 caf_token = fold_build3_loc (input_location, COMPONENT_REF,
9361 TREE_TYPE (c->caf_token),
9362 decl, c->caf_token, NULL_TREE);
9363 else if (attr->dimension && !attr->proc_pointer)
9364 caf_token = gfc_conv_descriptor_token (comp);
9365 }
9366 if (attr->dimension && !attr->codimension && !attr->proc_pointer)
9367 /* When this is an array but not in conjunction with a coarray
9368 then add the data-ref. For coarray'ed arrays the data-ref
9369 is added by deallocate_with_status. */
9370 comp = gfc_conv_descriptor_data_get (comp);
9371
9372 tmp = gfc_deallocate_with_status (comp, NULL_TREE, NULL_TREE,
9373 NULL_TREE, NULL_TREE, true,
9374 NULL, caf_dereg_mode,
9375 add_when_allocated, caf_token);
9376
9377 gfc_add_expr_to_block (&tmpblock, tmp);
9378 }
9379 else if (attr->allocatable && !attr->codimension
9380 && !deallocate_called)
9381 {
9382 /* Case of recursive allocatable derived types. */
9383 tree is_allocated;
9384 tree ubound;
9385 tree cdesc;
9386 stmtblock_t dealloc_block;
9387
9388 gfc_init_block (&dealloc_block);
9389 if (add_when_allocated)
9390 gfc_add_expr_to_block (&dealloc_block, add_when_allocated);
9391
9392 /* Convert the component into a rank 1 descriptor type. */
9393 if (attr->dimension)
9394 {
9395 tmp = gfc_get_element_type (TREE_TYPE (comp));
9396 ubound = gfc_full_array_size (&dealloc_block, comp,
9397 c->ts.type == BT_CLASS
9398 ? CLASS_DATA (c)->as->rank
9399 : c->as->rank);
9400 }
9401 else
9402 {
9403 tmp = TREE_TYPE (comp);
9404 ubound = build_int_cst (gfc_array_index_type, 1);
9405 }
9406
9407 cdesc = gfc_get_array_type_bounds (tmp, 1, 0, &gfc_index_one_node,
9408 &ubound, 1,
9409 GFC_ARRAY_ALLOCATABLE, false);
9410
9411 cdesc = gfc_create_var (cdesc, "cdesc");
9412 DECL_ARTIFICIAL (cdesc) = 1;
9413
9414 gfc_add_modify (&dealloc_block, gfc_conv_descriptor_dtype (cdesc),
9415 gfc_get_dtype_rank_type (1, tmp));
9416 gfc_conv_descriptor_lbound_set (&dealloc_block, cdesc,
9417 gfc_index_zero_node,
9418 gfc_index_one_node);
9419 gfc_conv_descriptor_stride_set (&dealloc_block, cdesc,
9420 gfc_index_zero_node,
9421 gfc_index_one_node);
9422 gfc_conv_descriptor_ubound_set (&dealloc_block, cdesc,
9423 gfc_index_zero_node, ubound);
9424
9425 if (attr->dimension)
9426 comp = gfc_conv_descriptor_data_get (comp);
9427
9428 gfc_conv_descriptor_data_set (&dealloc_block, cdesc, comp);
9429
9430 /* Now call the deallocator. */
9431 vtab = gfc_find_vtab (&c->ts);
9432 if (vtab->backend_decl == NULL)
9433 gfc_get_symbol_decl (vtab);
9434 tmp = gfc_build_addr_expr (NULL_TREE, vtab->backend_decl);
9435 dealloc_fndecl = gfc_vptr_deallocate_get (tmp);
9436 dealloc_fndecl = build_fold_indirect_ref_loc (input_location,
9437 dealloc_fndecl);
9438 tmp = build_int_cst (TREE_TYPE (comp), 0);
9439 is_allocated = fold_build2_loc (input_location, NE_EXPR,
9440 logical_type_node, tmp,
9441 comp);
9442 cdesc = gfc_build_addr_expr (NULL_TREE, cdesc);
9443
9444 tmp = build_call_expr_loc (input_location,
9445 dealloc_fndecl, 1,
9446 cdesc);
9447 gfc_add_expr_to_block (&dealloc_block, tmp);
9448
9449 tmp = gfc_finish_block (&dealloc_block);
9450
9451 tmp = fold_build3_loc (input_location, COND_EXPR,
9452 void_type_node, is_allocated, tmp,
9453 build_empty_stmt (input_location));
9454
9455 gfc_add_expr_to_block (&tmpblock, tmp);
9456 }
9457 else if (add_when_allocated)
9458 gfc_add_expr_to_block (&tmpblock, add_when_allocated);
9459
9460 if (c->ts.type == BT_CLASS && attr->allocatable
9461 && (!attr->codimension || !caf_enabled (caf_mode)))
9462 {
9463 /* Finally, reset the vptr to the declared type vtable and, if
9464 necessary reset the _len field.
9465
9466 First recover the reference to the component and obtain
9467 the vptr. */
9468 comp = fold_build3_loc (input_location, COMPONENT_REF, ctype,
9469 decl, cdecl, NULL_TREE);
9470 tmp = gfc_class_vptr_get (comp);
9471
9472 if (UNLIMITED_POLY (c))
9473 {
9474 /* Both vptr and _len field should be nulled. */
9475 gfc_add_modify (&tmpblock, tmp,
9476 build_int_cst (TREE_TYPE (tmp), 0));
9477 tmp = gfc_class_len_get (comp);
9478 gfc_add_modify (&tmpblock, tmp,
9479 build_int_cst (TREE_TYPE (tmp), 0));
9480 }
9481 else
9482 {
9483 /* Build the vtable address and set the vptr with it. */
9484 tree vtab;
9485 gfc_symbol *vtable;
9486 vtable = gfc_find_derived_vtab (c->ts.u.derived);
9487 vtab = vtable->backend_decl;
9488 if (vtab == NULL_TREE)
9489 vtab = gfc_get_symbol_decl (vtable);
9490 vtab = gfc_build_addr_expr (NULL, vtab);
9491 vtab = fold_convert (TREE_TYPE (tmp), vtab);
9492 gfc_add_modify (&tmpblock, tmp, vtab);
9493 }
9494 }
9495
9496 /* Now add the deallocation of this component. */
9497 gfc_add_block_to_block (&fnblock, &tmpblock);
9498 break;
9499
9500 case NULLIFY_ALLOC_COMP:
9501 /* Nullify
9502 - allocatable components (regular or in class)
9503 - components that have allocatable components
9504 - pointer components when in a coarray.
9505 Skip everything else especially proc_pointers, which may come
9506 coupled with the regular pointer attribute. */
9507 if (c->attr.proc_pointer
9508 || !(c->attr.allocatable || (c->ts.type == BT_CLASS
9509 && CLASS_DATA (c)->attr.allocatable)
9510 || (cmp_has_alloc_comps
9511 && ((c->ts.type == BT_DERIVED && !c->attr.pointer)
9512 || (c->ts.type == BT_CLASS
9513 && !CLASS_DATA (c)->attr.class_pointer)))
9514 || (caf_in_coarray (caf_mode) && c->attr.pointer)))
9515 continue;
9516
9517 /* Process class components first, because they always have the
9518 pointer-attribute set which would be caught wrong else. */
9519 if (c->ts.type == BT_CLASS
9520 && (CLASS_DATA (c)->attr.allocatable
9521 || CLASS_DATA (c)->attr.class_pointer))
9522 {
9523 tree vptr_decl;
9524
9525 /* Allocatable CLASS components. */
9526 comp = fold_build3_loc (input_location, COMPONENT_REF, ctype,
9527 decl, cdecl, NULL_TREE);
9528
9529 vptr_decl = gfc_class_vptr_get (comp);
9530
9531 comp = gfc_class_data_get (comp);
9532 if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (comp)))
9533 gfc_conv_descriptor_data_set (&fnblock, comp,
9534 null_pointer_node);
9535 else
9536 {
9537 tmp = fold_build2_loc (input_location, MODIFY_EXPR,
9538 void_type_node, comp,
9539 build_int_cst (TREE_TYPE (comp), 0));
9540 gfc_add_expr_to_block (&fnblock, tmp);
9541 }
9542
9543 /* The dynamic type of a disassociated pointer or unallocated
9544 allocatable variable is its declared type. An unlimited
9545 polymorphic entity has no declared type. */
9546 if (!UNLIMITED_POLY (c))
9547 {
9548 vtab = gfc_find_derived_vtab (c->ts.u.derived);
9549 if (!vtab->backend_decl)
9550 gfc_get_symbol_decl (vtab);
9551 tmp = gfc_build_addr_expr (NULL_TREE, vtab->backend_decl);
9552 }
9553 else
9554 tmp = build_int_cst (TREE_TYPE (vptr_decl), 0);
9555
9556 tmp = fold_build2_loc (input_location, MODIFY_EXPR,
9557 void_type_node, vptr_decl, tmp);
9558 gfc_add_expr_to_block (&fnblock, tmp);
9559
9560 cmp_has_alloc_comps = false;
9561 }
9562 /* Coarrays need the component to be nulled before the api-call
9563 is made. */
9564 else if (c->attr.pointer || c->attr.allocatable)
9565 {
9566 comp = fold_build3_loc (input_location, COMPONENT_REF, ctype,
9567 decl, cdecl, NULL_TREE);
9568 if (c->attr.dimension || c->attr.codimension)
9569 gfc_conv_descriptor_data_set (&fnblock, comp,
9570 null_pointer_node);
9571 else
9572 gfc_add_modify (&fnblock, comp,
9573 build_int_cst (TREE_TYPE (comp), 0));
9574 if (gfc_deferred_strlen (c, &comp))
9575 {
9576 comp = fold_build3_loc (input_location, COMPONENT_REF,
9577 TREE_TYPE (comp),
9578 decl, comp, NULL_TREE);
9579 tmp = fold_build2_loc (input_location, MODIFY_EXPR,
9580 TREE_TYPE (comp), comp,
9581 build_int_cst (TREE_TYPE (comp), 0));
9582 gfc_add_expr_to_block (&fnblock, tmp);
9583 }
9584 cmp_has_alloc_comps = false;
9585 }
9586
9587 if (flag_coarray == GFC_FCOARRAY_LIB && caf_in_coarray (caf_mode))
9588 {
9589 /* Register a component of a derived type coarray with the
9590 coarray library. Do not register ultimate component
9591 coarrays here. They are treated like regular coarrays and
9592 are either allocated on all images or on none. */
9593 tree token;
9594
9595 comp = fold_build3_loc (input_location, COMPONENT_REF, ctype,
9596 decl, cdecl, NULL_TREE);
9597 if (c->attr.dimension)
9598 {
9599 /* Set the dtype, because caf_register needs it. */
9600 gfc_add_modify (&fnblock, gfc_conv_descriptor_dtype (comp),
9601 gfc_get_dtype (TREE_TYPE (comp)));
9602 tmp = fold_build3_loc (input_location, COMPONENT_REF, ctype,
9603 decl, cdecl, NULL_TREE);
9604 token = gfc_conv_descriptor_token (tmp);
9605 }
9606 else
9607 {
9608 gfc_se se;
9609
9610 gfc_init_se (&se, NULL);
9611 token = fold_build3_loc (input_location, COMPONENT_REF,
9612 pvoid_type_node, decl, c->caf_token,
9613 NULL_TREE);
9614 comp = gfc_conv_scalar_to_descriptor (&se, comp,
9615 c->ts.type == BT_CLASS
9616 ? CLASS_DATA (c)->attr
9617 : c->attr);
9618 gfc_add_block_to_block (&fnblock, &se.pre);
9619 }
9620
9621 gfc_allocate_using_caf_lib (&fnblock, comp, size_zero_node,
9622 gfc_build_addr_expr (NULL_TREE,
9623 token),
9624 NULL_TREE, NULL_TREE, NULL_TREE,
9625 GFC_CAF_COARRAY_ALLOC_REGISTER_ONLY);
9626 }
9627
9628 if (cmp_has_alloc_comps)
9629 {
9630 comp = fold_build3_loc (input_location, COMPONENT_REF, ctype,
9631 decl, cdecl, NULL_TREE);
9632 rank = c->as ? c->as->rank : 0;
9633 tmp = structure_alloc_comps (c->ts.u.derived, comp, NULL_TREE,
9634 rank, purpose, caf_mode, args);
9635 gfc_add_expr_to_block (&fnblock, tmp);
9636 }
9637 break;
9638
9639 case REASSIGN_CAF_COMP:
9640 if (caf_enabled (caf_mode)
9641 && (c->attr.codimension
9642 || (c->ts.type == BT_CLASS
9643 && (CLASS_DATA (c)->attr.coarray_comp
9644 || caf_in_coarray (caf_mode)))
9645 || (c->ts.type == BT_DERIVED
9646 && (c->ts.u.derived->attr.coarray_comp
9647 || caf_in_coarray (caf_mode))))
9648 && !same_type)
9649 {
9650 comp = fold_build3_loc (input_location, COMPONENT_REF, ctype,
9651 decl, cdecl, NULL_TREE);
9652 dcmp = fold_build3_loc (input_location, COMPONENT_REF, ctype,
9653 dest, cdecl, NULL_TREE);
9654
9655 if (c->attr.codimension)
9656 {
9657 if (c->ts.type == BT_CLASS)
9658 {
9659 comp = gfc_class_data_get (comp);
9660 dcmp = gfc_class_data_get (dcmp);
9661 }
9662 gfc_conv_descriptor_data_set (&fnblock, dcmp,
9663 gfc_conv_descriptor_data_get (comp));
9664 }
9665 else
9666 {
9667 tmp = structure_alloc_comps (c->ts.u.derived, comp, dcmp,
9668 rank, purpose, caf_mode
9669 | GFC_STRUCTURE_CAF_MODE_IN_COARRAY,
9670 args);
9671 gfc_add_expr_to_block (&fnblock, tmp);
9672 }
9673 }
9674 break;
9675
9676 case COPY_ALLOC_COMP:
9677 if (c->attr.pointer || c->attr.proc_pointer)
9678 continue;
9679
9680 /* We need source and destination components. */
9681 comp = fold_build3_loc (input_location, COMPONENT_REF, ctype, decl,
9682 cdecl, NULL_TREE);
9683 dcmp = fold_build3_loc (input_location, COMPONENT_REF, ctype, dest,
9684 cdecl, NULL_TREE);
9685 dcmp = fold_convert (TREE_TYPE (comp), dcmp);
9686
9687 if (c->ts.type == BT_CLASS && CLASS_DATA (c)->attr.allocatable)
9688 {
9689 tree ftn_tree;
9690 tree size;
9691 tree dst_data;
9692 tree src_data;
9693 tree null_data;
9694
9695 dst_data = gfc_class_data_get (dcmp);
9696 src_data = gfc_class_data_get (comp);
9697 size = fold_convert (size_type_node,
9698 gfc_class_vtab_size_get (comp));
9699
9700 if (CLASS_DATA (c)->attr.dimension)
9701 {
9702 nelems = gfc_conv_descriptor_size (src_data,
9703 CLASS_DATA (c)->as->rank);
9704 size = fold_build2_loc (input_location, MULT_EXPR,
9705 size_type_node, size,
9706 fold_convert (size_type_node,
9707 nelems));
9708 }
9709 else
9710 nelems = build_int_cst (size_type_node, 1);
9711
9712 if (CLASS_DATA (c)->attr.dimension
9713 || CLASS_DATA (c)->attr.codimension)
9714 {
9715 src_data = gfc_conv_descriptor_data_get (src_data);
9716 dst_data = gfc_conv_descriptor_data_get (dst_data);
9717 }
9718
9719 gfc_init_block (&tmpblock);
9720
9721 gfc_add_modify (&tmpblock, gfc_class_vptr_get (dcmp),
9722 gfc_class_vptr_get (comp));
9723
9724 /* Copy the unlimited '_len' field. If it is greater than zero
9725 (ie. a character(_len)), multiply it by size and use this
9726 for the malloc call. */
9727 if (UNLIMITED_POLY (c))
9728 {
9729 gfc_add_modify (&tmpblock, gfc_class_len_get (dcmp),
9730 gfc_class_len_get (comp));
9731 size = gfc_resize_class_size_with_len (&tmpblock, comp, size);
9732 }
9733
9734 /* Coarray component have to have the same allocation status and
9735 shape/type-parameter/effective-type on the LHS and RHS of an
9736 intrinsic assignment. Hence, we did not deallocated them - and
9737 do not allocate them here. */
9738 if (!CLASS_DATA (c)->attr.codimension)
9739 {
9740 ftn_tree = builtin_decl_explicit (BUILT_IN_MALLOC);
9741 tmp = build_call_expr_loc (input_location, ftn_tree, 1, size);
9742 gfc_add_modify (&tmpblock, dst_data,
9743 fold_convert (TREE_TYPE (dst_data), tmp));
9744 }
9745
9746 tmp = gfc_copy_class_to_class (comp, dcmp, nelems,
9747 UNLIMITED_POLY (c));
9748 gfc_add_expr_to_block (&tmpblock, tmp);
9749 tmp = gfc_finish_block (&tmpblock);
9750
9751 gfc_init_block (&tmpblock);
9752 gfc_add_modify (&tmpblock, dst_data,
9753 fold_convert (TREE_TYPE (dst_data),
9754 null_pointer_node));
9755 null_data = gfc_finish_block (&tmpblock);
9756
9757 null_cond = fold_build2_loc (input_location, NE_EXPR,
9758 logical_type_node, src_data,
9759 null_pointer_node);
9760
9761 gfc_add_expr_to_block (&fnblock, build3_v (COND_EXPR, null_cond,
9762 tmp, null_data));
9763 continue;
9764 }
9765
9766 /* To implement guarded deep copy, i.e., deep copy only allocatable
9767 components that are really allocated, the deep copy code has to
9768 be generated first and then added to the if-block in
9769 gfc_duplicate_allocatable (). */
9770 if (cmp_has_alloc_comps && !c->attr.proc_pointer && !same_type)
9771 {
9772 rank = c->as ? c->as->rank : 0;
9773 tmp = fold_convert (TREE_TYPE (dcmp), comp);
9774 gfc_add_modify (&fnblock, dcmp, tmp);
9775 add_when_allocated = structure_alloc_comps (c->ts.u.derived,
9776 comp, dcmp,
9777 rank, purpose,
9778 caf_mode, args);
9779 }
9780 else
9781 add_when_allocated = NULL_TREE;
9782
9783 if (gfc_deferred_strlen (c, &tmp))
9784 {
9785 tree len, size;
9786 len = tmp;
9787 tmp = fold_build3_loc (input_location, COMPONENT_REF,
9788 TREE_TYPE (len),
9789 decl, len, NULL_TREE);
9790 len = fold_build3_loc (input_location, COMPONENT_REF,
9791 TREE_TYPE (len),
9792 dest, len, NULL_TREE);
9793 tmp = fold_build2_loc (input_location, MODIFY_EXPR,
9794 TREE_TYPE (len), len, tmp);
9795 gfc_add_expr_to_block (&fnblock, tmp);
9796 size = size_of_string_in_bytes (c->ts.kind, len);
9797 /* This component cannot have allocatable components,
9798 therefore add_when_allocated of duplicate_allocatable ()
9799 is always NULL. */
9800 tmp = duplicate_allocatable (dcmp, comp, ctype, rank,
9801 false, false, size, NULL_TREE);
9802 gfc_add_expr_to_block (&fnblock, tmp);
9803 }
9804 else if (c->attr.pdt_array)
9805 {
9806 tmp = duplicate_allocatable (dcmp, comp, ctype,
9807 c->as ? c->as->rank : 0,
9808 false, false, NULL_TREE, NULL_TREE);
9809 gfc_add_expr_to_block (&fnblock, tmp);
9810 }
9811 else if ((c->attr.allocatable)
9812 && !c->attr.proc_pointer && !same_type
9813 && (!(cmp_has_alloc_comps && c->as) || c->attr.codimension
9814 || caf_in_coarray (caf_mode)))
9815 {
9816 rank = c->as ? c->as->rank : 0;
9817 if (c->attr.codimension)
9818 tmp = gfc_copy_allocatable_data (dcmp, comp, ctype, rank);
9819 else if (flag_coarray == GFC_FCOARRAY_LIB
9820 && caf_in_coarray (caf_mode))
9821 {
9822 tree dst_tok;
9823 if (c->as)
9824 dst_tok = gfc_conv_descriptor_token (dcmp);
9825 else
9826 {
9827 /* For a scalar allocatable component the caf_token is
9828 the next component. */
9829 if (!c->caf_token)
9830 c->caf_token = c->next->backend_decl;
9831 dst_tok = fold_build3_loc (input_location,
9832 COMPONENT_REF,
9833 pvoid_type_node, dest,
9834 c->caf_token,
9835 NULL_TREE);
9836 }
9837 tmp = duplicate_allocatable_coarray (dcmp, dst_tok, comp,
9838 ctype, rank);
9839 }
9840 else
9841 tmp = gfc_duplicate_allocatable (dcmp, comp, ctype, rank,
9842 add_when_allocated);
9843 gfc_add_expr_to_block (&fnblock, tmp);
9844 }
9845 else
9846 if (cmp_has_alloc_comps || is_pdt_type)
9847 gfc_add_expr_to_block (&fnblock, add_when_allocated);
9848
9849 break;
9850
9851 case ALLOCATE_PDT_COMP:
9852
9853 comp = fold_build3_loc (input_location, COMPONENT_REF, ctype,
9854 decl, cdecl, NULL_TREE);
9855
9856 /* Set the PDT KIND and LEN fields. */
9857 if (c->attr.pdt_kind || c->attr.pdt_len)
9858 {
9859 gfc_se tse;
9860 gfc_expr *c_expr = NULL;
9861 gfc_actual_arglist *param = pdt_param_list;
9862 gfc_init_se (&tse, NULL);
9863 for (; param; param = param->next)
9864 if (param->name && !strcmp (c->name, param->name))
9865 c_expr = param->expr;
9866
9867 if (!c_expr)
9868 c_expr = c->initializer;
9869
9870 if (c_expr)
9871 {
9872 gfc_conv_expr_type (&tse, c_expr, TREE_TYPE (comp));
9873 gfc_add_modify (&fnblock, comp, tse.expr);
9874 }
9875 }
9876
9877 if (c->attr.pdt_string)
9878 {
9879 gfc_se tse;
9880 gfc_init_se (&tse, NULL);
9881 tree strlen = NULL_TREE;
9882 gfc_expr *e = gfc_copy_expr (c->ts.u.cl->length);
9883 /* Convert the parameterized string length to its value. The
9884 string length is stored in a hidden field in the same way as
9885 deferred string lengths. */
9886 gfc_insert_parameter_exprs (e, pdt_param_list);
9887 if (gfc_deferred_strlen (c, &strlen) && strlen != NULL_TREE)
9888 {
9889 gfc_conv_expr_type (&tse, e,
9890 TREE_TYPE (strlen));
9891 strlen = fold_build3_loc (input_location, COMPONENT_REF,
9892 TREE_TYPE (strlen),
9893 decl, strlen, NULL_TREE);
9894 gfc_add_modify (&fnblock, strlen, tse.expr);
9895 c->ts.u.cl->backend_decl = strlen;
9896 }
9897 gfc_free_expr (e);
9898
9899 /* Scalar parameterized strings can be allocated now. */
9900 if (!c->as)
9901 {
9902 tmp = fold_convert (gfc_array_index_type, strlen);
9903 tmp = size_of_string_in_bytes (c->ts.kind, tmp);
9904 tmp = gfc_evaluate_now (tmp, &fnblock);
9905 tmp = gfc_call_malloc (&fnblock, TREE_TYPE (comp), tmp);
9906 gfc_add_modify (&fnblock, comp, tmp);
9907 }
9908 }
9909
9910 /* Allocate parameterized arrays of parameterized derived types. */
9911 if (!(c->attr.pdt_array && c->as && c->as->type == AS_EXPLICIT)
9912 && !((c->ts.type == BT_DERIVED || c->ts.type == BT_CLASS)
9913 && (c->ts.u.derived && c->ts.u.derived->attr.pdt_type)))
9914 continue;
9915
9916 if (c->ts.type == BT_CLASS)
9917 comp = gfc_class_data_get (comp);
9918
9919 if (c->attr.pdt_array)
9920 {
9921 gfc_se tse;
9922 int i;
9923 tree size = gfc_index_one_node;
9924 tree offset = gfc_index_zero_node;
9925 tree lower, upper;
9926 gfc_expr *e;
9927
9928 /* This chunk takes the expressions for 'lower' and 'upper'
9929 in the arrayspec and substitutes in the expressions for
9930 the parameters from 'pdt_param_list'. The descriptor
9931 fields can then be filled from the values so obtained. */
9932 gcc_assert (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (comp)));
9933 for (i = 0; i < c->as->rank; i++)
9934 {
9935 gfc_init_se (&tse, NULL);
9936 e = gfc_copy_expr (c->as->lower[i]);
9937 gfc_insert_parameter_exprs (e, pdt_param_list);
9938 gfc_conv_expr_type (&tse, e, gfc_array_index_type);
9939 gfc_free_expr (e);
9940 lower = tse.expr;
9941 gfc_conv_descriptor_lbound_set (&fnblock, comp,
9942 gfc_rank_cst[i],
9943 lower);
9944 e = gfc_copy_expr (c->as->upper[i]);
9945 gfc_insert_parameter_exprs (e, pdt_param_list);
9946 gfc_conv_expr_type (&tse, e, gfc_array_index_type);
9947 gfc_free_expr (e);
9948 upper = tse.expr;
9949 gfc_conv_descriptor_ubound_set (&fnblock, comp,
9950 gfc_rank_cst[i],
9951 upper);
9952 gfc_conv_descriptor_stride_set (&fnblock, comp,
9953 gfc_rank_cst[i],
9954 size);
9955 size = gfc_evaluate_now (size, &fnblock);
9956 offset = fold_build2_loc (input_location,
9957 MINUS_EXPR,
9958 gfc_array_index_type,
9959 offset, size);
9960 offset = gfc_evaluate_now (offset, &fnblock);
9961 tmp = fold_build2_loc (input_location, MINUS_EXPR,
9962 gfc_array_index_type,
9963 upper, lower);
9964 tmp = fold_build2_loc (input_location, PLUS_EXPR,
9965 gfc_array_index_type,
9966 tmp, gfc_index_one_node);
9967 size = fold_build2_loc (input_location, MULT_EXPR,
9968 gfc_array_index_type, size, tmp);
9969 }
9970 gfc_conv_descriptor_offset_set (&fnblock, comp, offset);
9971 if (c->ts.type == BT_CLASS)
9972 {
9973 tmp = gfc_get_vptr_from_expr (comp);
9974 if (POINTER_TYPE_P (TREE_TYPE (tmp)))
9975 tmp = build_fold_indirect_ref_loc (input_location, tmp);
9976 tmp = gfc_vptr_size_get (tmp);
9977 }
9978 else
9979 tmp = TYPE_SIZE_UNIT (gfc_get_element_type (ctype));
9980 tmp = fold_convert (gfc_array_index_type, tmp);
9981 size = fold_build2_loc (input_location, MULT_EXPR,
9982 gfc_array_index_type, size, tmp);
9983 size = gfc_evaluate_now (size, &fnblock);
9984 tmp = gfc_call_malloc (&fnblock, NULL, size);
9985 gfc_conv_descriptor_data_set (&fnblock, comp, tmp);
9986 tmp = gfc_conv_descriptor_dtype (comp);
9987 gfc_add_modify (&fnblock, tmp, gfc_get_dtype (ctype));
9988
9989 if (c->initializer && c->initializer->rank)
9990 {
9991 gfc_init_se (&tse, NULL);
9992 e = gfc_copy_expr (c->initializer);
9993 gfc_insert_parameter_exprs (e, pdt_param_list);
9994 gfc_conv_expr_descriptor (&tse, e);
9995 gfc_add_block_to_block (&fnblock, &tse.pre);
9996 gfc_free_expr (e);
9997 tmp = builtin_decl_explicit (BUILT_IN_MEMCPY);
9998 tmp = build_call_expr_loc (input_location, tmp, 3,
9999 gfc_conv_descriptor_data_get (comp),
10000 gfc_conv_descriptor_data_get (tse.expr),
10001 fold_convert (size_type_node, size));
10002 gfc_add_expr_to_block (&fnblock, tmp);
10003 gfc_add_block_to_block (&fnblock, &tse.post);
10004 }
10005 }
10006
10007 /* Recurse in to PDT components. */
10008 if ((c->ts.type == BT_DERIVED || c->ts.type == BT_CLASS)
10009 && c->ts.u.derived && c->ts.u.derived->attr.pdt_type
10010 && !(c->attr.pointer || c->attr.allocatable))
10011 {
10012 bool is_deferred = false;
10013 gfc_actual_arglist *tail = c->param_list;
10014
10015 for (; tail; tail = tail->next)
10016 if (!tail->expr)
10017 is_deferred = true;
10018
10019 tail = is_deferred ? pdt_param_list : c->param_list;
10020 tmp = gfc_allocate_pdt_comp (c->ts.u.derived, comp,
10021 c->as ? c->as->rank : 0,
10022 tail);
10023 gfc_add_expr_to_block (&fnblock, tmp);
10024 }
10025
10026 break;
10027
10028 case DEALLOCATE_PDT_COMP:
10029 /* Deallocate array or parameterized string length components
10030 of parameterized derived types. */
10031 if (!(c->attr.pdt_array && c->as && c->as->type == AS_EXPLICIT)
10032 && !c->attr.pdt_string
10033 && !((c->ts.type == BT_DERIVED || c->ts.type == BT_CLASS)
10034 && (c->ts.u.derived && c->ts.u.derived->attr.pdt_type)))
10035 continue;
10036
10037 comp = fold_build3_loc (input_location, COMPONENT_REF, ctype,
10038 decl, cdecl, NULL_TREE);
10039 if (c->ts.type == BT_CLASS)
10040 comp = gfc_class_data_get (comp);
10041
10042 /* Recurse in to PDT components. */
10043 if ((c->ts.type == BT_DERIVED || c->ts.type == BT_CLASS)
10044 && c->ts.u.derived && c->ts.u.derived->attr.pdt_type
10045 && (!c->attr.pointer && !c->attr.allocatable))
10046 {
10047 tmp = gfc_deallocate_pdt_comp (c->ts.u.derived, comp,
10048 c->as ? c->as->rank : 0);
10049 gfc_add_expr_to_block (&fnblock, tmp);
10050 }
10051
10052 if (c->attr.pdt_array)
10053 {
10054 tmp = gfc_conv_descriptor_data_get (comp);
10055 null_cond = fold_build2_loc (input_location, NE_EXPR,
10056 logical_type_node, tmp,
10057 build_int_cst (TREE_TYPE (tmp), 0));
10058 tmp = gfc_call_free (tmp);
10059 tmp = build3_v (COND_EXPR, null_cond, tmp,
10060 build_empty_stmt (input_location));
10061 gfc_add_expr_to_block (&fnblock, tmp);
10062 gfc_conv_descriptor_data_set (&fnblock, comp, null_pointer_node);
10063 }
10064 else if (c->attr.pdt_string)
10065 {
10066 null_cond = fold_build2_loc (input_location, NE_EXPR,
10067 logical_type_node, comp,
10068 build_int_cst (TREE_TYPE (comp), 0));
10069 tmp = gfc_call_free (comp);
10070 tmp = build3_v (COND_EXPR, null_cond, tmp,
10071 build_empty_stmt (input_location));
10072 gfc_add_expr_to_block (&fnblock, tmp);
10073 tmp = fold_convert (TREE_TYPE (comp), null_pointer_node);
10074 gfc_add_modify (&fnblock, comp, tmp);
10075 }
10076
10077 break;
10078
10079 case CHECK_PDT_DUMMY:
10080
10081 comp = fold_build3_loc (input_location, COMPONENT_REF, ctype,
10082 decl, cdecl, NULL_TREE);
10083 if (c->ts.type == BT_CLASS)
10084 comp = gfc_class_data_get (comp);
10085
10086 /* Recurse in to PDT components. */
10087 if ((c->ts.type == BT_DERIVED || c->ts.type == BT_CLASS)
10088 && c->ts.u.derived && c->ts.u.derived->attr.pdt_type)
10089 {
10090 tmp = gfc_check_pdt_dummy (c->ts.u.derived, comp,
10091 c->as ? c->as->rank : 0,
10092 pdt_param_list);
10093 gfc_add_expr_to_block (&fnblock, tmp);
10094 }
10095
10096 if (!c->attr.pdt_len)
10097 continue;
10098 else
10099 {
10100 gfc_se tse;
10101 gfc_expr *c_expr = NULL;
10102 gfc_actual_arglist *param = pdt_param_list;
10103
10104 gfc_init_se (&tse, NULL);
10105 for (; param; param = param->next)
10106 if (!strcmp (c->name, param->name)
10107 && param->spec_type == SPEC_EXPLICIT)
10108 c_expr = param->expr;
10109
10110 if (c_expr)
10111 {
10112 tree error, cond, cname;
10113 gfc_conv_expr_type (&tse, c_expr, TREE_TYPE (comp));
10114 cond = fold_build2_loc (input_location, NE_EXPR,
10115 logical_type_node,
10116 comp, tse.expr);
10117 cname = gfc_build_cstring_const (c->name);
10118 cname = gfc_build_addr_expr (pchar_type_node, cname);
10119 error = gfc_trans_runtime_error (true, NULL,
10120 "The value of the PDT LEN "
10121 "parameter '%s' does not "
10122 "agree with that in the "
10123 "dummy declaration",
10124 cname);
10125 tmp = fold_build3_loc (input_location, COND_EXPR,
10126 void_type_node, cond, error,
10127 build_empty_stmt (input_location));
10128 gfc_add_expr_to_block (&fnblock, tmp);
10129 }
10130 }
10131 break;
10132
10133 default:
10134 gcc_unreachable ();
10135 break;
10136 }
10137 }
10138
10139 return gfc_finish_block (&fnblock);
10140 }
10141
10142 /* Recursively traverse an object of derived type, generating code to
10143 nullify allocatable components. */
10144
10145 tree
gfc_nullify_alloc_comp(gfc_symbol * der_type,tree decl,int rank,int caf_mode)10146 gfc_nullify_alloc_comp (gfc_symbol * der_type, tree decl, int rank,
10147 int caf_mode)
10148 {
10149 return structure_alloc_comps (der_type, decl, NULL_TREE, rank,
10150 NULLIFY_ALLOC_COMP,
10151 GFC_STRUCTURE_CAF_MODE_ENABLE_COARRAY | caf_mode, NULL);
10152 }
10153
10154
10155 /* Recursively traverse an object of derived type, generating code to
10156 deallocate allocatable components. */
10157
10158 tree
gfc_deallocate_alloc_comp(gfc_symbol * der_type,tree decl,int rank,int caf_mode)10159 gfc_deallocate_alloc_comp (gfc_symbol * der_type, tree decl, int rank,
10160 int caf_mode)
10161 {
10162 return structure_alloc_comps (der_type, decl, NULL_TREE, rank,
10163 DEALLOCATE_ALLOC_COMP,
10164 GFC_STRUCTURE_CAF_MODE_ENABLE_COARRAY | caf_mode, NULL);
10165 }
10166
10167 tree
gfc_bcast_alloc_comp(gfc_symbol * derived,gfc_expr * expr,int rank,tree image_index,tree stat,tree errmsg,tree errmsg_len)10168 gfc_bcast_alloc_comp (gfc_symbol *derived, gfc_expr *expr, int rank,
10169 tree image_index, tree stat, tree errmsg,
10170 tree errmsg_len)
10171 {
10172 tree tmp, array;
10173 gfc_se argse;
10174 stmtblock_t block, post_block;
10175 gfc_co_subroutines_args args;
10176
10177 args.image_index = image_index;
10178 args.stat = stat;
10179 args.errmsg = errmsg;
10180 args.errmsg_len = errmsg_len;
10181
10182 if (rank == 0)
10183 {
10184 gfc_start_block (&block);
10185 gfc_init_block (&post_block);
10186 gfc_init_se (&argse, NULL);
10187 gfc_conv_expr (&argse, expr);
10188 gfc_add_block_to_block (&block, &argse.pre);
10189 gfc_add_block_to_block (&post_block, &argse.post);
10190 array = argse.expr;
10191 }
10192 else
10193 {
10194 gfc_init_se (&argse, NULL);
10195 argse.want_pointer = 1;
10196 gfc_conv_expr_descriptor (&argse, expr);
10197 array = argse.expr;
10198 }
10199
10200 tmp = structure_alloc_comps (derived, array, NULL_TREE, rank,
10201 BCAST_ALLOC_COMP,
10202 GFC_STRUCTURE_CAF_MODE_ENABLE_COARRAY, &args);
10203 return tmp;
10204 }
10205
10206 /* Recursively traverse an object of derived type, generating code to
10207 deallocate allocatable components. But do not deallocate coarrays.
10208 To be used for intrinsic assignment, which may not change the allocation
10209 status of coarrays. */
10210
10211 tree
gfc_deallocate_alloc_comp_no_caf(gfc_symbol * der_type,tree decl,int rank)10212 gfc_deallocate_alloc_comp_no_caf (gfc_symbol * der_type, tree decl, int rank)
10213 {
10214 return structure_alloc_comps (der_type, decl, NULL_TREE, rank,
10215 DEALLOCATE_ALLOC_COMP, 0, NULL);
10216 }
10217
10218
10219 tree
gfc_reassign_alloc_comp_caf(gfc_symbol * der_type,tree decl,tree dest)10220 gfc_reassign_alloc_comp_caf (gfc_symbol *der_type, tree decl, tree dest)
10221 {
10222 return structure_alloc_comps (der_type, decl, dest, 0, REASSIGN_CAF_COMP,
10223 GFC_STRUCTURE_CAF_MODE_ENABLE_COARRAY, NULL);
10224 }
10225
10226
10227 /* Recursively traverse an object of derived type, generating code to
10228 copy it and its allocatable components. */
10229
10230 tree
gfc_copy_alloc_comp(gfc_symbol * der_type,tree decl,tree dest,int rank,int caf_mode)10231 gfc_copy_alloc_comp (gfc_symbol * der_type, tree decl, tree dest, int rank,
10232 int caf_mode)
10233 {
10234 return structure_alloc_comps (der_type, decl, dest, rank, COPY_ALLOC_COMP,
10235 caf_mode, NULL);
10236 }
10237
10238
10239 /* Recursively traverse an object of derived type, generating code to
10240 copy only its allocatable components. */
10241
10242 tree
gfc_copy_only_alloc_comp(gfc_symbol * der_type,tree decl,tree dest,int rank)10243 gfc_copy_only_alloc_comp (gfc_symbol * der_type, tree decl, tree dest, int rank)
10244 {
10245 return structure_alloc_comps (der_type, decl, dest, rank,
10246 COPY_ONLY_ALLOC_COMP, 0, NULL);
10247 }
10248
10249
10250 /* Recursively traverse an object of parameterized derived type, generating
10251 code to allocate parameterized components. */
10252
10253 tree
gfc_allocate_pdt_comp(gfc_symbol * der_type,tree decl,int rank,gfc_actual_arglist * param_list)10254 gfc_allocate_pdt_comp (gfc_symbol * der_type, tree decl, int rank,
10255 gfc_actual_arglist *param_list)
10256 {
10257 tree res;
10258 gfc_actual_arglist *old_param_list = pdt_param_list;
10259 pdt_param_list = param_list;
10260 res = structure_alloc_comps (der_type, decl, NULL_TREE, rank,
10261 ALLOCATE_PDT_COMP, 0, NULL);
10262 pdt_param_list = old_param_list;
10263 return res;
10264 }
10265
10266 /* Recursively traverse an object of parameterized derived type, generating
10267 code to deallocate parameterized components. */
10268
10269 tree
gfc_deallocate_pdt_comp(gfc_symbol * der_type,tree decl,int rank)10270 gfc_deallocate_pdt_comp (gfc_symbol * der_type, tree decl, int rank)
10271 {
10272 return structure_alloc_comps (der_type, decl, NULL_TREE, rank,
10273 DEALLOCATE_PDT_COMP, 0, NULL);
10274 }
10275
10276
10277 /* Recursively traverse a dummy of parameterized derived type to check the
10278 values of LEN parameters. */
10279
10280 tree
gfc_check_pdt_dummy(gfc_symbol * der_type,tree decl,int rank,gfc_actual_arglist * param_list)10281 gfc_check_pdt_dummy (gfc_symbol * der_type, tree decl, int rank,
10282 gfc_actual_arglist *param_list)
10283 {
10284 tree res;
10285 gfc_actual_arglist *old_param_list = pdt_param_list;
10286 pdt_param_list = param_list;
10287 res = structure_alloc_comps (der_type, decl, NULL_TREE, rank,
10288 CHECK_PDT_DUMMY, 0, NULL);
10289 pdt_param_list = old_param_list;
10290 return res;
10291 }
10292
10293
10294 /* Returns the value of LBOUND for an expression. This could be broken out
10295 from gfc_conv_intrinsic_bound but this seemed to be simpler. This is
10296 called by gfc_alloc_allocatable_for_assignment. */
10297 static tree
get_std_lbound(gfc_expr * expr,tree desc,int dim,bool assumed_size)10298 get_std_lbound (gfc_expr *expr, tree desc, int dim, bool assumed_size)
10299 {
10300 tree lbound;
10301 tree ubound;
10302 tree stride;
10303 tree cond, cond1, cond3, cond4;
10304 tree tmp;
10305 gfc_ref *ref;
10306
10307 if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (desc)))
10308 {
10309 tmp = gfc_rank_cst[dim];
10310 lbound = gfc_conv_descriptor_lbound_get (desc, tmp);
10311 ubound = gfc_conv_descriptor_ubound_get (desc, tmp);
10312 stride = gfc_conv_descriptor_stride_get (desc, tmp);
10313 cond1 = fold_build2_loc (input_location, GE_EXPR, logical_type_node,
10314 ubound, lbound);
10315 cond3 = fold_build2_loc (input_location, GE_EXPR, logical_type_node,
10316 stride, gfc_index_zero_node);
10317 cond3 = fold_build2_loc (input_location, TRUTH_AND_EXPR,
10318 logical_type_node, cond3, cond1);
10319 cond4 = fold_build2_loc (input_location, LT_EXPR, logical_type_node,
10320 stride, gfc_index_zero_node);
10321 if (assumed_size)
10322 cond = fold_build2_loc (input_location, EQ_EXPR, logical_type_node,
10323 tmp, build_int_cst (gfc_array_index_type,
10324 expr->rank - 1));
10325 else
10326 cond = logical_false_node;
10327
10328 cond1 = fold_build2_loc (input_location, TRUTH_OR_EXPR,
10329 logical_type_node, cond3, cond4);
10330 cond = fold_build2_loc (input_location, TRUTH_OR_EXPR,
10331 logical_type_node, cond, cond1);
10332
10333 return fold_build3_loc (input_location, COND_EXPR,
10334 gfc_array_index_type, cond,
10335 lbound, gfc_index_one_node);
10336 }
10337
10338 if (expr->expr_type == EXPR_FUNCTION)
10339 {
10340 /* A conversion function, so use the argument. */
10341 gcc_assert (expr->value.function.isym
10342 && expr->value.function.isym->conversion);
10343 expr = expr->value.function.actual->expr;
10344 }
10345
10346 if (expr->expr_type == EXPR_VARIABLE)
10347 {
10348 tmp = TREE_TYPE (expr->symtree->n.sym->backend_decl);
10349 for (ref = expr->ref; ref; ref = ref->next)
10350 {
10351 if (ref->type == REF_COMPONENT
10352 && ref->u.c.component->as
10353 && ref->next
10354 && ref->next->u.ar.type == AR_FULL)
10355 tmp = TREE_TYPE (ref->u.c.component->backend_decl);
10356 }
10357 return GFC_TYPE_ARRAY_LBOUND(tmp, dim);
10358 }
10359
10360 return gfc_index_one_node;
10361 }
10362
10363
10364 /* Returns true if an expression represents an lhs that can be reallocated
10365 on assignment. */
10366
10367 bool
gfc_is_reallocatable_lhs(gfc_expr * expr)10368 gfc_is_reallocatable_lhs (gfc_expr *expr)
10369 {
10370 gfc_ref * ref;
10371 gfc_symbol *sym;
10372
10373 if (!expr->ref)
10374 return false;
10375
10376 sym = expr->symtree->n.sym;
10377
10378 if (sym->attr.associate_var && !expr->ref)
10379 return false;
10380
10381 /* An allocatable class variable with no reference. */
10382 if (sym->ts.type == BT_CLASS
10383 && (!sym->attr.associate_var || sym->attr.select_rank_temporary)
10384 && CLASS_DATA (sym)->attr.allocatable
10385 && expr->ref
10386 && ((expr->ref->type == REF_ARRAY && expr->ref->u.ar.type == AR_FULL
10387 && expr->ref->next == NULL)
10388 || (expr->ref->type == REF_COMPONENT
10389 && strcmp (expr->ref->u.c.component->name, "_data") == 0
10390 && (expr->ref->next == NULL
10391 || (expr->ref->next->type == REF_ARRAY
10392 && expr->ref->next->u.ar.type == AR_FULL
10393 && expr->ref->next->next == NULL)))))
10394 return true;
10395
10396 /* An allocatable variable. */
10397 if (sym->attr.allocatable
10398 && (!sym->attr.associate_var || sym->attr.select_rank_temporary)
10399 && expr->ref
10400 && expr->ref->type == REF_ARRAY
10401 && expr->ref->u.ar.type == AR_FULL)
10402 return true;
10403
10404 /* All that can be left are allocatable components. */
10405 if ((sym->ts.type != BT_DERIVED
10406 && sym->ts.type != BT_CLASS)
10407 || !sym->ts.u.derived->attr.alloc_comp)
10408 return false;
10409
10410 /* Find a component ref followed by an array reference. */
10411 for (ref = expr->ref; ref; ref = ref->next)
10412 if (ref->next
10413 && ref->type == REF_COMPONENT
10414 && ref->next->type == REF_ARRAY
10415 && !ref->next->next)
10416 break;
10417
10418 if (!ref)
10419 return false;
10420
10421 /* Return true if valid reallocatable lhs. */
10422 if (ref->u.c.component->attr.allocatable
10423 && ref->next->u.ar.type == AR_FULL)
10424 return true;
10425
10426 return false;
10427 }
10428
10429
10430 static tree
concat_str_length(gfc_expr * expr)10431 concat_str_length (gfc_expr* expr)
10432 {
10433 tree type;
10434 tree len1;
10435 tree len2;
10436 gfc_se se;
10437
10438 type = gfc_typenode_for_spec (&expr->value.op.op1->ts);
10439 len1 = TYPE_MAX_VALUE (TYPE_DOMAIN (type));
10440 if (len1 == NULL_TREE)
10441 {
10442 if (expr->value.op.op1->expr_type == EXPR_OP)
10443 len1 = concat_str_length (expr->value.op.op1);
10444 else if (expr->value.op.op1->expr_type == EXPR_CONSTANT)
10445 len1 = build_int_cst (gfc_charlen_type_node,
10446 expr->value.op.op1->value.character.length);
10447 else if (expr->value.op.op1->ts.u.cl->length)
10448 {
10449 gfc_init_se (&se, NULL);
10450 gfc_conv_expr (&se, expr->value.op.op1->ts.u.cl->length);
10451 len1 = se.expr;
10452 }
10453 else
10454 {
10455 /* Last resort! */
10456 gfc_init_se (&se, NULL);
10457 se.want_pointer = 1;
10458 se.descriptor_only = 1;
10459 gfc_conv_expr (&se, expr->value.op.op1);
10460 len1 = se.string_length;
10461 }
10462 }
10463
10464 type = gfc_typenode_for_spec (&expr->value.op.op2->ts);
10465 len2 = TYPE_MAX_VALUE (TYPE_DOMAIN (type));
10466 if (len2 == NULL_TREE)
10467 {
10468 if (expr->value.op.op2->expr_type == EXPR_OP)
10469 len2 = concat_str_length (expr->value.op.op2);
10470 else if (expr->value.op.op2->expr_type == EXPR_CONSTANT)
10471 len2 = build_int_cst (gfc_charlen_type_node,
10472 expr->value.op.op2->value.character.length);
10473 else if (expr->value.op.op2->ts.u.cl->length)
10474 {
10475 gfc_init_se (&se, NULL);
10476 gfc_conv_expr (&se, expr->value.op.op2->ts.u.cl->length);
10477 len2 = se.expr;
10478 }
10479 else
10480 {
10481 /* Last resort! */
10482 gfc_init_se (&se, NULL);
10483 se.want_pointer = 1;
10484 se.descriptor_only = 1;
10485 gfc_conv_expr (&se, expr->value.op.op2);
10486 len2 = se.string_length;
10487 }
10488 }
10489
10490 gcc_assert(len1 && len2);
10491 len1 = fold_convert (gfc_charlen_type_node, len1);
10492 len2 = fold_convert (gfc_charlen_type_node, len2);
10493
10494 return fold_build2_loc (input_location, PLUS_EXPR,
10495 gfc_charlen_type_node, len1, len2);
10496 }
10497
10498
10499 /* Allocate the lhs of an assignment to an allocatable array, otherwise
10500 reallocate it. */
10501
10502 tree
gfc_alloc_allocatable_for_assignment(gfc_loopinfo * loop,gfc_expr * expr1,gfc_expr * expr2)10503 gfc_alloc_allocatable_for_assignment (gfc_loopinfo *loop,
10504 gfc_expr *expr1,
10505 gfc_expr *expr2)
10506 {
10507 stmtblock_t realloc_block;
10508 stmtblock_t alloc_block;
10509 stmtblock_t fblock;
10510 gfc_ss *rss;
10511 gfc_ss *lss;
10512 gfc_array_info *linfo;
10513 tree realloc_expr;
10514 tree alloc_expr;
10515 tree size1;
10516 tree size2;
10517 tree elemsize1;
10518 tree elemsize2;
10519 tree array1;
10520 tree cond_null;
10521 tree cond;
10522 tree tmp;
10523 tree tmp2;
10524 tree lbound;
10525 tree ubound;
10526 tree desc;
10527 tree old_desc;
10528 tree desc2;
10529 tree offset;
10530 tree jump_label1;
10531 tree jump_label2;
10532 tree neq_size;
10533 tree lbd;
10534 tree class_expr2 = NULL_TREE;
10535 int n;
10536 int dim;
10537 gfc_array_spec * as;
10538 bool coarray = (flag_coarray == GFC_FCOARRAY_LIB
10539 && gfc_caf_attr (expr1, true).codimension);
10540 tree token;
10541 gfc_se caf_se;
10542
10543 /* x = f(...) with x allocatable. In this case, expr1 is the rhs.
10544 Find the lhs expression in the loop chain and set expr1 and
10545 expr2 accordingly. */
10546 if (expr1->expr_type == EXPR_FUNCTION && expr2 == NULL)
10547 {
10548 expr2 = expr1;
10549 /* Find the ss for the lhs. */
10550 lss = loop->ss;
10551 for (; lss && lss != gfc_ss_terminator; lss = lss->loop_chain)
10552 if (lss->info->expr && lss->info->expr->expr_type == EXPR_VARIABLE)
10553 break;
10554 if (lss == gfc_ss_terminator)
10555 return NULL_TREE;
10556 expr1 = lss->info->expr;
10557 }
10558
10559 /* Bail out if this is not a valid allocate on assignment. */
10560 if (!gfc_is_reallocatable_lhs (expr1)
10561 || (expr2 && !expr2->rank))
10562 return NULL_TREE;
10563
10564 /* Find the ss for the lhs. */
10565 lss = loop->ss;
10566 for (; lss && lss != gfc_ss_terminator; lss = lss->loop_chain)
10567 if (lss->info->expr == expr1)
10568 break;
10569
10570 if (lss == gfc_ss_terminator)
10571 return NULL_TREE;
10572
10573 linfo = &lss->info->data.array;
10574
10575 /* Find an ss for the rhs. For operator expressions, we see the
10576 ss's for the operands. Any one of these will do. */
10577 rss = loop->ss;
10578 for (; rss && rss != gfc_ss_terminator; rss = rss->loop_chain)
10579 if (rss->info->expr != expr1 && rss != loop->temp_ss)
10580 break;
10581
10582 if (expr2 && rss == gfc_ss_terminator)
10583 return NULL_TREE;
10584
10585 /* Ensure that the string length from the current scope is used. */
10586 if (expr2->ts.type == BT_CHARACTER
10587 && expr2->expr_type == EXPR_FUNCTION
10588 && !expr2->value.function.isym)
10589 expr2->ts.u.cl->backend_decl = rss->info->string_length;
10590
10591 gfc_start_block (&fblock);
10592
10593 /* Since the lhs is allocatable, this must be a descriptor type.
10594 Get the data and array size. */
10595 desc = linfo->descriptor;
10596 gcc_assert (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (desc)));
10597 array1 = gfc_conv_descriptor_data_get (desc);
10598
10599 if (expr2)
10600 desc2 = rss->info->data.array.descriptor;
10601 else
10602 desc2 = NULL_TREE;
10603
10604 /* Get the old lhs element size for deferred character and class expr1. */
10605 if (expr1->ts.type == BT_CHARACTER && expr1->ts.deferred)
10606 {
10607 if (expr1->ts.u.cl->backend_decl
10608 && VAR_P (expr1->ts.u.cl->backend_decl))
10609 elemsize1 = expr1->ts.u.cl->backend_decl;
10610 else
10611 elemsize1 = lss->info->string_length;
10612 }
10613 else if (expr1->ts.type == BT_CLASS)
10614 {
10615 /* Unfortunately, the lhs vptr is set too early in many cases.
10616 Play it safe by using the descriptor element length. */
10617 tmp = gfc_conv_descriptor_elem_len (desc);
10618 elemsize1 = fold_convert (gfc_array_index_type, tmp);
10619 }
10620 else
10621 elemsize1 = NULL_TREE;
10622 if (elemsize1 != NULL_TREE)
10623 elemsize1 = gfc_evaluate_now (elemsize1, &fblock);
10624
10625 /* Get the new lhs size in bytes. */
10626 if (expr1->ts.type == BT_CHARACTER && expr1->ts.deferred)
10627 {
10628 if (expr2->ts.deferred)
10629 {
10630 if (expr2->ts.u.cl->backend_decl
10631 && VAR_P (expr2->ts.u.cl->backend_decl))
10632 tmp = expr2->ts.u.cl->backend_decl;
10633 else
10634 tmp = rss->info->string_length;
10635 }
10636 else
10637 {
10638 tmp = expr2->ts.u.cl->backend_decl;
10639 if (!tmp && expr2->expr_type == EXPR_OP
10640 && expr2->value.op.op == INTRINSIC_CONCAT)
10641 {
10642 tmp = concat_str_length (expr2);
10643 expr2->ts.u.cl->backend_decl = gfc_evaluate_now (tmp, &fblock);
10644 }
10645 else if (!tmp && expr2->ts.u.cl->length)
10646 {
10647 gfc_se tmpse;
10648 gfc_init_se (&tmpse, NULL);
10649 gfc_conv_expr_type (&tmpse, expr2->ts.u.cl->length,
10650 gfc_charlen_type_node);
10651 tmp = tmpse.expr;
10652 expr2->ts.u.cl->backend_decl = gfc_evaluate_now (tmp, &fblock);
10653 }
10654 tmp = fold_convert (TREE_TYPE (expr1->ts.u.cl->backend_decl), tmp);
10655 }
10656
10657 if (expr1->ts.u.cl->backend_decl
10658 && VAR_P (expr1->ts.u.cl->backend_decl))
10659 gfc_add_modify (&fblock, expr1->ts.u.cl->backend_decl, tmp);
10660 else
10661 gfc_add_modify (&fblock, lss->info->string_length, tmp);
10662
10663 if (expr1->ts.kind > 1)
10664 tmp = fold_build2_loc (input_location, MULT_EXPR,
10665 TREE_TYPE (tmp),
10666 tmp, build_int_cst (TREE_TYPE (tmp),
10667 expr1->ts.kind));
10668 }
10669 else if (expr1->ts.type == BT_CHARACTER && expr1->ts.u.cl->backend_decl)
10670 {
10671 tmp = TYPE_SIZE_UNIT (TREE_TYPE (gfc_typenode_for_spec (&expr1->ts)));
10672 tmp = fold_build2_loc (input_location, MULT_EXPR,
10673 gfc_array_index_type, tmp,
10674 expr1->ts.u.cl->backend_decl);
10675 }
10676 else if (UNLIMITED_POLY (expr1) && expr2->ts.type != BT_CLASS)
10677 tmp = TYPE_SIZE_UNIT (gfc_typenode_for_spec (&expr2->ts));
10678 else if (expr1->ts.type == BT_CLASS && expr2->ts.type == BT_CLASS)
10679 {
10680 tmp = expr2->rank ? gfc_get_class_from_expr (desc2) : NULL_TREE;
10681 if (tmp == NULL_TREE && expr2->expr_type == EXPR_VARIABLE)
10682 tmp = class_expr2 = gfc_get_class_from_gfc_expr (expr2);
10683
10684 if (tmp != NULL_TREE)
10685 tmp = gfc_class_vtab_size_get (tmp);
10686 else
10687 tmp = TYPE_SIZE_UNIT (gfc_typenode_for_spec (&CLASS_DATA (expr2)->ts));
10688 }
10689 else
10690 tmp = TYPE_SIZE_UNIT (gfc_typenode_for_spec (&expr2->ts));
10691 elemsize2 = fold_convert (gfc_array_index_type, tmp);
10692 elemsize2 = gfc_evaluate_now (elemsize2, &fblock);
10693
10694 /* 7.4.1.3 "If variable is an allocated allocatable variable, it is
10695 deallocated if expr is an array of different shape or any of the
10696 corresponding length type parameter values of variable and expr
10697 differ." This assures F95 compatibility. */
10698 jump_label1 = gfc_build_label_decl (NULL_TREE);
10699 jump_label2 = gfc_build_label_decl (NULL_TREE);
10700
10701 /* Allocate if data is NULL. */
10702 cond_null = fold_build2_loc (input_location, EQ_EXPR, logical_type_node,
10703 array1, build_int_cst (TREE_TYPE (array1), 0));
10704
10705 if (expr1->ts.type == BT_CHARACTER && expr1->ts.deferred)
10706 {
10707 tmp = fold_build2_loc (input_location, NE_EXPR,
10708 logical_type_node,
10709 lss->info->string_length,
10710 rss->info->string_length);
10711 cond_null = fold_build2_loc (input_location, TRUTH_OR_EXPR,
10712 logical_type_node, tmp, cond_null);
10713 cond_null= gfc_evaluate_now (cond_null, &fblock);
10714 }
10715 else
10716 cond_null= gfc_evaluate_now (cond_null, &fblock);
10717
10718 tmp = build3_v (COND_EXPR, cond_null,
10719 build1_v (GOTO_EXPR, jump_label1),
10720 build_empty_stmt (input_location));
10721 gfc_add_expr_to_block (&fblock, tmp);
10722
10723 /* Get arrayspec if expr is a full array. */
10724 if (expr2 && expr2->expr_type == EXPR_FUNCTION
10725 && expr2->value.function.isym
10726 && expr2->value.function.isym->conversion)
10727 {
10728 /* For conversion functions, take the arg. */
10729 gfc_expr *arg = expr2->value.function.actual->expr;
10730 as = gfc_get_full_arrayspec_from_expr (arg);
10731 }
10732 else if (expr2)
10733 as = gfc_get_full_arrayspec_from_expr (expr2);
10734 else
10735 as = NULL;
10736
10737 /* If the lhs shape is not the same as the rhs jump to setting the
10738 bounds and doing the reallocation....... */
10739 for (n = 0; n < expr1->rank; n++)
10740 {
10741 /* Check the shape. */
10742 lbound = gfc_conv_descriptor_lbound_get (desc, gfc_rank_cst[n]);
10743 ubound = gfc_conv_descriptor_ubound_get (desc, gfc_rank_cst[n]);
10744 tmp = fold_build2_loc (input_location, MINUS_EXPR,
10745 gfc_array_index_type,
10746 loop->to[n], loop->from[n]);
10747 tmp = fold_build2_loc (input_location, PLUS_EXPR,
10748 gfc_array_index_type,
10749 tmp, lbound);
10750 tmp = fold_build2_loc (input_location, MINUS_EXPR,
10751 gfc_array_index_type,
10752 tmp, ubound);
10753 cond = fold_build2_loc (input_location, NE_EXPR,
10754 logical_type_node,
10755 tmp, gfc_index_zero_node);
10756 tmp = build3_v (COND_EXPR, cond,
10757 build1_v (GOTO_EXPR, jump_label1),
10758 build_empty_stmt (input_location));
10759 gfc_add_expr_to_block (&fblock, tmp);
10760 }
10761
10762 /* ...else if the element lengths are not the same also go to
10763 setting the bounds and doing the reallocation.... */
10764 if (elemsize1 != NULL_TREE)
10765 {
10766 cond = fold_build2_loc (input_location, NE_EXPR,
10767 logical_type_node,
10768 elemsize1, elemsize2);
10769 tmp = build3_v (COND_EXPR, cond,
10770 build1_v (GOTO_EXPR, jump_label1),
10771 build_empty_stmt (input_location));
10772 gfc_add_expr_to_block (&fblock, tmp);
10773 }
10774
10775 /* ....else jump past the (re)alloc code. */
10776 tmp = build1_v (GOTO_EXPR, jump_label2);
10777 gfc_add_expr_to_block (&fblock, tmp);
10778
10779 /* Add the label to start automatic (re)allocation. */
10780 tmp = build1_v (LABEL_EXPR, jump_label1);
10781 gfc_add_expr_to_block (&fblock, tmp);
10782
10783 /* If the lhs has not been allocated, its bounds will not have been
10784 initialized and so its size is set to zero. */
10785 size1 = gfc_create_var (gfc_array_index_type, NULL);
10786 gfc_init_block (&alloc_block);
10787 gfc_add_modify (&alloc_block, size1, gfc_index_zero_node);
10788 gfc_init_block (&realloc_block);
10789 gfc_add_modify (&realloc_block, size1,
10790 gfc_conv_descriptor_size (desc, expr1->rank));
10791 tmp = build3_v (COND_EXPR, cond_null,
10792 gfc_finish_block (&alloc_block),
10793 gfc_finish_block (&realloc_block));
10794 gfc_add_expr_to_block (&fblock, tmp);
10795
10796 /* Get the rhs size and fix it. */
10797 size2 = gfc_index_one_node;
10798 for (n = 0; n < expr2->rank; n++)
10799 {
10800 tmp = fold_build2_loc (input_location, MINUS_EXPR,
10801 gfc_array_index_type,
10802 loop->to[n], loop->from[n]);
10803 tmp = fold_build2_loc (input_location, PLUS_EXPR,
10804 gfc_array_index_type,
10805 tmp, gfc_index_one_node);
10806 size2 = fold_build2_loc (input_location, MULT_EXPR,
10807 gfc_array_index_type,
10808 tmp, size2);
10809 }
10810 size2 = gfc_evaluate_now (size2, &fblock);
10811
10812 cond = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
10813 size1, size2);
10814
10815 /* If the lhs is deferred length, assume that the element size
10816 changes and force a reallocation. */
10817 if (expr1->ts.deferred)
10818 neq_size = gfc_evaluate_now (logical_true_node, &fblock);
10819 else
10820 neq_size = gfc_evaluate_now (cond, &fblock);
10821
10822 /* Deallocation of allocatable components will have to occur on
10823 reallocation. Fix the old descriptor now. */
10824 if ((expr1->ts.type == BT_DERIVED)
10825 && expr1->ts.u.derived->attr.alloc_comp)
10826 old_desc = gfc_evaluate_now (desc, &fblock);
10827 else
10828 old_desc = NULL_TREE;
10829
10830 /* Now modify the lhs descriptor and the associated scalarizer
10831 variables. F2003 7.4.1.3: "If variable is or becomes an
10832 unallocated allocatable variable, then it is allocated with each
10833 deferred type parameter equal to the corresponding type parameters
10834 of expr , with the shape of expr , and with each lower bound equal
10835 to the corresponding element of LBOUND(expr)."
10836 Reuse size1 to keep a dimension-by-dimension track of the
10837 stride of the new array. */
10838 size1 = gfc_index_one_node;
10839 offset = gfc_index_zero_node;
10840
10841 for (n = 0; n < expr2->rank; n++)
10842 {
10843 tmp = fold_build2_loc (input_location, MINUS_EXPR,
10844 gfc_array_index_type,
10845 loop->to[n], loop->from[n]);
10846 tmp = fold_build2_loc (input_location, PLUS_EXPR,
10847 gfc_array_index_type,
10848 tmp, gfc_index_one_node);
10849
10850 lbound = gfc_index_one_node;
10851 ubound = tmp;
10852
10853 if (as)
10854 {
10855 lbd = get_std_lbound (expr2, desc2, n,
10856 as->type == AS_ASSUMED_SIZE);
10857 ubound = fold_build2_loc (input_location,
10858 MINUS_EXPR,
10859 gfc_array_index_type,
10860 ubound, lbound);
10861 ubound = fold_build2_loc (input_location,
10862 PLUS_EXPR,
10863 gfc_array_index_type,
10864 ubound, lbd);
10865 lbound = lbd;
10866 }
10867
10868 gfc_conv_descriptor_lbound_set (&fblock, desc,
10869 gfc_rank_cst[n],
10870 lbound);
10871 gfc_conv_descriptor_ubound_set (&fblock, desc,
10872 gfc_rank_cst[n],
10873 ubound);
10874 gfc_conv_descriptor_stride_set (&fblock, desc,
10875 gfc_rank_cst[n],
10876 size1);
10877 lbound = gfc_conv_descriptor_lbound_get (desc,
10878 gfc_rank_cst[n]);
10879 tmp2 = fold_build2_loc (input_location, MULT_EXPR,
10880 gfc_array_index_type,
10881 lbound, size1);
10882 offset = fold_build2_loc (input_location, MINUS_EXPR,
10883 gfc_array_index_type,
10884 offset, tmp2);
10885 size1 = fold_build2_loc (input_location, MULT_EXPR,
10886 gfc_array_index_type,
10887 tmp, size1);
10888 }
10889
10890 /* Set the lhs descriptor and scalarizer offsets. For rank > 1,
10891 the array offset is saved and the info.offset is used for a
10892 running offset. Use the saved_offset instead. */
10893 tmp = gfc_conv_descriptor_offset (desc);
10894 gfc_add_modify (&fblock, tmp, offset);
10895 if (linfo->saved_offset
10896 && VAR_P (linfo->saved_offset))
10897 gfc_add_modify (&fblock, linfo->saved_offset, tmp);
10898
10899 /* Now set the deltas for the lhs. */
10900 for (n = 0; n < expr1->rank; n++)
10901 {
10902 tmp = gfc_conv_descriptor_lbound_get (desc, gfc_rank_cst[n]);
10903 dim = lss->dim[n];
10904 tmp = fold_build2_loc (input_location, MINUS_EXPR,
10905 gfc_array_index_type, tmp,
10906 loop->from[dim]);
10907 if (linfo->delta[dim] && VAR_P (linfo->delta[dim]))
10908 gfc_add_modify (&fblock, linfo->delta[dim], tmp);
10909 }
10910
10911 if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (desc)))
10912 gfc_conv_descriptor_span_set (&fblock, desc, elemsize2);
10913
10914 size2 = fold_build2_loc (input_location, MULT_EXPR,
10915 gfc_array_index_type,
10916 elemsize2, size2);
10917 size2 = fold_convert (size_type_node, size2);
10918 size2 = fold_build2_loc (input_location, MAX_EXPR, size_type_node,
10919 size2, size_one_node);
10920 size2 = gfc_evaluate_now (size2, &fblock);
10921
10922 /* For deferred character length, the 'size' field of the dtype might
10923 have changed so set the dtype. */
10924 if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (desc))
10925 && expr1->ts.type == BT_CHARACTER && expr1->ts.deferred)
10926 {
10927 tree type;
10928 tmp = gfc_conv_descriptor_dtype (desc);
10929 if (expr2->ts.u.cl->backend_decl)
10930 type = gfc_typenode_for_spec (&expr2->ts);
10931 else
10932 type = gfc_typenode_for_spec (&expr1->ts);
10933
10934 gfc_add_modify (&fblock, tmp,
10935 gfc_get_dtype_rank_type (expr1->rank,type));
10936 }
10937 else if (expr1->ts.type == BT_CLASS)
10938 {
10939 tree type;
10940 tmp = gfc_conv_descriptor_dtype (desc);
10941
10942 if (expr2->ts.type != BT_CLASS)
10943 type = gfc_typenode_for_spec (&expr2->ts);
10944 else
10945 type = gfc_get_character_type_len (1, elemsize2);
10946
10947 gfc_add_modify (&fblock, tmp,
10948 gfc_get_dtype_rank_type (expr2->rank,type));
10949 /* Set the _len field as well... */
10950 if (UNLIMITED_POLY (expr1))
10951 {
10952 tmp = gfc_class_len_get (TREE_OPERAND (desc, 0));
10953 if (expr2->ts.type == BT_CHARACTER)
10954 gfc_add_modify (&fblock, tmp,
10955 fold_convert (TREE_TYPE (tmp),
10956 TYPE_SIZE_UNIT (type)));
10957 else
10958 gfc_add_modify (&fblock, tmp,
10959 build_int_cst (TREE_TYPE (tmp), 0));
10960 }
10961 /* ...and the vptr. */
10962 tmp = gfc_class_vptr_get (TREE_OPERAND (desc, 0));
10963 if (expr2->ts.type == BT_CLASS && !VAR_P (desc2)
10964 && TREE_CODE (desc2) == COMPONENT_REF)
10965 {
10966 tmp2 = gfc_get_class_from_expr (desc2);
10967 tmp2 = gfc_class_vptr_get (tmp2);
10968 }
10969 else if (expr2->ts.type == BT_CLASS && class_expr2 != NULL_TREE)
10970 tmp2 = gfc_class_vptr_get (class_expr2);
10971 else
10972 {
10973 tmp2 = gfc_get_symbol_decl (gfc_find_vtab (&expr2->ts));
10974 tmp2 = gfc_build_addr_expr (TREE_TYPE (tmp), tmp2);
10975 }
10976
10977 gfc_add_modify (&fblock, tmp, fold_convert (TREE_TYPE (tmp), tmp2));
10978 }
10979 else if (coarray && GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (desc)))
10980 {
10981 gfc_add_modify (&fblock, gfc_conv_descriptor_dtype (desc),
10982 gfc_get_dtype (TREE_TYPE (desc)));
10983 }
10984
10985 /* Realloc expression. Note that the scalarizer uses desc.data
10986 in the array reference - (*desc.data)[<element>]. */
10987 gfc_init_block (&realloc_block);
10988 gfc_init_se (&caf_se, NULL);
10989
10990 if (coarray)
10991 {
10992 token = gfc_get_ultimate_alloc_ptr_comps_caf_token (&caf_se, expr1);
10993 if (token == NULL_TREE)
10994 {
10995 tmp = gfc_get_tree_for_caf_expr (expr1);
10996 if (POINTER_TYPE_P (TREE_TYPE (tmp)))
10997 tmp = build_fold_indirect_ref (tmp);
10998 gfc_get_caf_token_offset (&caf_se, &token, NULL, tmp, NULL_TREE,
10999 expr1);
11000 token = gfc_build_addr_expr (NULL_TREE, token);
11001 }
11002
11003 gfc_add_block_to_block (&realloc_block, &caf_se.pre);
11004 }
11005 if ((expr1->ts.type == BT_DERIVED)
11006 && expr1->ts.u.derived->attr.alloc_comp)
11007 {
11008 tmp = gfc_deallocate_alloc_comp_no_caf (expr1->ts.u.derived, old_desc,
11009 expr1->rank);
11010 gfc_add_expr_to_block (&realloc_block, tmp);
11011 }
11012
11013 if (!coarray)
11014 {
11015 tmp = build_call_expr_loc (input_location,
11016 builtin_decl_explicit (BUILT_IN_REALLOC), 2,
11017 fold_convert (pvoid_type_node, array1),
11018 size2);
11019 gfc_conv_descriptor_data_set (&realloc_block,
11020 desc, tmp);
11021 }
11022 else
11023 {
11024 tmp = build_call_expr_loc (input_location,
11025 gfor_fndecl_caf_deregister, 5, token,
11026 build_int_cst (integer_type_node,
11027 GFC_CAF_COARRAY_DEALLOCATE_ONLY),
11028 null_pointer_node, null_pointer_node,
11029 integer_zero_node);
11030 gfc_add_expr_to_block (&realloc_block, tmp);
11031 tmp = build_call_expr_loc (input_location,
11032 gfor_fndecl_caf_register,
11033 7, size2,
11034 build_int_cst (integer_type_node,
11035 GFC_CAF_COARRAY_ALLOC_ALLOCATE_ONLY),
11036 token, gfc_build_addr_expr (NULL_TREE, desc),
11037 null_pointer_node, null_pointer_node,
11038 integer_zero_node);
11039 gfc_add_expr_to_block (&realloc_block, tmp);
11040 }
11041
11042 if ((expr1->ts.type == BT_DERIVED)
11043 && expr1->ts.u.derived->attr.alloc_comp)
11044 {
11045 tmp = gfc_nullify_alloc_comp (expr1->ts.u.derived, desc,
11046 expr1->rank);
11047 gfc_add_expr_to_block (&realloc_block, tmp);
11048 }
11049
11050 gfc_add_block_to_block (&realloc_block, &caf_se.post);
11051 realloc_expr = gfc_finish_block (&realloc_block);
11052
11053 /* Reallocate if sizes or dynamic types are different. */
11054 if (elemsize1)
11055 {
11056 tmp = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
11057 elemsize1, elemsize2);
11058 tmp = gfc_evaluate_now (tmp, &fblock);
11059 neq_size = fold_build2_loc (input_location, TRUTH_OR_EXPR,
11060 logical_type_node, neq_size, tmp);
11061 }
11062 tmp = build3_v (COND_EXPR, neq_size, realloc_expr,
11063 build_empty_stmt (input_location));
11064
11065 realloc_expr = tmp;
11066
11067 /* Malloc expression. */
11068 gfc_init_block (&alloc_block);
11069 if (!coarray)
11070 {
11071 tmp = build_call_expr_loc (input_location,
11072 builtin_decl_explicit (BUILT_IN_MALLOC),
11073 1, size2);
11074 gfc_conv_descriptor_data_set (&alloc_block,
11075 desc, tmp);
11076 }
11077 else
11078 {
11079 tmp = build_call_expr_loc (input_location,
11080 gfor_fndecl_caf_register,
11081 7, size2,
11082 build_int_cst (integer_type_node,
11083 GFC_CAF_COARRAY_ALLOC),
11084 token, gfc_build_addr_expr (NULL_TREE, desc),
11085 null_pointer_node, null_pointer_node,
11086 integer_zero_node);
11087 gfc_add_expr_to_block (&alloc_block, tmp);
11088 }
11089
11090
11091 /* We already set the dtype in the case of deferred character
11092 length arrays and class lvalues. */
11093 if (!(GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (desc))
11094 && ((expr1->ts.type == BT_CHARACTER && expr1->ts.deferred)
11095 || coarray))
11096 && expr1->ts.type != BT_CLASS)
11097 {
11098 tmp = gfc_conv_descriptor_dtype (desc);
11099 gfc_add_modify (&alloc_block, tmp, gfc_get_dtype (TREE_TYPE (desc)));
11100 }
11101
11102 if ((expr1->ts.type == BT_DERIVED)
11103 && expr1->ts.u.derived->attr.alloc_comp)
11104 {
11105 tmp = gfc_nullify_alloc_comp (expr1->ts.u.derived, desc,
11106 expr1->rank);
11107 gfc_add_expr_to_block (&alloc_block, tmp);
11108 }
11109 alloc_expr = gfc_finish_block (&alloc_block);
11110
11111 /* Malloc if not allocated; realloc otherwise. */
11112 tmp = build3_v (COND_EXPR, cond_null, alloc_expr, realloc_expr);
11113 gfc_add_expr_to_block (&fblock, tmp);
11114
11115 /* Make sure that the scalarizer data pointer is updated. */
11116 if (linfo->data && VAR_P (linfo->data))
11117 {
11118 tmp = gfc_conv_descriptor_data_get (desc);
11119 gfc_add_modify (&fblock, linfo->data, tmp);
11120 }
11121
11122 /* Add the label for same shape lhs and rhs. */
11123 tmp = build1_v (LABEL_EXPR, jump_label2);
11124 gfc_add_expr_to_block (&fblock, tmp);
11125
11126 return gfc_finish_block (&fblock);
11127 }
11128
11129
11130 /* Initialize class descriptor's TKR infomation. */
11131
11132 void
gfc_trans_class_array(gfc_symbol * sym,gfc_wrapped_block * block)11133 gfc_trans_class_array (gfc_symbol * sym, gfc_wrapped_block * block)
11134 {
11135 tree type, etype;
11136 tree tmp;
11137 tree descriptor;
11138 stmtblock_t init;
11139 locus loc;
11140 int rank;
11141
11142 /* Make sure the frontend gets these right. */
11143 gcc_assert (sym->ts.type == BT_CLASS && CLASS_DATA (sym)
11144 && (CLASS_DATA (sym)->attr.class_pointer
11145 || CLASS_DATA (sym)->attr.allocatable));
11146
11147 gcc_assert (VAR_P (sym->backend_decl)
11148 || TREE_CODE (sym->backend_decl) == PARM_DECL);
11149
11150 if (sym->attr.dummy)
11151 return;
11152
11153 descriptor = gfc_class_data_get (sym->backend_decl);
11154 type = TREE_TYPE (descriptor);
11155
11156 if (type == NULL || !GFC_DESCRIPTOR_TYPE_P (type))
11157 return;
11158
11159 gfc_save_backend_locus (&loc);
11160 gfc_set_backend_locus (&sym->declared_at);
11161 gfc_init_block (&init);
11162
11163 rank = CLASS_DATA (sym)->as ? (CLASS_DATA (sym)->as->rank) : (0);
11164 gcc_assert (rank>=0);
11165 tmp = gfc_conv_descriptor_dtype (descriptor);
11166 etype = gfc_get_element_type (type);
11167 tmp = fold_build2_loc (input_location, MODIFY_EXPR, TREE_TYPE (tmp), tmp,
11168 gfc_get_dtype_rank_type (rank, etype));
11169 gfc_add_expr_to_block (&init, tmp);
11170
11171 gfc_add_init_cleanup (block, gfc_finish_block (&init), NULL_TREE);
11172 gfc_restore_backend_locus (&loc);
11173 }
11174
11175
11176 /* NULLIFY an allocatable/pointer array on function entry, free it on exit.
11177 Do likewise, recursively if necessary, with the allocatable components of
11178 derived types. This function is also called for assumed-rank arrays, which
11179 are always dummy arguments. */
11180
11181 void
gfc_trans_deferred_array(gfc_symbol * sym,gfc_wrapped_block * block)11182 gfc_trans_deferred_array (gfc_symbol * sym, gfc_wrapped_block * block)
11183 {
11184 tree type;
11185 tree tmp;
11186 tree descriptor;
11187 stmtblock_t init;
11188 stmtblock_t cleanup;
11189 locus loc;
11190 int rank;
11191 bool sym_has_alloc_comp, has_finalizer;
11192
11193 sym_has_alloc_comp = (sym->ts.type == BT_DERIVED
11194 || sym->ts.type == BT_CLASS)
11195 && sym->ts.u.derived->attr.alloc_comp;
11196 has_finalizer = sym->ts.type == BT_CLASS || sym->ts.type == BT_DERIVED
11197 ? gfc_is_finalizable (sym->ts.u.derived, NULL) : false;
11198
11199 /* Make sure the frontend gets these right. */
11200 gcc_assert (sym->attr.pointer || sym->attr.allocatable || sym_has_alloc_comp
11201 || has_finalizer
11202 || (sym->as->type == AS_ASSUMED_RANK && sym->attr.dummy));
11203
11204 gfc_save_backend_locus (&loc);
11205 gfc_set_backend_locus (&sym->declared_at);
11206 gfc_init_block (&init);
11207
11208 gcc_assert (VAR_P (sym->backend_decl)
11209 || TREE_CODE (sym->backend_decl) == PARM_DECL);
11210
11211 if (sym->ts.type == BT_CHARACTER
11212 && !INTEGER_CST_P (sym->ts.u.cl->backend_decl))
11213 {
11214 gfc_conv_string_length (sym->ts.u.cl, NULL, &init);
11215 gfc_trans_vla_type_sizes (sym, &init);
11216 }
11217
11218 /* Dummy, use associated and result variables don't need anything special. */
11219 if (sym->attr.dummy || sym->attr.use_assoc || sym->attr.result)
11220 {
11221 gfc_add_init_cleanup (block, gfc_finish_block (&init), NULL_TREE);
11222 gfc_restore_backend_locus (&loc);
11223 return;
11224 }
11225
11226 descriptor = sym->backend_decl;
11227
11228 /* Although static, derived types with default initializers and
11229 allocatable components must not be nulled wholesale; instead they
11230 are treated component by component. */
11231 if (TREE_STATIC (descriptor) && !sym_has_alloc_comp && !has_finalizer)
11232 {
11233 /* SAVEd variables are not freed on exit. */
11234 gfc_trans_static_array_pointer (sym);
11235
11236 gfc_add_init_cleanup (block, gfc_finish_block (&init), NULL_TREE);
11237 gfc_restore_backend_locus (&loc);
11238 return;
11239 }
11240
11241 /* Get the descriptor type. */
11242 type = TREE_TYPE (sym->backend_decl);
11243
11244 if ((sym_has_alloc_comp || (has_finalizer && sym->ts.type != BT_CLASS))
11245 && !(sym->attr.pointer || sym->attr.allocatable))
11246 {
11247 if (!sym->attr.save
11248 && !(TREE_STATIC (sym->backend_decl) && sym->attr.is_main_program))
11249 {
11250 if (sym->value == NULL
11251 || !gfc_has_default_initializer (sym->ts.u.derived))
11252 {
11253 rank = sym->as ? sym->as->rank : 0;
11254 tmp = gfc_nullify_alloc_comp (sym->ts.u.derived,
11255 descriptor, rank);
11256 gfc_add_expr_to_block (&init, tmp);
11257 }
11258 else
11259 gfc_init_default_dt (sym, &init, false);
11260 }
11261 }
11262 else if (!GFC_DESCRIPTOR_TYPE_P (type))
11263 {
11264 /* If the backend_decl is not a descriptor, we must have a pointer
11265 to one. */
11266 descriptor = build_fold_indirect_ref_loc (input_location,
11267 sym->backend_decl);
11268 type = TREE_TYPE (descriptor);
11269 }
11270
11271 /* NULLIFY the data pointer, for non-saved allocatables. */
11272 if (GFC_DESCRIPTOR_TYPE_P (type) && !sym->attr.save && sym->attr.allocatable)
11273 {
11274 gfc_conv_descriptor_data_set (&init, descriptor, null_pointer_node);
11275 if (flag_coarray == GFC_FCOARRAY_LIB && sym->attr.codimension)
11276 {
11277 /* Declare the variable static so its array descriptor stays present
11278 after leaving the scope. It may still be accessed through another
11279 image. This may happen, for example, with the caf_mpi
11280 implementation. */
11281 TREE_STATIC (descriptor) = 1;
11282 tmp = gfc_conv_descriptor_token (descriptor);
11283 gfc_add_modify (&init, tmp, fold_convert (TREE_TYPE (tmp),
11284 null_pointer_node));
11285 }
11286 }
11287
11288 /* Set initial TKR for pointers and allocatables */
11289 if (GFC_DESCRIPTOR_TYPE_P (type)
11290 && (sym->attr.pointer || sym->attr.allocatable))
11291 {
11292 tree etype;
11293
11294 gcc_assert (sym->as && sym->as->rank>=0);
11295 tmp = gfc_conv_descriptor_dtype (descriptor);
11296 etype = gfc_get_element_type (type);
11297 tmp = fold_build2_loc (input_location, MODIFY_EXPR,
11298 TREE_TYPE (tmp), tmp,
11299 gfc_get_dtype_rank_type (sym->as->rank, etype));
11300 gfc_add_expr_to_block (&init, tmp);
11301 }
11302 gfc_restore_backend_locus (&loc);
11303 gfc_init_block (&cleanup);
11304
11305 /* Allocatable arrays need to be freed when they go out of scope.
11306 The allocatable components of pointers must not be touched. */
11307 if (!sym->attr.allocatable && has_finalizer && sym->ts.type != BT_CLASS
11308 && !sym->attr.pointer && !sym->attr.artificial && !sym->attr.save
11309 && !sym->ns->proc_name->attr.is_main_program)
11310 {
11311 gfc_expr *e;
11312 sym->attr.referenced = 1;
11313 e = gfc_lval_expr_from_sym (sym);
11314 gfc_add_finalizer_call (&cleanup, e);
11315 gfc_free_expr (e);
11316 }
11317 else if ((!sym->attr.allocatable || !has_finalizer)
11318 && sym_has_alloc_comp && !(sym->attr.function || sym->attr.result)
11319 && !sym->attr.pointer && !sym->attr.save
11320 && !sym->ns->proc_name->attr.is_main_program)
11321 {
11322 int rank;
11323 rank = sym->as ? sym->as->rank : 0;
11324 tmp = gfc_deallocate_alloc_comp (sym->ts.u.derived, descriptor, rank);
11325 gfc_add_expr_to_block (&cleanup, tmp);
11326 }
11327
11328 if (sym->attr.allocatable && (sym->attr.dimension || sym->attr.codimension)
11329 && !sym->attr.save && !sym->attr.result
11330 && !sym->ns->proc_name->attr.is_main_program)
11331 {
11332 gfc_expr *e;
11333 e = has_finalizer ? gfc_lval_expr_from_sym (sym) : NULL;
11334 tmp = gfc_deallocate_with_status (sym->backend_decl, NULL_TREE, NULL_TREE,
11335 NULL_TREE, NULL_TREE, true, e,
11336 sym->attr.codimension
11337 ? GFC_CAF_COARRAY_DEREGISTER
11338 : GFC_CAF_COARRAY_NOCOARRAY);
11339 if (e)
11340 gfc_free_expr (e);
11341 gfc_add_expr_to_block (&cleanup, tmp);
11342 }
11343
11344 gfc_add_init_cleanup (block, gfc_finish_block (&init),
11345 gfc_finish_block (&cleanup));
11346 }
11347
11348 /************ Expression Walking Functions ******************/
11349
11350 /* Walk a variable reference.
11351
11352 Possible extension - multiple component subscripts.
11353 x(:,:) = foo%a(:)%b(:)
11354 Transforms to
11355 forall (i=..., j=...)
11356 x(i,j) = foo%a(j)%b(i)
11357 end forall
11358 This adds a fair amount of complexity because you need to deal with more
11359 than one ref. Maybe handle in a similar manner to vector subscripts.
11360 Maybe not worth the effort. */
11361
11362
11363 static gfc_ss *
gfc_walk_variable_expr(gfc_ss * ss,gfc_expr * expr)11364 gfc_walk_variable_expr (gfc_ss * ss, gfc_expr * expr)
11365 {
11366 gfc_ref *ref;
11367
11368 gfc_fix_class_refs (expr);
11369
11370 for (ref = expr->ref; ref; ref = ref->next)
11371 if (ref->type == REF_ARRAY && ref->u.ar.type != AR_ELEMENT)
11372 break;
11373
11374 return gfc_walk_array_ref (ss, expr, ref);
11375 }
11376
11377
11378 gfc_ss *
gfc_walk_array_ref(gfc_ss * ss,gfc_expr * expr,gfc_ref * ref)11379 gfc_walk_array_ref (gfc_ss * ss, gfc_expr * expr, gfc_ref * ref)
11380 {
11381 gfc_array_ref *ar;
11382 gfc_ss *newss;
11383 int n;
11384
11385 for (; ref; ref = ref->next)
11386 {
11387 if (ref->type == REF_SUBSTRING)
11388 {
11389 ss = gfc_get_scalar_ss (ss, ref->u.ss.start);
11390 if (ref->u.ss.end)
11391 ss = gfc_get_scalar_ss (ss, ref->u.ss.end);
11392 }
11393
11394 /* We're only interested in array sections from now on. */
11395 if (ref->type != REF_ARRAY)
11396 continue;
11397
11398 ar = &ref->u.ar;
11399
11400 switch (ar->type)
11401 {
11402 case AR_ELEMENT:
11403 for (n = ar->dimen - 1; n >= 0; n--)
11404 ss = gfc_get_scalar_ss (ss, ar->start[n]);
11405 break;
11406
11407 case AR_FULL:
11408 newss = gfc_get_array_ss (ss, expr, ar->as->rank, GFC_SS_SECTION);
11409 newss->info->data.array.ref = ref;
11410
11411 /* Make sure array is the same as array(:,:), this way
11412 we don't need to special case all the time. */
11413 ar->dimen = ar->as->rank;
11414 for (n = 0; n < ar->dimen; n++)
11415 {
11416 ar->dimen_type[n] = DIMEN_RANGE;
11417
11418 gcc_assert (ar->start[n] == NULL);
11419 gcc_assert (ar->end[n] == NULL);
11420 gcc_assert (ar->stride[n] == NULL);
11421 }
11422 ss = newss;
11423 break;
11424
11425 case AR_SECTION:
11426 newss = gfc_get_array_ss (ss, expr, 0, GFC_SS_SECTION);
11427 newss->info->data.array.ref = ref;
11428
11429 /* We add SS chains for all the subscripts in the section. */
11430 for (n = 0; n < ar->dimen; n++)
11431 {
11432 gfc_ss *indexss;
11433
11434 switch (ar->dimen_type[n])
11435 {
11436 case DIMEN_ELEMENT:
11437 /* Add SS for elemental (scalar) subscripts. */
11438 gcc_assert (ar->start[n]);
11439 indexss = gfc_get_scalar_ss (gfc_ss_terminator, ar->start[n]);
11440 indexss->loop_chain = gfc_ss_terminator;
11441 newss->info->data.array.subscript[n] = indexss;
11442 break;
11443
11444 case DIMEN_RANGE:
11445 /* We don't add anything for sections, just remember this
11446 dimension for later. */
11447 newss->dim[newss->dimen] = n;
11448 newss->dimen++;
11449 break;
11450
11451 case DIMEN_VECTOR:
11452 /* Create a GFC_SS_VECTOR index in which we can store
11453 the vector's descriptor. */
11454 indexss = gfc_get_array_ss (gfc_ss_terminator, ar->start[n],
11455 1, GFC_SS_VECTOR);
11456 indexss->loop_chain = gfc_ss_terminator;
11457 newss->info->data.array.subscript[n] = indexss;
11458 newss->dim[newss->dimen] = n;
11459 newss->dimen++;
11460 break;
11461
11462 default:
11463 /* We should know what sort of section it is by now. */
11464 gcc_unreachable ();
11465 }
11466 }
11467 /* We should have at least one non-elemental dimension,
11468 unless we are creating a descriptor for a (scalar) coarray. */
11469 gcc_assert (newss->dimen > 0
11470 || newss->info->data.array.ref->u.ar.as->corank > 0);
11471 ss = newss;
11472 break;
11473
11474 default:
11475 /* We should know what sort of section it is by now. */
11476 gcc_unreachable ();
11477 }
11478
11479 }
11480 return ss;
11481 }
11482
11483
11484 /* Walk an expression operator. If only one operand of a binary expression is
11485 scalar, we must also add the scalar term to the SS chain. */
11486
11487 static gfc_ss *
gfc_walk_op_expr(gfc_ss * ss,gfc_expr * expr)11488 gfc_walk_op_expr (gfc_ss * ss, gfc_expr * expr)
11489 {
11490 gfc_ss *head;
11491 gfc_ss *head2;
11492
11493 head = gfc_walk_subexpr (ss, expr->value.op.op1);
11494 if (expr->value.op.op2 == NULL)
11495 head2 = head;
11496 else
11497 head2 = gfc_walk_subexpr (head, expr->value.op.op2);
11498
11499 /* All operands are scalar. Pass back and let the caller deal with it. */
11500 if (head2 == ss)
11501 return head2;
11502
11503 /* All operands require scalarization. */
11504 if (head != ss && (expr->value.op.op2 == NULL || head2 != head))
11505 return head2;
11506
11507 /* One of the operands needs scalarization, the other is scalar.
11508 Create a gfc_ss for the scalar expression. */
11509 if (head == ss)
11510 {
11511 /* First operand is scalar. We build the chain in reverse order, so
11512 add the scalar SS after the second operand. */
11513 head = head2;
11514 while (head && head->next != ss)
11515 head = head->next;
11516 /* Check we haven't somehow broken the chain. */
11517 gcc_assert (head);
11518 head->next = gfc_get_scalar_ss (ss, expr->value.op.op1);
11519 }
11520 else /* head2 == head */
11521 {
11522 gcc_assert (head2 == head);
11523 /* Second operand is scalar. */
11524 head2 = gfc_get_scalar_ss (head2, expr->value.op.op2);
11525 }
11526
11527 return head2;
11528 }
11529
11530
11531 /* Reverse a SS chain. */
11532
11533 gfc_ss *
gfc_reverse_ss(gfc_ss * ss)11534 gfc_reverse_ss (gfc_ss * ss)
11535 {
11536 gfc_ss *next;
11537 gfc_ss *head;
11538
11539 gcc_assert (ss != NULL);
11540
11541 head = gfc_ss_terminator;
11542 while (ss != gfc_ss_terminator)
11543 {
11544 next = ss->next;
11545 /* Check we didn't somehow break the chain. */
11546 gcc_assert (next != NULL);
11547 ss->next = head;
11548 head = ss;
11549 ss = next;
11550 }
11551
11552 return (head);
11553 }
11554
11555
11556 /* Given an expression referring to a procedure, return the symbol of its
11557 interface. We can't get the procedure symbol directly as we have to handle
11558 the case of (deferred) type-bound procedures. */
11559
11560 gfc_symbol *
gfc_get_proc_ifc_for_expr(gfc_expr * procedure_ref)11561 gfc_get_proc_ifc_for_expr (gfc_expr *procedure_ref)
11562 {
11563 gfc_symbol *sym;
11564 gfc_ref *ref;
11565
11566 if (procedure_ref == NULL)
11567 return NULL;
11568
11569 /* Normal procedure case. */
11570 if (procedure_ref->expr_type == EXPR_FUNCTION
11571 && procedure_ref->value.function.esym)
11572 sym = procedure_ref->value.function.esym;
11573 else
11574 sym = procedure_ref->symtree->n.sym;
11575
11576 /* Typebound procedure case. */
11577 for (ref = procedure_ref->ref; ref; ref = ref->next)
11578 {
11579 if (ref->type == REF_COMPONENT
11580 && ref->u.c.component->attr.proc_pointer)
11581 sym = ref->u.c.component->ts.interface;
11582 else
11583 sym = NULL;
11584 }
11585
11586 return sym;
11587 }
11588
11589
11590 /* Given an expression referring to an intrinsic function call,
11591 return the intrinsic symbol. */
11592
11593 gfc_intrinsic_sym *
gfc_get_intrinsic_for_expr(gfc_expr * call)11594 gfc_get_intrinsic_for_expr (gfc_expr *call)
11595 {
11596 if (call == NULL)
11597 return NULL;
11598
11599 /* Normal procedure case. */
11600 if (call->expr_type == EXPR_FUNCTION)
11601 return call->value.function.isym;
11602 else
11603 return NULL;
11604 }
11605
11606
11607 /* Indicates whether an argument to an intrinsic function should be used in
11608 scalarization. It is usually the case, except for some intrinsics
11609 requiring the value to be constant, and using the value at compile time only.
11610 As the value is not used at runtime in those cases, we don’t produce code
11611 for it, and it should not be visible to the scalarizer.
11612 FUNCTION is the intrinsic function being called, ACTUAL_ARG is the actual
11613 argument being examined in that call, and ARG_NUM the index number
11614 of ACTUAL_ARG in the list of arguments.
11615 The intrinsic procedure’s dummy argument associated with ACTUAL_ARG is
11616 identified using the name in ACTUAL_ARG if it is present (that is: if it’s
11617 a keyword argument), otherwise using ARG_NUM. */
11618
11619 static bool
arg_evaluated_for_scalarization(gfc_intrinsic_sym * function,gfc_dummy_arg * dummy_arg)11620 arg_evaluated_for_scalarization (gfc_intrinsic_sym *function,
11621 gfc_dummy_arg *dummy_arg)
11622 {
11623 if (function != NULL && dummy_arg != NULL)
11624 {
11625 switch (function->id)
11626 {
11627 case GFC_ISYM_INDEX:
11628 case GFC_ISYM_LEN_TRIM:
11629 case GFC_ISYM_MASKL:
11630 case GFC_ISYM_MASKR:
11631 case GFC_ISYM_SCAN:
11632 case GFC_ISYM_VERIFY:
11633 if (strcmp ("kind", gfc_dummy_arg_get_name (*dummy_arg)) == 0)
11634 return false;
11635 /* Fallthrough. */
11636
11637 default:
11638 break;
11639 }
11640 }
11641
11642 return true;
11643 }
11644
11645
11646 /* Walk the arguments of an elemental function.
11647 PROC_EXPR is used to check whether an argument is permitted to be absent. If
11648 it is NULL, we don't do the check and the argument is assumed to be present.
11649 */
11650
11651 gfc_ss *
gfc_walk_elemental_function_args(gfc_ss * ss,gfc_actual_arglist * arg,gfc_intrinsic_sym * intrinsic_sym,gfc_ss_type type)11652 gfc_walk_elemental_function_args (gfc_ss * ss, gfc_actual_arglist *arg,
11653 gfc_intrinsic_sym *intrinsic_sym,
11654 gfc_ss_type type)
11655 {
11656 int scalar;
11657 gfc_ss *head;
11658 gfc_ss *tail;
11659 gfc_ss *newss;
11660
11661 head = gfc_ss_terminator;
11662 tail = NULL;
11663
11664 scalar = 1;
11665 for (; arg; arg = arg->next)
11666 {
11667 gfc_dummy_arg * const dummy_arg = arg->associated_dummy;
11668 if (!arg->expr
11669 || arg->expr->expr_type == EXPR_NULL
11670 || !arg_evaluated_for_scalarization (intrinsic_sym, dummy_arg))
11671 continue;
11672
11673 newss = gfc_walk_subexpr (head, arg->expr);
11674 if (newss == head)
11675 {
11676 /* Scalar argument. */
11677 gcc_assert (type == GFC_SS_SCALAR || type == GFC_SS_REFERENCE);
11678 newss = gfc_get_scalar_ss (head, arg->expr);
11679 newss->info->type = type;
11680 if (dummy_arg)
11681 newss->info->data.scalar.dummy_arg = dummy_arg;
11682 }
11683 else
11684 scalar = 0;
11685
11686 if (dummy_arg != NULL
11687 && gfc_dummy_arg_is_optional (*dummy_arg)
11688 && arg->expr->expr_type == EXPR_VARIABLE
11689 && (gfc_expr_attr (arg->expr).optional
11690 || gfc_expr_attr (arg->expr).allocatable
11691 || gfc_expr_attr (arg->expr).pointer))
11692 newss->info->can_be_null_ref = true;
11693
11694 head = newss;
11695 if (!tail)
11696 {
11697 tail = head;
11698 while (tail->next != gfc_ss_terminator)
11699 tail = tail->next;
11700 }
11701 }
11702
11703 if (scalar)
11704 {
11705 /* If all the arguments are scalar we don't need the argument SS. */
11706 gfc_free_ss_chain (head);
11707 /* Pass it back. */
11708 return ss;
11709 }
11710
11711 /* Add it onto the existing chain. */
11712 tail->next = ss;
11713 return head;
11714 }
11715
11716
11717 /* Walk a function call. Scalar functions are passed back, and taken out of
11718 scalarization loops. For elemental functions we walk their arguments.
11719 The result of functions returning arrays is stored in a temporary outside
11720 the loop, so that the function is only called once. Hence we do not need
11721 to walk their arguments. */
11722
11723 static gfc_ss *
gfc_walk_function_expr(gfc_ss * ss,gfc_expr * expr)11724 gfc_walk_function_expr (gfc_ss * ss, gfc_expr * expr)
11725 {
11726 gfc_intrinsic_sym *isym;
11727 gfc_symbol *sym;
11728 gfc_component *comp = NULL;
11729
11730 isym = expr->value.function.isym;
11731
11732 /* Handle intrinsic functions separately. */
11733 if (isym)
11734 return gfc_walk_intrinsic_function (ss, expr, isym);
11735
11736 sym = expr->value.function.esym;
11737 if (!sym)
11738 sym = expr->symtree->n.sym;
11739
11740 if (gfc_is_class_array_function (expr))
11741 return gfc_get_array_ss (ss, expr,
11742 CLASS_DATA (expr->value.function.esym->result)->as->rank,
11743 GFC_SS_FUNCTION);
11744
11745 /* A function that returns arrays. */
11746 comp = gfc_get_proc_ptr_comp (expr);
11747 if ((!comp && gfc_return_by_reference (sym) && sym->result->attr.dimension)
11748 || (comp && comp->attr.dimension))
11749 return gfc_get_array_ss (ss, expr, expr->rank, GFC_SS_FUNCTION);
11750
11751 /* Walk the parameters of an elemental function. For now we always pass
11752 by reference. */
11753 if (sym->attr.elemental || (comp && comp->attr.elemental))
11754 {
11755 gfc_ss *old_ss = ss;
11756
11757 ss = gfc_walk_elemental_function_args (old_ss,
11758 expr->value.function.actual,
11759 gfc_get_intrinsic_for_expr (expr),
11760 GFC_SS_REFERENCE);
11761 if (ss != old_ss
11762 && (comp
11763 || sym->attr.proc_pointer
11764 || sym->attr.if_source != IFSRC_DECL
11765 || sym->attr.array_outer_dependency))
11766 ss->info->array_outer_dependency = 1;
11767 }
11768
11769 /* Scalar functions are OK as these are evaluated outside the scalarization
11770 loop. Pass back and let the caller deal with it. */
11771 return ss;
11772 }
11773
11774
11775 /* An array temporary is constructed for array constructors. */
11776
11777 static gfc_ss *
gfc_walk_array_constructor(gfc_ss * ss,gfc_expr * expr)11778 gfc_walk_array_constructor (gfc_ss * ss, gfc_expr * expr)
11779 {
11780 return gfc_get_array_ss (ss, expr, expr->rank, GFC_SS_CONSTRUCTOR);
11781 }
11782
11783
11784 /* Walk an expression. Add walked expressions to the head of the SS chain.
11785 A wholly scalar expression will not be added. */
11786
11787 gfc_ss *
gfc_walk_subexpr(gfc_ss * ss,gfc_expr * expr)11788 gfc_walk_subexpr (gfc_ss * ss, gfc_expr * expr)
11789 {
11790 gfc_ss *head;
11791
11792 switch (expr->expr_type)
11793 {
11794 case EXPR_VARIABLE:
11795 head = gfc_walk_variable_expr (ss, expr);
11796 return head;
11797
11798 case EXPR_OP:
11799 head = gfc_walk_op_expr (ss, expr);
11800 return head;
11801
11802 case EXPR_FUNCTION:
11803 head = gfc_walk_function_expr (ss, expr);
11804 return head;
11805
11806 case EXPR_CONSTANT:
11807 case EXPR_NULL:
11808 case EXPR_STRUCTURE:
11809 /* Pass back and let the caller deal with it. */
11810 break;
11811
11812 case EXPR_ARRAY:
11813 head = gfc_walk_array_constructor (ss, expr);
11814 return head;
11815
11816 case EXPR_SUBSTRING:
11817 /* Pass back and let the caller deal with it. */
11818 break;
11819
11820 default:
11821 gfc_internal_error ("bad expression type during walk (%d)",
11822 expr->expr_type);
11823 }
11824 return ss;
11825 }
11826
11827
11828 /* Entry point for expression walking.
11829 A return value equal to the passed chain means this is
11830 a scalar expression. It is up to the caller to take whatever action is
11831 necessary to translate these. */
11832
11833 gfc_ss *
gfc_walk_expr(gfc_expr * expr)11834 gfc_walk_expr (gfc_expr * expr)
11835 {
11836 gfc_ss *res;
11837
11838 res = gfc_walk_subexpr (gfc_ss_terminator, expr);
11839 return gfc_reverse_ss (res);
11840 }
11841