1 /* IO Code translation/library interface
2 Copyright (C) 2002-2018 Free Software Foundation, Inc.
3 Contributed by Paul Brook
5 This file is part of GCC.
7 GCC is free software; you can redistribute it and/or modify it under
8 the terms of the GNU General Public License as published by the Free
9 Software Foundation; either version 3, or (at your option) any later
12 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
13 WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
17 You should have received a copy of the GNU General Public License
18 along with GCC; see the file COPYING3. If not see
19 <http://www.gnu.org/licenses/>. */
24 #include "coretypes.h"
28 #include "stringpool.h"
29 #include "fold-const.h"
30 #include "stor-layout.h"
31 #include "trans-stmt.h"
32 #include "trans-array.h"
33 #include "trans-types.h"
34 #include "trans-const.h"
37 /* Members of the ioparm structure. */
66 typedef struct GTY(()) gfc_st_parameter_field
{
69 enum ioparam_type param_type
;
70 enum iofield_type type
;
74 gfc_st_parameter_field
;
76 typedef struct GTY(()) gfc_st_parameter
{
84 #define IOPARM(param_type, name, mask, type) IOPARM_##param_type##_##name,
90 static GTY(()) gfc_st_parameter st_parameter
[] =
101 static GTY(()) gfc_st_parameter_field st_parameter_field
[] =
103 #define IOPARM(param_type, name, mask, type) \
104 { #name, mask, IOPARM_ptype_##param_type, IOPARM_type_##type, NULL, NULL },
105 #include "ioparm.def"
107 { NULL
, 0, (enum ioparam_type
) 0, (enum iofield_type
) 0, NULL
, NULL
}
110 /* Library I/O subroutines */
119 IOCALL_X_INTEGER_WRITE
,
121 IOCALL_X_LOGICAL_WRITE
,
123 IOCALL_X_CHARACTER_WRITE
,
124 IOCALL_X_CHARACTER_WIDE
,
125 IOCALL_X_CHARACTER_WIDE_WRITE
,
129 IOCALL_X_COMPLEX_WRITE
,
131 IOCALL_X_REAL128_WRITE
,
133 IOCALL_X_COMPLEX128_WRITE
,
135 IOCALL_X_ARRAY_WRITE
,
141 IOCALL_IOLENGTH_DONE
,
147 IOCALL_SET_NML_DTIO_VAL
,
148 IOCALL_SET_NML_VAL_DIM
,
153 static GTY(()) tree iocall
[IOCALL_NUM
];
155 /* Variable for keeping track of what the last data transfer statement
156 was. Used for deciding which subroutine to call when the data
157 transfer is complete. */
158 static enum { READ
, WRITE
, IOLENGTH
} last_dt
;
160 /* The data transfer parameter block that should be shared by all
161 data transfer calls belonging to the same read/write/iolength. */
162 static GTY(()) tree dt_parm
;
163 static stmtblock_t
*dt_post_end_block
;
166 gfc_build_st_parameter (enum ioparam_type ptype
, tree
*types
)
169 gfc_st_parameter_field
*p
;
172 tree t
= make_node (RECORD_TYPE
);
175 len
= strlen (st_parameter
[ptype
].name
);
176 gcc_assert (len
<= sizeof (name
) - sizeof ("__st_parameter_"));
177 memcpy (name
, "__st_parameter_", sizeof ("__st_parameter_"));
178 memcpy (name
+ sizeof ("__st_parameter_") - 1, st_parameter
[ptype
].name
,
180 TYPE_NAME (t
) = get_identifier (name
);
182 for (type
= 0, p
= st_parameter_field
; type
< IOPARM_field_num
; type
++, p
++)
183 if (p
->param_type
== ptype
)
186 case IOPARM_type_int4
:
187 case IOPARM_type_intio
:
188 case IOPARM_type_pint4
:
189 case IOPARM_type_pintio
:
190 case IOPARM_type_parray
:
191 case IOPARM_type_pchar
:
192 case IOPARM_type_pad
:
193 p
->field
= gfc_add_field_to_struct (t
, get_identifier (p
->name
),
194 types
[p
->type
], &chain
);
196 case IOPARM_type_char1
:
197 p
->field
= gfc_add_field_to_struct (t
, get_identifier (p
->name
),
198 pchar_type_node
, &chain
);
200 case IOPARM_type_char2
:
201 len
= strlen (p
->name
);
202 gcc_assert (len
<= sizeof (name
) - sizeof ("_len"));
203 memcpy (name
, p
->name
, len
);
204 memcpy (name
+ len
, "_len", sizeof ("_len"));
205 p
->field_len
= gfc_add_field_to_struct (t
, get_identifier (name
),
206 gfc_charlen_type_node
,
208 if (p
->type
== IOPARM_type_char2
)
209 p
->field
= gfc_add_field_to_struct (t
, get_identifier (p
->name
),
210 pchar_type_node
, &chain
);
212 case IOPARM_type_common
:
214 = gfc_add_field_to_struct (t
,
215 get_identifier (p
->name
),
216 st_parameter
[IOPARM_ptype_common
].type
,
219 case IOPARM_type_num
:
223 /* -Wpadded warnings on these artificially created structures are not
224 helpful; suppress them. */
225 int save_warn_padded
= warn_padded
;
228 warn_padded
= save_warn_padded
;
229 st_parameter
[ptype
].type
= t
;
233 /* Build code to test an error condition and call generate_error if needed.
234 Note: This builds calls to generate_error in the runtime library function.
235 The function generate_error is dependent on certain parameters in the
236 st_parameter_common flags to be set. (See libgfortran/runtime/error.c)
237 Therefore, the code to set these flags must be generated before
238 this function is used. */
241 gfc_trans_io_runtime_check (bool has_iostat
, tree cond
, tree var
,
242 int error_code
, const char * msgid
,
243 stmtblock_t
* pblock
)
248 tree arg1
, arg2
, arg3
;
251 if (integer_zerop (cond
))
254 /* The code to generate the error. */
255 gfc_start_block (&block
);
258 gfc_add_expr_to_block (&block
, build_predict_expr (PRED_FORTRAN_FAIL_IO
,
261 gfc_add_expr_to_block (&block
, build_predict_expr (PRED_NORETURN
,
264 arg1
= gfc_build_addr_expr (NULL_TREE
, var
);
266 arg2
= build_int_cst (integer_type_node
, error_code
),
268 message
= xasprintf ("%s", _(msgid
));
269 arg3
= gfc_build_addr_expr (pchar_type_node
,
270 gfc_build_localized_cstring_const (message
));
273 tmp
= build_call_expr_loc (input_location
,
274 gfor_fndecl_generate_error
, 3, arg1
, arg2
, arg3
);
276 gfc_add_expr_to_block (&block
, tmp
);
278 body
= gfc_finish_block (&block
);
280 if (integer_onep (cond
))
282 gfc_add_expr_to_block (pblock
, body
);
286 tmp
= build3_v (COND_EXPR
, cond
, body
, build_empty_stmt (input_location
));
287 gfc_add_expr_to_block (pblock
, tmp
);
292 /* Create function decls for IO library functions. */
295 gfc_build_io_library_fndecls (void)
297 tree types
[IOPARM_type_num
], pad_idx
, gfc_int4_type_node
;
298 tree gfc_intio_type_node
;
299 tree parm_type
, dt_parm_type
;
300 HOST_WIDE_INT pad_size
;
303 types
[IOPARM_type_int4
] = gfc_int4_type_node
= gfc_get_int_type (4);
304 types
[IOPARM_type_intio
] = gfc_intio_type_node
305 = gfc_get_int_type (gfc_intio_kind
);
306 types
[IOPARM_type_pint4
] = build_pointer_type (gfc_int4_type_node
);
307 types
[IOPARM_type_pintio
]
308 = build_pointer_type (gfc_intio_type_node
);
309 types
[IOPARM_type_parray
] = pchar_type_node
;
310 types
[IOPARM_type_pchar
] = pchar_type_node
;
311 pad_size
= 16 * TREE_INT_CST_LOW (TYPE_SIZE_UNIT (pchar_type_node
));
312 pad_size
+= 32 * TREE_INT_CST_LOW (TYPE_SIZE_UNIT (integer_type_node
));
313 pad_idx
= build_index_type (size_int (pad_size
- 1));
314 types
[IOPARM_type_pad
] = build_array_type (char_type_node
, pad_idx
);
316 /* pad actually contains pointers and integers so it needs to have an
317 alignment that is at least as large as the needed alignment for those
318 types. See the st_parameter_dt structure in libgfortran/io/io.h for
319 what really goes into this space. */
320 SET_TYPE_ALIGN (types
[IOPARM_type_pad
], MAX (TYPE_ALIGN (pchar_type_node
),
321 TYPE_ALIGN (gfc_get_int_type (gfc_intio_kind
))));
323 for (ptype
= IOPARM_ptype_common
; ptype
< IOPARM_ptype_num
; ptype
++)
324 gfc_build_st_parameter ((enum ioparam_type
) ptype
, types
);
326 /* Define the transfer functions. */
328 dt_parm_type
= build_pointer_type (st_parameter
[IOPARM_ptype_dt
].type
);
330 iocall
[IOCALL_X_INTEGER
] = gfc_build_library_function_decl_with_spec (
331 get_identifier (PREFIX("transfer_integer")), ".wW",
332 void_type_node
, 3, dt_parm_type
, pvoid_type_node
, gfc_int4_type_node
);
334 iocall
[IOCALL_X_INTEGER_WRITE
] = gfc_build_library_function_decl_with_spec (
335 get_identifier (PREFIX("transfer_integer_write")), ".wR",
336 void_type_node
, 3, dt_parm_type
, pvoid_type_node
, gfc_int4_type_node
);
338 iocall
[IOCALL_X_LOGICAL
] = gfc_build_library_function_decl_with_spec (
339 get_identifier (PREFIX("transfer_logical")), ".wW",
340 void_type_node
, 3, dt_parm_type
, pvoid_type_node
, gfc_int4_type_node
);
342 iocall
[IOCALL_X_LOGICAL_WRITE
] = gfc_build_library_function_decl_with_spec (
343 get_identifier (PREFIX("transfer_logical_write")), ".wR",
344 void_type_node
, 3, dt_parm_type
, pvoid_type_node
, gfc_int4_type_node
);
346 iocall
[IOCALL_X_CHARACTER
] = gfc_build_library_function_decl_with_spec (
347 get_identifier (PREFIX("transfer_character")), ".wW",
348 void_type_node
, 3, dt_parm_type
, pvoid_type_node
, gfc_charlen_type_node
);
350 iocall
[IOCALL_X_CHARACTER_WRITE
] = gfc_build_library_function_decl_with_spec (
351 get_identifier (PREFIX("transfer_character_write")), ".wR",
352 void_type_node
, 3, dt_parm_type
, pvoid_type_node
, gfc_charlen_type_node
);
354 iocall
[IOCALL_X_CHARACTER_WIDE
] = gfc_build_library_function_decl_with_spec (
355 get_identifier (PREFIX("transfer_character_wide")), ".wW",
356 void_type_node
, 4, dt_parm_type
, pvoid_type_node
,
357 gfc_charlen_type_node
, gfc_int4_type_node
);
359 iocall
[IOCALL_X_CHARACTER_WIDE_WRITE
] =
360 gfc_build_library_function_decl_with_spec (
361 get_identifier (PREFIX("transfer_character_wide_write")), ".wR",
362 void_type_node
, 4, dt_parm_type
, pvoid_type_node
,
363 gfc_charlen_type_node
, gfc_int4_type_node
);
365 iocall
[IOCALL_X_REAL
] = gfc_build_library_function_decl_with_spec (
366 get_identifier (PREFIX("transfer_real")), ".wW",
367 void_type_node
, 3, dt_parm_type
, pvoid_type_node
, gfc_int4_type_node
);
369 iocall
[IOCALL_X_REAL_WRITE
] = gfc_build_library_function_decl_with_spec (
370 get_identifier (PREFIX("transfer_real_write")), ".wR",
371 void_type_node
, 3, dt_parm_type
, pvoid_type_node
, gfc_int4_type_node
);
373 iocall
[IOCALL_X_COMPLEX
] = gfc_build_library_function_decl_with_spec (
374 get_identifier (PREFIX("transfer_complex")), ".wW",
375 void_type_node
, 3, dt_parm_type
, pvoid_type_node
, gfc_int4_type_node
);
377 iocall
[IOCALL_X_COMPLEX_WRITE
] = gfc_build_library_function_decl_with_spec (
378 get_identifier (PREFIX("transfer_complex_write")), ".wR",
379 void_type_node
, 3, dt_parm_type
, pvoid_type_node
, gfc_int4_type_node
);
381 /* Version for __float128. */
382 iocall
[IOCALL_X_REAL128
] = gfc_build_library_function_decl_with_spec (
383 get_identifier (PREFIX("transfer_real128")), ".wW",
384 void_type_node
, 3, dt_parm_type
, pvoid_type_node
, gfc_int4_type_node
);
386 iocall
[IOCALL_X_REAL128_WRITE
] = gfc_build_library_function_decl_with_spec (
387 get_identifier (PREFIX("transfer_real128_write")), ".wR",
388 void_type_node
, 3, dt_parm_type
, pvoid_type_node
, gfc_int4_type_node
);
390 iocall
[IOCALL_X_COMPLEX128
] = gfc_build_library_function_decl_with_spec (
391 get_identifier (PREFIX("transfer_complex128")), ".wW",
392 void_type_node
, 3, dt_parm_type
, pvoid_type_node
, gfc_int4_type_node
);
394 iocall
[IOCALL_X_COMPLEX128_WRITE
] = gfc_build_library_function_decl_with_spec (
395 get_identifier (PREFIX("transfer_complex128_write")), ".wR",
396 void_type_node
, 3, dt_parm_type
, pvoid_type_node
, gfc_int4_type_node
);
398 iocall
[IOCALL_X_ARRAY
] = gfc_build_library_function_decl_with_spec (
399 get_identifier (PREFIX("transfer_array")), ".ww",
400 void_type_node
, 4, dt_parm_type
, pvoid_type_node
,
401 integer_type_node
, gfc_charlen_type_node
);
403 iocall
[IOCALL_X_ARRAY_WRITE
] = gfc_build_library_function_decl_with_spec (
404 get_identifier (PREFIX("transfer_array_write")), ".wr",
405 void_type_node
, 4, dt_parm_type
, pvoid_type_node
,
406 integer_type_node
, gfc_charlen_type_node
);
408 iocall
[IOCALL_X_DERIVED
] = gfc_build_library_function_decl_with_spec (
409 get_identifier (PREFIX("transfer_derived")), ".wrR",
410 void_type_node
, 2, dt_parm_type
, pvoid_type_node
, pchar_type_node
);
412 /* Library entry points */
414 iocall
[IOCALL_READ
] = gfc_build_library_function_decl_with_spec (
415 get_identifier (PREFIX("st_read")), ".w",
416 void_type_node
, 1, dt_parm_type
);
418 iocall
[IOCALL_WRITE
] = gfc_build_library_function_decl_with_spec (
419 get_identifier (PREFIX("st_write")), ".w",
420 void_type_node
, 1, dt_parm_type
);
422 parm_type
= build_pointer_type (st_parameter
[IOPARM_ptype_open
].type
);
423 iocall
[IOCALL_OPEN
] = gfc_build_library_function_decl_with_spec (
424 get_identifier (PREFIX("st_open")), ".w",
425 void_type_node
, 1, parm_type
);
427 parm_type
= build_pointer_type (st_parameter
[IOPARM_ptype_close
].type
);
428 iocall
[IOCALL_CLOSE
] = gfc_build_library_function_decl_with_spec (
429 get_identifier (PREFIX("st_close")), ".w",
430 void_type_node
, 1, parm_type
);
432 parm_type
= build_pointer_type (st_parameter
[IOPARM_ptype_inquire
].type
);
433 iocall
[IOCALL_INQUIRE
] = gfc_build_library_function_decl_with_spec (
434 get_identifier (PREFIX("st_inquire")), ".w",
435 void_type_node
, 1, parm_type
);
437 iocall
[IOCALL_IOLENGTH
] = gfc_build_library_function_decl_with_spec(
438 get_identifier (PREFIX("st_iolength")), ".w",
439 void_type_node
, 1, dt_parm_type
);
441 parm_type
= build_pointer_type (st_parameter
[IOPARM_ptype_wait
].type
);
442 iocall
[IOCALL_WAIT
] = gfc_build_library_function_decl_with_spec (
443 get_identifier (PREFIX("st_wait_async")), ".w",
444 void_type_node
, 1, parm_type
);
446 parm_type
= build_pointer_type (st_parameter
[IOPARM_ptype_filepos
].type
);
447 iocall
[IOCALL_REWIND
] = gfc_build_library_function_decl_with_spec (
448 get_identifier (PREFIX("st_rewind")), ".w",
449 void_type_node
, 1, parm_type
);
451 iocall
[IOCALL_BACKSPACE
] = gfc_build_library_function_decl_with_spec (
452 get_identifier (PREFIX("st_backspace")), ".w",
453 void_type_node
, 1, parm_type
);
455 iocall
[IOCALL_ENDFILE
] = gfc_build_library_function_decl_with_spec (
456 get_identifier (PREFIX("st_endfile")), ".w",
457 void_type_node
, 1, parm_type
);
459 iocall
[IOCALL_FLUSH
] = gfc_build_library_function_decl_with_spec (
460 get_identifier (PREFIX("st_flush")), ".w",
461 void_type_node
, 1, parm_type
);
463 /* Library helpers */
465 iocall
[IOCALL_READ_DONE
] = gfc_build_library_function_decl_with_spec (
466 get_identifier (PREFIX("st_read_done")), ".w",
467 void_type_node
, 1, dt_parm_type
);
469 iocall
[IOCALL_WRITE_DONE
] = gfc_build_library_function_decl_with_spec (
470 get_identifier (PREFIX("st_write_done")), ".w",
471 void_type_node
, 1, dt_parm_type
);
473 iocall
[IOCALL_IOLENGTH_DONE
] = gfc_build_library_function_decl_with_spec (
474 get_identifier (PREFIX("st_iolength_done")), ".w",
475 void_type_node
, 1, dt_parm_type
);
477 iocall
[IOCALL_SET_NML_VAL
] = gfc_build_library_function_decl_with_spec (
478 get_identifier (PREFIX("st_set_nml_var")), ".w.R",
479 void_type_node
, 6, dt_parm_type
, pvoid_type_node
, pvoid_type_node
,
480 gfc_int4_type_node
, gfc_charlen_type_node
, get_dtype_type_node());
482 iocall
[IOCALL_SET_NML_DTIO_VAL
] = gfc_build_library_function_decl_with_spec (
483 get_identifier (PREFIX("st_set_nml_dtio_var")), ".w.R",
484 void_type_node
, 8, dt_parm_type
, pvoid_type_node
, pvoid_type_node
,
485 gfc_int4_type_node
, gfc_charlen_type_node
, get_dtype_type_node(),
486 pvoid_type_node
, pvoid_type_node
);
488 iocall
[IOCALL_SET_NML_VAL_DIM
] = gfc_build_library_function_decl_with_spec (
489 get_identifier (PREFIX("st_set_nml_var_dim")), ".w",
490 void_type_node
, 5, dt_parm_type
, gfc_int4_type_node
,
491 gfc_array_index_type
, gfc_array_index_type
, gfc_array_index_type
);
496 set_parameter_tree (stmtblock_t
*block
, tree var
, enum iofield type
, tree value
)
499 gfc_st_parameter_field
*p
= &st_parameter_field
[type
];
501 if (p
->param_type
== IOPARM_ptype_common
)
502 var
= fold_build3_loc (input_location
, COMPONENT_REF
,
503 st_parameter
[IOPARM_ptype_common
].type
,
504 var
, TYPE_FIELDS (TREE_TYPE (var
)), NULL_TREE
);
505 tmp
= fold_build3_loc (input_location
, COMPONENT_REF
, TREE_TYPE (p
->field
),
506 var
, p
->field
, NULL_TREE
);
507 gfc_add_modify (block
, tmp
, value
);
511 /* Generate code to store an integer constant into the
512 st_parameter_XXX structure. */
515 set_parameter_const (stmtblock_t
*block
, tree var
, enum iofield type
,
518 gfc_st_parameter_field
*p
= &st_parameter_field
[type
];
520 set_parameter_tree (block
, var
, type
,
521 build_int_cst (TREE_TYPE (p
->field
), val
));
526 /* Generate code to store a non-string I/O parameter into the
527 st_parameter_XXX structure. This is a pass by value. */
530 set_parameter_value (stmtblock_t
*block
, tree var
, enum iofield type
,
535 gfc_st_parameter_field
*p
= &st_parameter_field
[type
];
536 tree dest_type
= TREE_TYPE (p
->field
);
538 gfc_init_se (&se
, NULL
);
539 gfc_conv_expr_val (&se
, e
);
541 se
.expr
= convert (dest_type
, se
.expr
);
542 gfc_add_block_to_block (block
, &se
.pre
);
544 if (p
->param_type
== IOPARM_ptype_common
)
545 var
= fold_build3_loc (input_location
, COMPONENT_REF
,
546 st_parameter
[IOPARM_ptype_common
].type
,
547 var
, TYPE_FIELDS (TREE_TYPE (var
)), NULL_TREE
);
549 tmp
= fold_build3_loc (input_location
, COMPONENT_REF
, dest_type
, var
,
550 p
->field
, NULL_TREE
);
551 gfc_add_modify (block
, tmp
, se
.expr
);
556 /* Similar to set_parameter_value except generate runtime
560 set_parameter_value_chk (stmtblock_t
*block
, bool has_iostat
, tree var
,
561 enum iofield type
, gfc_expr
*e
)
565 gfc_st_parameter_field
*p
= &st_parameter_field
[type
];
566 tree dest_type
= TREE_TYPE (p
->field
);
568 gfc_init_se (&se
, NULL
);
569 gfc_conv_expr_val (&se
, e
);
571 /* If we're storing a UNIT number, we need to check it first. */
572 if (type
== IOPARM_common_unit
&& e
->ts
.kind
> 4)
577 /* Don't evaluate the UNIT number multiple times. */
578 se
.expr
= gfc_evaluate_now (se
.expr
, &se
.pre
);
580 /* UNIT numbers should be greater than the min. */
581 i
= gfc_validate_kind (BT_INTEGER
, 4, false);
582 val
= gfc_conv_mpz_to_tree (gfc_integer_kinds
[i
].pedantic_min_int
, 4);
583 cond
= fold_build2_loc (input_location
, LT_EXPR
, logical_type_node
,
585 fold_convert (TREE_TYPE (se
.expr
), val
));
586 gfc_trans_io_runtime_check (has_iostat
, cond
, var
, LIBERROR_BAD_UNIT
,
587 "Unit number in I/O statement too small",
590 /* UNIT numbers should be less than the max. */
591 val
= gfc_conv_mpz_to_tree (gfc_integer_kinds
[i
].huge
, 4);
592 cond
= fold_build2_loc (input_location
, GT_EXPR
, logical_type_node
,
594 fold_convert (TREE_TYPE (se
.expr
), val
));
595 gfc_trans_io_runtime_check (has_iostat
, cond
, var
, LIBERROR_BAD_UNIT
,
596 "Unit number in I/O statement too large",
600 se
.expr
= convert (dest_type
, se
.expr
);
601 gfc_add_block_to_block (block
, &se
.pre
);
603 if (p
->param_type
== IOPARM_ptype_common
)
604 var
= fold_build3_loc (input_location
, COMPONENT_REF
,
605 st_parameter
[IOPARM_ptype_common
].type
,
606 var
, TYPE_FIELDS (TREE_TYPE (var
)), NULL_TREE
);
608 tmp
= fold_build3_loc (input_location
, COMPONENT_REF
, dest_type
, var
,
609 p
->field
, NULL_TREE
);
610 gfc_add_modify (block
, tmp
, se
.expr
);
615 /* Build code to check the unit range if KIND=8 is used. Similar to
616 set_parameter_value_chk but we do not generate error calls for
617 inquire statements. */
620 set_parameter_value_inquire (stmtblock_t
*block
, tree var
,
621 enum iofield type
, gfc_expr
*e
)
624 gfc_st_parameter_field
*p
= &st_parameter_field
[type
];
625 tree dest_type
= TREE_TYPE (p
->field
);
627 gfc_init_se (&se
, NULL
);
628 gfc_conv_expr_val (&se
, e
);
630 /* If we're inquiring on a UNIT number, we need to check to make
631 sure it exists for larger than kind = 4. */
632 if (type
== IOPARM_common_unit
&& e
->ts
.kind
> 4)
634 stmtblock_t newblock
;
635 tree cond1
, cond2
, cond3
, val
, body
;
638 /* Don't evaluate the UNIT number multiple times. */
639 se
.expr
= gfc_evaluate_now (se
.expr
, &se
.pre
);
641 /* UNIT numbers should be greater than the min. */
642 i
= gfc_validate_kind (BT_INTEGER
, 4, false);
643 val
= gfc_conv_mpz_to_tree (gfc_integer_kinds
[i
].pedantic_min_int
, 4);
644 cond1
= build2_loc (input_location
, LT_EXPR
, logical_type_node
,
646 fold_convert (TREE_TYPE (se
.expr
), val
));
647 /* UNIT numbers should be less than the max. */
648 val
= gfc_conv_mpz_to_tree (gfc_integer_kinds
[i
].huge
, 4);
649 cond2
= build2_loc (input_location
, GT_EXPR
, logical_type_node
,
651 fold_convert (TREE_TYPE (se
.expr
), val
));
652 cond3
= build2_loc (input_location
, TRUTH_OR_EXPR
,
653 logical_type_node
, cond1
, cond2
);
655 gfc_start_block (&newblock
);
657 /* The unit number GFC_INVALID_UNIT is reserved. No units can
658 ever have this value. It is used here to signal to the
659 runtime library that the inquire unit number is outside the
660 allowable range and so cannot exist. It is needed when
661 -fdefault-integer-8 is used. */
662 set_parameter_const (&newblock
, var
, IOPARM_common_unit
,
665 body
= gfc_finish_block (&newblock
);
667 cond3
= gfc_unlikely (cond3
, PRED_FORTRAN_FAIL_IO
);
668 var
= build3_v (COND_EXPR
, cond3
, body
, build_empty_stmt (input_location
));
669 gfc_add_expr_to_block (&se
.pre
, var
);
672 se
.expr
= convert (dest_type
, se
.expr
);
673 gfc_add_block_to_block (block
, &se
.pre
);
679 /* Generate code to store a non-string I/O parameter into the
680 st_parameter_XXX structure. This is pass by reference. */
683 set_parameter_ref (stmtblock_t
*block
, stmtblock_t
*postblock
,
684 tree var
, enum iofield type
, gfc_expr
*e
)
688 gfc_st_parameter_field
*p
= &st_parameter_field
[type
];
690 gcc_assert (e
->ts
.type
== BT_INTEGER
|| e
->ts
.type
== BT_LOGICAL
);
691 gfc_init_se (&se
, NULL
);
692 gfc_conv_expr_lhs (&se
, e
);
694 gfc_add_block_to_block (block
, &se
.pre
);
696 if (TYPE_MODE (TREE_TYPE (se
.expr
))
697 == TYPE_MODE (TREE_TYPE (TREE_TYPE (p
->field
))))
699 addr
= convert (TREE_TYPE (p
->field
), gfc_build_addr_expr (NULL_TREE
, se
.expr
));
701 /* If this is for the iostat variable initialize the
702 user variable to LIBERROR_OK which is zero. */
703 if (type
== IOPARM_common_iostat
)
704 gfc_add_modify (block
, se
.expr
,
705 build_int_cst (TREE_TYPE (se
.expr
), LIBERROR_OK
));
709 /* The type used by the library has different size
710 from the type of the variable supplied by the user.
711 Need to use a temporary. */
712 tree tmpvar
= gfc_create_var (TREE_TYPE (TREE_TYPE (p
->field
)),
713 st_parameter_field
[type
].name
);
715 /* If this is for the iostat variable, initialize the
716 user variable to LIBERROR_OK which is zero. */
717 if (type
== IOPARM_common_iostat
)
718 gfc_add_modify (block
, tmpvar
,
719 build_int_cst (TREE_TYPE (tmpvar
), LIBERROR_OK
));
721 addr
= gfc_build_addr_expr (NULL_TREE
, tmpvar
);
722 /* After the I/O operation, we set the variable from the temporary. */
723 tmp
= convert (TREE_TYPE (se
.expr
), tmpvar
);
724 gfc_add_modify (postblock
, se
.expr
, tmp
);
727 set_parameter_tree (block
, var
, type
, addr
);
731 /* Given an array expr, find its address and length to get a string. If the
732 array is full, the string's address is the address of array's first element
733 and the length is the size of the whole array. If it is an element, the
734 string's address is the element's address and the length is the rest size of
738 gfc_convert_array_to_string (gfc_se
* se
, gfc_expr
* e
)
744 tree type
, array
, tmp
;
748 /* If it is an element, we need its address and size of the rest. */
749 gcc_assert (e
->expr_type
== EXPR_VARIABLE
);
750 gcc_assert (e
->ref
->u
.ar
.type
== AR_ELEMENT
);
751 sym
= e
->symtree
->n
.sym
;
752 rank
= sym
->as
->rank
- 1;
753 gfc_conv_expr (se
, e
);
755 array
= sym
->backend_decl
;
756 type
= TREE_TYPE (array
);
758 if (GFC_ARRAY_TYPE_P (type
))
759 size
= GFC_TYPE_ARRAY_SIZE (type
);
762 gcc_assert (GFC_DESCRIPTOR_TYPE_P (type
));
763 size
= gfc_conv_array_stride (array
, rank
);
764 tmp
= fold_build2_loc (input_location
, MINUS_EXPR
,
765 gfc_array_index_type
,
766 gfc_conv_array_ubound (array
, rank
),
767 gfc_conv_array_lbound (array
, rank
));
768 tmp
= fold_build2_loc (input_location
, PLUS_EXPR
,
769 gfc_array_index_type
, tmp
,
771 size
= fold_build2_loc (input_location
, MULT_EXPR
,
772 gfc_array_index_type
, tmp
, size
);
776 size
= fold_build2_loc (input_location
, MINUS_EXPR
,
777 gfc_array_index_type
, size
,
778 TREE_OPERAND (se
->expr
, 1));
779 se
->expr
= gfc_build_addr_expr (NULL_TREE
, se
->expr
);
780 tmp
= TYPE_SIZE_UNIT (gfc_get_element_type (type
));
781 size
= fold_build2_loc (input_location
, MULT_EXPR
,
782 gfc_array_index_type
, size
,
783 fold_convert (gfc_array_index_type
, tmp
));
784 se
->string_length
= fold_convert (gfc_charlen_type_node
, size
);
788 gfc_conv_array_parameter (se
, e
, true, NULL
, NULL
, &size
);
789 se
->string_length
= fold_convert (gfc_charlen_type_node
, size
);
793 /* Generate code to store a string and its length into the
794 st_parameter_XXX structure. */
797 set_string (stmtblock_t
* block
, stmtblock_t
* postblock
, tree var
,
798 enum iofield type
, gfc_expr
* e
)
804 gfc_st_parameter_field
*p
= &st_parameter_field
[type
];
806 gfc_init_se (&se
, NULL
);
808 if (p
->param_type
== IOPARM_ptype_common
)
809 var
= fold_build3_loc (input_location
, COMPONENT_REF
,
810 st_parameter
[IOPARM_ptype_common
].type
,
811 var
, TYPE_FIELDS (TREE_TYPE (var
)), NULL_TREE
);
812 io
= fold_build3_loc (input_location
, COMPONENT_REF
, TREE_TYPE (p
->field
),
813 var
, p
->field
, NULL_TREE
);
814 len
= fold_build3_loc (input_location
, COMPONENT_REF
,
815 TREE_TYPE (p
->field_len
),
816 var
, p
->field_len
, NULL_TREE
);
818 /* Integer variable assigned a format label. */
819 if (e
->ts
.type
== BT_INTEGER
821 && e
->symtree
->n
.sym
->attr
.assign
== 1)
826 gfc_conv_label_variable (&se
, e
);
827 tmp
= GFC_DECL_STRING_LEN (se
.expr
);
828 cond
= fold_build2_loc (input_location
, LT_EXPR
, logical_type_node
,
829 tmp
, build_int_cst (TREE_TYPE (tmp
), 0));
831 msg
= xasprintf ("Label assigned to variable '%s' (%%ld) is not a format "
832 "label", e
->symtree
->name
);
833 gfc_trans_runtime_check (true, false, cond
, &se
.pre
, &e
->where
, msg
,
834 fold_convert (long_integer_type_node
, tmp
));
837 gfc_add_modify (&se
.pre
, io
,
838 fold_convert (TREE_TYPE (io
), GFC_DECL_ASSIGN_ADDR (se
.expr
)));
839 gfc_add_modify (&se
.pre
, len
, GFC_DECL_STRING_LEN (se
.expr
));
843 /* General character. */
844 if (e
->ts
.type
== BT_CHARACTER
&& e
->rank
== 0)
845 gfc_conv_expr (&se
, e
);
846 /* Array assigned Hollerith constant or character array. */
847 else if (e
->rank
> 0 || (e
->symtree
&& e
->symtree
->n
.sym
->as
->rank
> 0))
848 gfc_convert_array_to_string (&se
, e
);
852 gfc_conv_string_parameter (&se
);
853 gfc_add_modify (&se
.pre
, io
, fold_convert (TREE_TYPE (io
), se
.expr
));
854 gfc_add_modify (&se
.pre
, len
, fold_convert (TREE_TYPE (len
),
858 gfc_add_block_to_block (block
, &se
.pre
);
859 gfc_add_block_to_block (postblock
, &se
.post
);
864 /* Generate code to store the character (array) and the character length
865 for an internal unit. */
868 set_internal_unit (stmtblock_t
* block
, stmtblock_t
* post_block
,
869 tree var
, gfc_expr
* e
)
876 gfc_st_parameter_field
*p
;
879 gfc_init_se (&se
, NULL
);
881 p
= &st_parameter_field
[IOPARM_dt_internal_unit
];
883 io
= fold_build3_loc (input_location
, COMPONENT_REF
, TREE_TYPE (p
->field
),
884 var
, p
->field
, NULL_TREE
);
885 len
= fold_build3_loc (input_location
, COMPONENT_REF
, TREE_TYPE (p
->field_len
),
886 var
, p
->field_len
, NULL_TREE
);
887 p
= &st_parameter_field
[IOPARM_dt_internal_unit_desc
];
888 desc
= fold_build3_loc (input_location
, COMPONENT_REF
, TREE_TYPE (p
->field
),
889 var
, p
->field
, NULL_TREE
);
891 gcc_assert (e
->ts
.type
== BT_CHARACTER
);
893 /* Character scalars. */
896 gfc_conv_expr (&se
, e
);
897 gfc_conv_string_parameter (&se
);
899 se
.expr
= build_int_cst (pchar_type_node
, 0);
902 /* Character array. */
903 else if (e
->rank
> 0)
905 if (is_subref_array (e
))
907 /* Use a temporary for components of arrays of derived types
908 or substring array references. */
909 gfc_conv_subref_array_arg (&se
, e
, 0,
910 last_dt
== READ
? INTENT_IN
: INTENT_OUT
, false);
911 tmp
= build_fold_indirect_ref_loc (input_location
,
913 se
.expr
= gfc_build_addr_expr (pchar_type_node
, tmp
);
914 tmp
= gfc_conv_descriptor_data_get (tmp
);
918 /* Return the data pointer and rank from the descriptor. */
919 gfc_conv_expr_descriptor (&se
, e
);
920 tmp
= gfc_conv_descriptor_data_get (se
.expr
);
921 se
.expr
= gfc_build_addr_expr (pchar_type_node
, se
.expr
);
927 /* The cast is needed for character substrings and the descriptor
929 gfc_add_modify (&se
.pre
, io
, fold_convert (TREE_TYPE (io
), tmp
));
930 gfc_add_modify (&se
.pre
, len
,
931 fold_convert (TREE_TYPE (len
), se
.string_length
));
932 gfc_add_modify (&se
.pre
, desc
, se
.expr
);
934 gfc_add_block_to_block (block
, &se
.pre
);
935 gfc_add_block_to_block (post_block
, &se
.post
);
939 /* Add a case to a IO-result switch. */
942 add_case (int label_value
, gfc_st_label
* label
, stmtblock_t
* body
)
947 return; /* No label, no case */
949 value
= build_int_cst (integer_type_node
, label_value
);
951 /* Make a backend label for this case. */
952 tmp
= gfc_build_label_decl (NULL_TREE
);
954 /* And the case itself. */
955 tmp
= build_case_label (value
, NULL_TREE
, tmp
);
956 gfc_add_expr_to_block (body
, tmp
);
958 /* Jump to the label. */
959 tmp
= build1_v (GOTO_EXPR
, gfc_get_label_decl (label
));
960 gfc_add_expr_to_block (body
, tmp
);
964 /* Generate a switch statement that branches to the correct I/O
965 result label. The last statement of an I/O call stores the
966 result into a variable because there is often cleanup that
967 must be done before the switch, so a temporary would have to
968 be created anyway. */
971 io_result (stmtblock_t
* block
, tree var
, gfc_st_label
* err_label
,
972 gfc_st_label
* end_label
, gfc_st_label
* eor_label
)
976 gfc_st_parameter_field
*p
= &st_parameter_field
[IOPARM_common_flags
];
978 /* If no labels are specified, ignore the result instead
979 of building an empty switch. */
980 if (err_label
== NULL
982 && eor_label
== NULL
)
985 /* Build a switch statement. */
986 gfc_start_block (&body
);
988 /* The label values here must be the same as the values
989 in the library_return enum in the runtime library */
990 add_case (1, err_label
, &body
);
991 add_case (2, end_label
, &body
);
992 add_case (3, eor_label
, &body
);
994 tmp
= gfc_finish_block (&body
);
996 var
= fold_build3_loc (input_location
, COMPONENT_REF
,
997 st_parameter
[IOPARM_ptype_common
].type
,
998 var
, TYPE_FIELDS (TREE_TYPE (var
)), NULL_TREE
);
999 rc
= fold_build3_loc (input_location
, COMPONENT_REF
, TREE_TYPE (p
->field
),
1000 var
, p
->field
, NULL_TREE
);
1001 rc
= fold_build2_loc (input_location
, BIT_AND_EXPR
, TREE_TYPE (rc
),
1002 rc
, build_int_cst (TREE_TYPE (rc
),
1003 IOPARM_common_libreturn_mask
));
1005 tmp
= fold_build2_loc (input_location
, SWITCH_EXPR
, NULL_TREE
, rc
, tmp
);
1007 gfc_add_expr_to_block (block
, tmp
);
1011 /* Store the current file and line number to variables so that if a
1012 library call goes awry, we can tell the user where the problem is. */
1015 set_error_locus (stmtblock_t
* block
, tree var
, locus
* where
)
1018 tree str
, locus_file
;
1020 gfc_st_parameter_field
*p
= &st_parameter_field
[IOPARM_common_filename
];
1022 locus_file
= fold_build3_loc (input_location
, COMPONENT_REF
,
1023 st_parameter
[IOPARM_ptype_common
].type
,
1024 var
, TYPE_FIELDS (TREE_TYPE (var
)), NULL_TREE
);
1025 locus_file
= fold_build3_loc (input_location
, COMPONENT_REF
,
1026 TREE_TYPE (p
->field
), locus_file
,
1027 p
->field
, NULL_TREE
);
1028 f
= where
->lb
->file
;
1029 str
= gfc_build_cstring_const (f
->filename
);
1031 str
= gfc_build_addr_expr (pchar_type_node
, str
);
1032 gfc_add_modify (block
, locus_file
, str
);
1034 line
= LOCATION_LINE (where
->lb
->location
);
1035 set_parameter_const (block
, var
, IOPARM_common_line
, line
);
1039 /* Translate an OPEN statement. */
1042 gfc_trans_open (gfc_code
* code
)
1044 stmtblock_t block
, post_block
;
1047 unsigned int mask
= 0;
1049 gfc_start_block (&block
);
1050 gfc_init_block (&post_block
);
1052 var
= gfc_create_var (st_parameter
[IOPARM_ptype_open
].type
, "open_parm");
1054 set_error_locus (&block
, var
, &code
->loc
);
1058 mask
|= set_string (&block
, &post_block
, var
, IOPARM_common_iomsg
,
1062 mask
|= set_parameter_ref (&block
, &post_block
, var
, IOPARM_common_iostat
,
1066 mask
|= IOPARM_common_err
;
1069 mask
|= set_string (&block
, &post_block
, var
, IOPARM_open_file
, p
->file
);
1072 mask
|= set_string (&block
, &post_block
, var
, IOPARM_open_status
,
1076 mask
|= set_string (&block
, &post_block
, var
, IOPARM_open_access
,
1080 mask
|= set_string (&block
, &post_block
, var
, IOPARM_open_form
, p
->form
);
1083 mask
|= set_parameter_value (&block
, var
, IOPARM_open_recl_in
,
1087 mask
|= set_string (&block
, &post_block
, var
, IOPARM_open_blank
,
1091 mask
|= set_string (&block
, &post_block
, var
, IOPARM_open_position
,
1095 mask
|= set_string (&block
, &post_block
, var
, IOPARM_open_action
,
1099 mask
|= set_string (&block
, &post_block
, var
, IOPARM_open_delim
,
1103 mask
|= set_string (&block
, &post_block
, var
, IOPARM_open_pad
, p
->pad
);
1106 mask
|= set_string (&block
, &post_block
, var
, IOPARM_open_decimal
,
1110 mask
|= set_string (&block
, &post_block
, var
, IOPARM_open_encoding
,
1114 mask
|= set_string (&block
, &post_block
, var
, IOPARM_open_round
, p
->round
);
1117 mask
|= set_string (&block
, &post_block
, var
, IOPARM_open_sign
, p
->sign
);
1119 if (p
->asynchronous
)
1120 mask
|= set_string (&block
, &post_block
, var
, IOPARM_open_asynchronous
,
1124 mask
|= set_string (&block
, &post_block
, var
, IOPARM_open_convert
,
1128 mask
|= set_parameter_ref (&block
, &post_block
, var
, IOPARM_open_newunit
,
1132 mask
|= set_string (&block
, &post_block
, var
, IOPARM_open_cc
, p
->cc
);
1135 mask
|= set_string (&block
, &post_block
, var
, IOPARM_open_share
, p
->share
);
1137 mask
|= set_parameter_const (&block
, var
, IOPARM_open_readonly
, p
->readonly
);
1139 set_parameter_const (&block
, var
, IOPARM_common_flags
, mask
);
1142 set_parameter_value_chk (&block
, p
->iostat
, var
, IOPARM_common_unit
, p
->unit
);
1144 set_parameter_const (&block
, var
, IOPARM_common_unit
, 0);
1146 tmp
= gfc_build_addr_expr (NULL_TREE
, var
);
1147 tmp
= build_call_expr_loc (input_location
,
1148 iocall
[IOCALL_OPEN
], 1, tmp
);
1149 gfc_add_expr_to_block (&block
, tmp
);
1151 gfc_add_block_to_block (&block
, &post_block
);
1153 io_result (&block
, var
, p
->err
, NULL
, NULL
);
1155 return gfc_finish_block (&block
);
1159 /* Translate a CLOSE statement. */
1162 gfc_trans_close (gfc_code
* code
)
1164 stmtblock_t block
, post_block
;
1167 unsigned int mask
= 0;
1169 gfc_start_block (&block
);
1170 gfc_init_block (&post_block
);
1172 var
= gfc_create_var (st_parameter
[IOPARM_ptype_close
].type
, "close_parm");
1174 set_error_locus (&block
, var
, &code
->loc
);
1175 p
= code
->ext
.close
;
1178 mask
|= set_string (&block
, &post_block
, var
, IOPARM_common_iomsg
,
1182 mask
|= set_parameter_ref (&block
, &post_block
, var
, IOPARM_common_iostat
,
1186 mask
|= IOPARM_common_err
;
1189 mask
|= set_string (&block
, &post_block
, var
, IOPARM_close_status
,
1192 set_parameter_const (&block
, var
, IOPARM_common_flags
, mask
);
1195 set_parameter_value_chk (&block
, p
->iostat
, var
, IOPARM_common_unit
, p
->unit
);
1197 set_parameter_const (&block
, var
, IOPARM_common_unit
, 0);
1199 tmp
= gfc_build_addr_expr (NULL_TREE
, var
);
1200 tmp
= build_call_expr_loc (input_location
,
1201 iocall
[IOCALL_CLOSE
], 1, tmp
);
1202 gfc_add_expr_to_block (&block
, tmp
);
1204 gfc_add_block_to_block (&block
, &post_block
);
1206 io_result (&block
, var
, p
->err
, NULL
, NULL
);
1208 return gfc_finish_block (&block
);
1212 /* Common subroutine for building a file positioning statement. */
1215 build_filepos (tree function
, gfc_code
* code
)
1217 stmtblock_t block
, post_block
;
1220 unsigned int mask
= 0;
1222 p
= code
->ext
.filepos
;
1224 gfc_start_block (&block
);
1225 gfc_init_block (&post_block
);
1227 var
= gfc_create_var (st_parameter
[IOPARM_ptype_filepos
].type
,
1230 set_error_locus (&block
, var
, &code
->loc
);
1233 mask
|= set_string (&block
, &post_block
, var
, IOPARM_common_iomsg
,
1237 mask
|= set_parameter_ref (&block
, &post_block
, var
,
1238 IOPARM_common_iostat
, p
->iostat
);
1241 mask
|= IOPARM_common_err
;
1243 set_parameter_const (&block
, var
, IOPARM_common_flags
, mask
);
1246 set_parameter_value_chk (&block
, p
->iostat
, var
, IOPARM_common_unit
,
1249 set_parameter_const (&block
, var
, IOPARM_common_unit
, 0);
1251 tmp
= gfc_build_addr_expr (NULL_TREE
, var
);
1252 tmp
= build_call_expr_loc (input_location
,
1254 gfc_add_expr_to_block (&block
, tmp
);
1256 gfc_add_block_to_block (&block
, &post_block
);
1258 io_result (&block
, var
, p
->err
, NULL
, NULL
);
1260 return gfc_finish_block (&block
);
1264 /* Translate a BACKSPACE statement. */
1267 gfc_trans_backspace (gfc_code
* code
)
1269 return build_filepos (iocall
[IOCALL_BACKSPACE
], code
);
1273 /* Translate an ENDFILE statement. */
1276 gfc_trans_endfile (gfc_code
* code
)
1278 return build_filepos (iocall
[IOCALL_ENDFILE
], code
);
1282 /* Translate a REWIND statement. */
1285 gfc_trans_rewind (gfc_code
* code
)
1287 return build_filepos (iocall
[IOCALL_REWIND
], code
);
1291 /* Translate a FLUSH statement. */
1294 gfc_trans_flush (gfc_code
* code
)
1296 return build_filepos (iocall
[IOCALL_FLUSH
], code
);
1300 /* Translate the non-IOLENGTH form of an INQUIRE statement. */
1303 gfc_trans_inquire (gfc_code
* code
)
1305 stmtblock_t block
, post_block
;
1308 unsigned int mask
= 0, mask2
= 0;
1310 gfc_start_block (&block
);
1311 gfc_init_block (&post_block
);
1313 var
= gfc_create_var (st_parameter
[IOPARM_ptype_inquire
].type
,
1316 set_error_locus (&block
, var
, &code
->loc
);
1317 p
= code
->ext
.inquire
;
1320 mask
|= set_string (&block
, &post_block
, var
, IOPARM_common_iomsg
,
1324 mask
|= set_parameter_ref (&block
, &post_block
, var
, IOPARM_common_iostat
,
1328 mask
|= IOPARM_common_err
;
1331 if (p
->unit
&& p
->file
)
1332 gfc_error ("INQUIRE statement at %L cannot contain both FILE and UNIT specifiers", &code
->loc
);
1335 mask
|= set_string (&block
, &post_block
, var
, IOPARM_inquire_file
,
1339 mask
|= set_parameter_ref (&block
, &post_block
, var
, IOPARM_inquire_exist
,
1343 mask
|= set_parameter_ref (&block
, &post_block
, var
, IOPARM_inquire_opened
,
1347 mask
|= set_parameter_ref (&block
, &post_block
, var
, IOPARM_inquire_number
,
1351 mask
|= set_parameter_ref (&block
, &post_block
, var
, IOPARM_inquire_named
,
1355 mask
|= set_string (&block
, &post_block
, var
, IOPARM_inquire_name
,
1359 mask
|= set_string (&block
, &post_block
, var
, IOPARM_inquire_access
,
1363 mask
|= set_string (&block
, &post_block
, var
, IOPARM_inquire_sequential
,
1367 mask
|= set_string (&block
, &post_block
, var
, IOPARM_inquire_direct
,
1371 mask
|= set_string (&block
, &post_block
, var
, IOPARM_inquire_form
,
1375 mask
|= set_string (&block
, &post_block
, var
, IOPARM_inquire_formatted
,
1379 mask
|= set_string (&block
, &post_block
, var
, IOPARM_inquire_unformatted
,
1383 mask
|= set_parameter_ref (&block
, &post_block
, var
,
1384 IOPARM_inquire_recl_out
, p
->recl
);
1387 mask
|= set_parameter_ref (&block
, &post_block
, var
,
1388 IOPARM_inquire_nextrec
, p
->nextrec
);
1391 mask
|= set_string (&block
, &post_block
, var
, IOPARM_inquire_blank
,
1395 mask
|= set_string (&block
, &post_block
, var
, IOPARM_inquire_delim
,
1399 mask
|= set_string (&block
, &post_block
, var
, IOPARM_inquire_position
,
1403 mask
|= set_string (&block
, &post_block
, var
, IOPARM_inquire_action
,
1407 mask
|= set_string (&block
, &post_block
, var
, IOPARM_inquire_read
,
1411 mask
|= set_string (&block
, &post_block
, var
, IOPARM_inquire_write
,
1415 mask
|= set_string (&block
, &post_block
, var
, IOPARM_inquire_readwrite
,
1419 mask
|= set_string (&block
, &post_block
, var
, IOPARM_inquire_pad
,
1423 mask
|= set_string (&block
, &post_block
, var
, IOPARM_inquire_convert
,
1427 mask
|= set_parameter_ref (&block
, &post_block
, var
,
1428 IOPARM_inquire_strm_pos_out
, p
->strm_pos
);
1430 /* The second series of flags. */
1431 if (p
->asynchronous
)
1432 mask2
|= set_string (&block
, &post_block
, var
, IOPARM_inquire_asynchronous
,
1436 mask2
|= set_string (&block
, &post_block
, var
, IOPARM_inquire_decimal
,
1440 mask2
|= set_string (&block
, &post_block
, var
, IOPARM_inquire_encoding
,
1444 mask2
|= set_string (&block
, &post_block
, var
, IOPARM_inquire_round
,
1448 mask2
|= set_string (&block
, &post_block
, var
, IOPARM_inquire_sign
,
1452 mask2
|= set_parameter_ref (&block
, &post_block
, var
,
1453 IOPARM_inquire_pending
, p
->pending
);
1456 mask2
|= set_parameter_ref (&block
, &post_block
, var
, IOPARM_inquire_size
,
1460 mask2
|= set_parameter_ref (&block
, &post_block
,var
, IOPARM_inquire_id
,
1463 mask2
|= set_string (&block
, &post_block
, var
, IOPARM_inquire_iqstream
,
1467 mask2
|= set_string (&block
, &post_block
, var
, IOPARM_inquire_share
,
1471 mask2
|= set_string (&block
, &post_block
, var
, IOPARM_inquire_cc
, p
->cc
);
1474 mask
|= set_parameter_const (&block
, var
, IOPARM_inquire_flags2
, mask2
);
1476 set_parameter_const (&block
, var
, IOPARM_common_flags
, mask
);
1480 set_parameter_value (&block
, var
, IOPARM_common_unit
, p
->unit
);
1481 set_parameter_value_inquire (&block
, var
, IOPARM_common_unit
, p
->unit
);
1484 set_parameter_const (&block
, var
, IOPARM_common_unit
, 0);
1486 tmp
= gfc_build_addr_expr (NULL_TREE
, var
);
1487 tmp
= build_call_expr_loc (input_location
,
1488 iocall
[IOCALL_INQUIRE
], 1, tmp
);
1489 gfc_add_expr_to_block (&block
, tmp
);
1491 gfc_add_block_to_block (&block
, &post_block
);
1493 io_result (&block
, var
, p
->err
, NULL
, NULL
);
1495 return gfc_finish_block (&block
);
1500 gfc_trans_wait (gfc_code
* code
)
1502 stmtblock_t block
, post_block
;
1505 unsigned int mask
= 0;
1507 gfc_start_block (&block
);
1508 gfc_init_block (&post_block
);
1510 var
= gfc_create_var (st_parameter
[IOPARM_ptype_wait
].type
,
1513 set_error_locus (&block
, var
, &code
->loc
);
1516 /* Set parameters here. */
1518 mask
|= set_string (&block
, &post_block
, var
, IOPARM_common_iomsg
,
1522 mask
|= set_parameter_ref (&block
, &post_block
, var
, IOPARM_common_iostat
,
1526 mask
|= IOPARM_common_err
;
1529 mask
|= set_parameter_ref (&block
, &post_block
, var
, IOPARM_wait_id
, p
->id
);
1531 set_parameter_const (&block
, var
, IOPARM_common_flags
, mask
);
1534 set_parameter_value_chk (&block
, p
->iostat
, var
, IOPARM_common_unit
, p
->unit
);
1536 tmp
= gfc_build_addr_expr (NULL_TREE
, var
);
1537 tmp
= build_call_expr_loc (input_location
,
1538 iocall
[IOCALL_WAIT
], 1, tmp
);
1539 gfc_add_expr_to_block (&block
, tmp
);
1541 gfc_add_block_to_block (&block
, &post_block
);
1543 io_result (&block
, var
, p
->err
, NULL
, NULL
);
1545 return gfc_finish_block (&block
);
1550 /* nml_full_name builds up the fully qualified name of a
1551 derived type component. '+' is used to denote a type extension. */
1554 nml_full_name (const char* var_name
, const char* cmp_name
, bool parent
)
1556 int full_name_length
;
1559 full_name_length
= strlen (var_name
) + strlen (cmp_name
) + 1;
1560 full_name
= XCNEWVEC (char, full_name_length
+ 1);
1561 strcpy (full_name
, var_name
);
1562 full_name
= strcat (full_name
, parent
? "+" : "%");
1563 full_name
= strcat (full_name
, cmp_name
);
1568 /* nml_get_addr_expr builds an address expression from the
1569 gfc_symbol or gfc_component backend_decl's. An offset is
1570 provided so that the address of an element of an array of
1571 derived types is returned. This is used in the runtime to
1572 determine that span of the derived type. */
1575 nml_get_addr_expr (gfc_symbol
* sym
, gfc_component
* c
,
1578 tree decl
= NULL_TREE
;
1583 sym
->attr
.referenced
= 1;
1584 decl
= gfc_get_symbol_decl (sym
);
1586 /* If this is the enclosing function declaration, use
1587 the fake result instead. */
1588 if (decl
== current_function_decl
)
1589 decl
= gfc_get_fake_result_decl (sym
, 0);
1590 else if (decl
== DECL_CONTEXT (current_function_decl
))
1591 decl
= gfc_get_fake_result_decl (sym
, 1);
1594 decl
= c
->backend_decl
;
1596 gcc_assert (decl
&& (TREE_CODE (decl
) == FIELD_DECL
1598 || TREE_CODE (decl
) == PARM_DECL
1599 || TREE_CODE (decl
) == COMPONENT_REF
));
1603 /* Build indirect reference, if dummy argument. */
1605 if (POINTER_TYPE_P (TREE_TYPE(tmp
)))
1606 tmp
= build_fold_indirect_ref_loc (input_location
, tmp
);
1608 /* Treat the component of a derived type, using base_addr for
1609 the derived type. */
1611 if (TREE_CODE (decl
) == FIELD_DECL
)
1612 tmp
= fold_build3_loc (input_location
, COMPONENT_REF
, TREE_TYPE (tmp
),
1613 base_addr
, tmp
, NULL_TREE
);
1615 if (GFC_CLASS_TYPE_P (TREE_TYPE (tmp
))
1616 && GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (gfc_class_data_get (tmp
))))
1617 tmp
= gfc_class_data_get (tmp
);
1619 if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (tmp
)))
1620 tmp
= gfc_conv_array_data (tmp
);
1623 if (!POINTER_TYPE_P (TREE_TYPE (tmp
)))
1624 tmp
= gfc_build_addr_expr (NULL_TREE
, tmp
);
1626 if (TREE_CODE (TREE_TYPE (tmp
)) == ARRAY_TYPE
)
1627 tmp
= gfc_build_array_ref (tmp
, gfc_index_zero_node
, NULL
);
1629 if (!POINTER_TYPE_P (TREE_TYPE (tmp
)))
1630 tmp
= build_fold_indirect_ref_loc (input_location
,
1634 gcc_assert (tmp
&& POINTER_TYPE_P (TREE_TYPE (tmp
)));
1640 /* For an object VAR_NAME whose base address is BASE_ADDR, generate a
1641 call to iocall[IOCALL_SET_NML_VAL]. For derived type variable, recursively
1642 generate calls to iocall[IOCALL_SET_NML_VAL] for each component. */
1644 #define IARG(i) build_int_cst (gfc_array_index_type, i)
1647 transfer_namelist_element (stmtblock_t
* block
, const char * var_name
,
1648 gfc_symbol
* sym
, gfc_component
* c
,
1651 gfc_typespec
* ts
= NULL
;
1652 gfc_array_spec
* as
= NULL
;
1653 tree addr_expr
= NULL
;
1659 tree decl
= NULL_TREE
;
1660 tree gfc_int4_type_node
= gfc_get_int_type (4);
1661 tree dtio_proc
= null_pointer_node
;
1662 tree vtable
= null_pointer_node
;
1666 gcc_assert (sym
|| c
);
1668 /* Build the namelist object name. */
1670 string
= gfc_build_cstring_const (var_name
);
1671 string
= gfc_build_addr_expr (pchar_type_node
, string
);
1673 /* Build ts, as and data address using symbol or component. */
1675 ts
= sym
? &sym
->ts
: &c
->ts
;
1677 if (ts
->type
!= BT_CLASS
)
1678 as
= sym
? sym
->as
: c
->as
;
1680 as
= sym
? CLASS_DATA (sym
)->as
: CLASS_DATA (c
)->as
;
1682 addr_expr
= nml_get_addr_expr (sym
, c
, base_addr
);
1689 decl
= sym
? sym
->backend_decl
: c
->backend_decl
;
1690 if (sym
&& sym
->attr
.dummy
)
1691 decl
= build_fold_indirect_ref_loc (input_location
, decl
);
1693 if (ts
->type
== BT_CLASS
)
1694 decl
= gfc_class_data_get (decl
);
1695 dt
= TREE_TYPE (decl
);
1696 dtype
= gfc_get_dtype (dt
);
1700 dt
= gfc_typenode_for_spec (ts
);
1701 dtype
= gfc_get_dtype_rank_type (0, dt
);
1704 /* Build up the arguments for the transfer call.
1705 The call for the scalar part transfers:
1706 (address, name, type, kind or string_length, dtype) */
1708 dt_parm_addr
= gfc_build_addr_expr (NULL_TREE
, dt_parm
);
1710 /* Check if the derived type has a specific DTIO for the mode.
1711 Note that although namelist io is forbidden to have a format
1712 list, the specific subroutine is of the formatted kind. */
1713 if (ts
->type
== BT_DERIVED
|| ts
->type
== BT_CLASS
)
1715 gfc_symbol
*derived
;
1716 if (ts
->type
==BT_CLASS
)
1717 derived
= ts
->u
.derived
->components
->ts
.u
.derived
;
1719 derived
= ts
->u
.derived
;
1721 gfc_symtree
*tb_io_st
= gfc_find_typebound_dtio_proc (derived
,
1722 last_dt
== WRITE
, true);
1724 if (ts
->type
== BT_CLASS
&& tb_io_st
)
1726 // polymorphic DTIO call (based on the dynamic type)
1728 gfc_symtree
*st
= gfc_find_symtree (sym
->ns
->sym_root
, sym
->name
);
1729 // build vtable expr
1730 gfc_expr
*expr
= gfc_get_variable_expr (st
);
1731 gfc_add_vptr_component (expr
);
1732 gfc_init_se (&se
, NULL
);
1733 se
.want_pointer
= 1;
1734 gfc_conv_expr (&se
, expr
);
1737 gfc_add_component_ref (expr
,
1738 tb_io_st
->n
.tb
->u
.generic
->specific_st
->name
);
1739 gfc_init_se (&se
, NULL
);
1740 se
.want_pointer
= 1;
1741 gfc_conv_expr (&se
, expr
);
1742 gfc_free_expr (expr
);
1743 dtio_proc
= se
.expr
;
1747 // non-polymorphic DTIO call (based on the declared type)
1748 gfc_symbol
*dtio_sub
= gfc_find_specific_dtio_proc (derived
,
1749 last_dt
== WRITE
, true);
1750 if (dtio_sub
!= NULL
)
1752 dtio_proc
= gfc_get_symbol_decl (dtio_sub
);
1753 dtio_proc
= gfc_build_addr_expr (NULL
, dtio_proc
);
1754 gfc_symbol
*vtab
= gfc_find_derived_vtab (derived
);
1755 vtable
= vtab
->backend_decl
;
1756 if (vtable
== NULL_TREE
)
1757 vtable
= gfc_get_symbol_decl (vtab
);
1758 vtable
= gfc_build_addr_expr (pvoid_type_node
, vtable
);
1763 if (ts
->type
== BT_CHARACTER
)
1764 tmp
= ts
->u
.cl
->backend_decl
;
1766 tmp
= build_int_cst (gfc_charlen_type_node
, 0);
1768 if (dtio_proc
== null_pointer_node
)
1769 tmp
= build_call_expr_loc (input_location
,
1770 iocall
[IOCALL_SET_NML_VAL
], 6,
1771 dt_parm_addr
, addr_expr
, string
,
1772 build_int_cst (gfc_int4_type_node
, ts
->kind
),
1775 tmp
= build_call_expr_loc (input_location
,
1776 iocall
[IOCALL_SET_NML_DTIO_VAL
], 8,
1777 dt_parm_addr
, addr_expr
, string
,
1778 build_int_cst (gfc_int4_type_node
, ts
->kind
),
1779 tmp
, dtype
, dtio_proc
, vtable
);
1780 gfc_add_expr_to_block (block
, tmp
);
1782 /* If the object is an array, transfer rank times:
1783 (null pointer, name, stride, lbound, ubound) */
1785 for ( n_dim
= 0 ; n_dim
< rank
; n_dim
++ )
1787 tmp
= build_call_expr_loc (input_location
,
1788 iocall
[IOCALL_SET_NML_VAL_DIM
], 5,
1790 build_int_cst (gfc_int4_type_node
, n_dim
),
1791 gfc_conv_array_stride (decl
, n_dim
),
1792 gfc_conv_array_lbound (decl
, n_dim
),
1793 gfc_conv_array_ubound (decl
, n_dim
));
1794 gfc_add_expr_to_block (block
, tmp
);
1797 if (gfc_bt_struct (ts
->type
) && ts
->u
.derived
->components
1798 && dtio_proc
== null_pointer_node
)
1802 /* Provide the RECORD_TYPE to build component references. */
1804 tree expr
= build_fold_indirect_ref_loc (input_location
,
1807 for (cmp
= ts
->u
.derived
->components
; cmp
; cmp
= cmp
->next
)
1809 char *full_name
= nml_full_name (var_name
, cmp
->name
,
1810 ts
->u
.derived
->attr
.extension
);
1811 transfer_namelist_element (block
,
1821 /* Create a data transfer statement. Not all of the fields are valid
1822 for both reading and writing, but improper use has been filtered
1826 build_dt (tree function
, gfc_code
* code
)
1828 stmtblock_t block
, post_block
, post_end_block
, post_iu_block
;
1833 unsigned int mask
= 0;
1835 gfc_start_block (&block
);
1836 gfc_init_block (&post_block
);
1837 gfc_init_block (&post_end_block
);
1838 gfc_init_block (&post_iu_block
);
1840 var
= gfc_create_var (st_parameter
[IOPARM_ptype_dt
].type
, "dt_parm");
1842 set_error_locus (&block
, var
, &code
->loc
);
1844 if (last_dt
== IOLENGTH
)
1848 inq
= code
->ext
.inquire
;
1850 /* First check that preconditions are met. */
1851 gcc_assert (inq
!= NULL
);
1852 gcc_assert (inq
->iolength
!= NULL
);
1854 /* Connect to the iolength variable. */
1855 mask
|= set_parameter_ref (&block
, &post_end_block
, var
,
1856 IOPARM_dt_iolength
, inq
->iolength
);
1862 gcc_assert (dt
!= NULL
);
1865 if (dt
&& dt
->io_unit
)
1867 if (dt
->io_unit
->ts
.type
== BT_CHARACTER
)
1869 mask
|= set_internal_unit (&block
, &post_iu_block
,
1871 set_parameter_const (&block
, var
, IOPARM_common_unit
,
1872 dt
->io_unit
->ts
.kind
== 1 ?
1873 GFC_INTERNAL_UNIT
: GFC_INTERNAL_UNIT4
);
1877 set_parameter_const (&block
, var
, IOPARM_common_unit
, 0);
1882 mask
|= set_string (&block
, &post_block
, var
, IOPARM_common_iomsg
,
1886 mask
|= set_parameter_ref (&block
, &post_end_block
, var
,
1887 IOPARM_common_iostat
, dt
->iostat
);
1890 mask
|= IOPARM_common_err
;
1893 mask
|= IOPARM_common_eor
;
1896 mask
|= IOPARM_common_end
;
1899 mask
|= set_parameter_ref (&block
, &post_end_block
, var
,
1900 IOPARM_dt_id
, dt
->id
);
1903 mask
|= set_parameter_value (&block
, var
, IOPARM_dt_pos
, dt
->pos
);
1905 if (dt
->asynchronous
)
1906 mask
|= set_string (&block
, &post_block
, var
,
1907 IOPARM_dt_asynchronous
, dt
->asynchronous
);
1910 mask
|= set_string (&block
, &post_block
, var
, IOPARM_dt_blank
,
1914 mask
|= set_string (&block
, &post_block
, var
, IOPARM_dt_decimal
,
1918 mask
|= set_string (&block
, &post_block
, var
, IOPARM_dt_delim
,
1922 mask
|= set_string (&block
, &post_block
, var
, IOPARM_dt_pad
,
1926 mask
|= set_string (&block
, &post_block
, var
, IOPARM_dt_round
,
1930 mask
|= set_string (&block
, &post_block
, var
, IOPARM_dt_sign
,
1934 mask
|= set_parameter_value (&block
, var
, IOPARM_dt_rec
, dt
->rec
);
1937 mask
|= set_string (&block
, &post_block
, var
, IOPARM_dt_advance
,
1940 if (dt
->format_expr
)
1941 mask
|= set_string (&block
, &post_end_block
, var
, IOPARM_dt_format
,
1944 if (dt
->format_label
)
1946 if (dt
->format_label
== &format_asterisk
)
1947 mask
|= IOPARM_dt_list_format
;
1949 mask
|= set_string (&block
, &post_block
, var
, IOPARM_dt_format
,
1950 dt
->format_label
->format
);
1954 mask
|= set_parameter_ref (&block
, &post_end_block
, var
,
1955 IOPARM_dt_size
, dt
->size
);
1958 mask
|= IOPARM_dt_dtio
;
1961 mask
|= IOPARM_dt_dec_ext
;
1965 if (dt
->format_expr
|| dt
->format_label
)
1966 gfc_internal_error ("build_dt: format with namelist");
1968 nmlname
= gfc_get_character_expr (gfc_default_character_kind
, NULL
,
1970 strlen (dt
->namelist
->name
));
1972 mask
|= set_string (&block
, &post_block
, var
, IOPARM_dt_namelist_name
,
1975 gfc_free_expr (nmlname
);
1977 if (last_dt
== READ
)
1978 mask
|= IOPARM_dt_namelist_read_mode
;
1980 set_parameter_const (&block
, var
, IOPARM_common_flags
, mask
);
1984 for (nml
= dt
->namelist
->namelist
; nml
; nml
= nml
->next
)
1985 transfer_namelist_element (&block
, nml
->sym
->name
, nml
->sym
,
1989 set_parameter_const (&block
, var
, IOPARM_common_flags
, mask
);
1991 if (dt
->io_unit
&& dt
->io_unit
->ts
.type
== BT_INTEGER
)
1992 set_parameter_value_chk (&block
, dt
->iostat
, var
,
1993 IOPARM_common_unit
, dt
->io_unit
);
1996 set_parameter_const (&block
, var
, IOPARM_common_flags
, mask
);
1998 tmp
= gfc_build_addr_expr (NULL_TREE
, var
);
1999 tmp
= build_call_expr_loc (UNKNOWN_LOCATION
,
2001 gfc_add_expr_to_block (&block
, tmp
);
2003 gfc_add_block_to_block (&block
, &post_block
);
2006 dt_post_end_block
= &post_end_block
;
2008 /* Set implied do loop exit condition. */
2009 if (last_dt
== READ
|| last_dt
== WRITE
)
2011 gfc_st_parameter_field
*p
= &st_parameter_field
[IOPARM_common_flags
];
2013 tmp
= fold_build3_loc (input_location
, COMPONENT_REF
,
2014 st_parameter
[IOPARM_ptype_common
].type
,
2015 dt_parm
, TYPE_FIELDS (TREE_TYPE (dt_parm
)),
2017 tmp
= fold_build3_loc (input_location
, COMPONENT_REF
,
2018 TREE_TYPE (p
->field
), tmp
, p
->field
, NULL_TREE
);
2019 tmp
= fold_build2_loc (input_location
, BIT_AND_EXPR
, TREE_TYPE (tmp
),
2020 tmp
, build_int_cst (TREE_TYPE (tmp
),
2021 IOPARM_common_libreturn_mask
));
2026 gfc_add_expr_to_block (&block
, gfc_trans_code_cond (code
->block
->next
, tmp
));
2028 gfc_add_block_to_block (&block
, &post_iu_block
);
2031 dt_post_end_block
= NULL
;
2033 return gfc_finish_block (&block
);
2037 /* Translate the IOLENGTH form of an INQUIRE statement. We treat
2038 this as a third sort of data transfer statement, except that
2039 lengths are summed instead of actually transferring any data. */
2042 gfc_trans_iolength (gfc_code
* code
)
2045 return build_dt (iocall
[IOCALL_IOLENGTH
], code
);
2049 /* Translate a READ statement. */
2052 gfc_trans_read (gfc_code
* code
)
2055 return build_dt (iocall
[IOCALL_READ
], code
);
2059 /* Translate a WRITE statement */
2062 gfc_trans_write (gfc_code
* code
)
2065 return build_dt (iocall
[IOCALL_WRITE
], code
);
2069 /* Finish a data transfer statement. */
2072 gfc_trans_dt_end (gfc_code
* code
)
2077 gfc_init_block (&block
);
2082 function
= iocall
[IOCALL_READ_DONE
];
2086 function
= iocall
[IOCALL_WRITE_DONE
];
2090 function
= iocall
[IOCALL_IOLENGTH_DONE
];
2097 tmp
= gfc_build_addr_expr (NULL_TREE
, dt_parm
);
2098 tmp
= build_call_expr_loc (input_location
,
2100 gfc_add_expr_to_block (&block
, tmp
);
2101 gfc_add_block_to_block (&block
, dt_post_end_block
);
2102 gfc_init_block (dt_post_end_block
);
2104 if (last_dt
!= IOLENGTH
)
2106 gcc_assert (code
->ext
.dt
!= NULL
);
2107 io_result (&block
, dt_parm
, code
->ext
.dt
->err
,
2108 code
->ext
.dt
->end
, code
->ext
.dt
->eor
);
2111 return gfc_finish_block (&block
);
2115 transfer_expr (gfc_se
* se
, gfc_typespec
* ts
, tree addr_expr
,
2116 gfc_code
* code
, tree vptr
);
2118 /* Given an array field in a derived type variable, generate the code
2119 for the loop that iterates over array elements, and the code that
2120 accesses those array elements. Use transfer_expr to generate code
2121 for transferring that element. Because elements may also be
2122 derived types, transfer_expr and transfer_array_component are mutually
2126 transfer_array_component (tree expr
, gfc_component
* cm
, locus
* where
)
2135 gfc_array_info
*ss_array
;
2137 gfc_start_block (&block
);
2138 gfc_init_se (&se
, NULL
);
2140 /* Create and initialize Scalarization Status. Unlike in
2141 gfc_trans_transfer, we can't simply use gfc_walk_expr to take
2142 care of this task, because we don't have a gfc_expr at hand.
2143 Build one manually, as in gfc_trans_subarray_assign. */
2145 ss
= gfc_get_array_ss (gfc_ss_terminator
, NULL
, cm
->as
->rank
,
2147 ss_array
= &ss
->info
->data
.array
;
2149 if (cm
->attr
.pdt_array
)
2150 ss_array
->shape
= NULL
;
2152 ss_array
->shape
= gfc_get_shape (cm
->as
->rank
);
2154 ss_array
->descriptor
= expr
;
2155 ss_array
->data
= gfc_conv_array_data (expr
);
2156 ss_array
->offset
= gfc_conv_array_offset (expr
);
2157 for (n
= 0; n
< cm
->as
->rank
; n
++)
2159 ss_array
->start
[n
] = gfc_conv_array_lbound (expr
, n
);
2160 ss_array
->stride
[n
] = gfc_index_one_node
;
2162 if (cm
->attr
.pdt_array
)
2163 ss_array
->end
[n
] = gfc_conv_array_ubound (expr
, n
);
2166 mpz_init (ss_array
->shape
[n
]);
2167 mpz_sub (ss_array
->shape
[n
], cm
->as
->upper
[n
]->value
.integer
,
2168 cm
->as
->lower
[n
]->value
.integer
);
2169 mpz_add_ui (ss_array
->shape
[n
], ss_array
->shape
[n
], 1);
2173 /* Once we got ss, we use scalarizer to create the loop. */
2175 gfc_init_loopinfo (&loop
);
2176 gfc_add_ss_to_loop (&loop
, ss
);
2177 gfc_conv_ss_startstride (&loop
);
2178 gfc_conv_loop_setup (&loop
, where
);
2179 gfc_mark_ss_chain_used (ss
, 1);
2180 gfc_start_scalarized_body (&loop
, &body
);
2182 gfc_copy_loopinfo_to_se (&se
, &loop
);
2185 /* gfc_conv_tmp_array_ref assumes that se.expr contains the array. */
2187 gfc_conv_tmp_array_ref (&se
);
2189 /* Now se.expr contains an element of the array. Take the address and pass
2190 it to the IO routines. */
2191 tmp
= gfc_build_addr_expr (NULL_TREE
, se
.expr
);
2192 transfer_expr (&se
, &cm
->ts
, tmp
, NULL
, NULL_TREE
);
2194 /* We are done now with the loop body. Wrap up the scalarizer and
2197 gfc_add_block_to_block (&body
, &se
.pre
);
2198 gfc_add_block_to_block (&body
, &se
.post
);
2200 gfc_trans_scalarizing_loops (&loop
, &body
);
2202 gfc_add_block_to_block (&block
, &loop
.pre
);
2203 gfc_add_block_to_block (&block
, &loop
.post
);
2205 if (!cm
->attr
.pdt_array
)
2207 gcc_assert (ss_array
->shape
!= NULL
);
2208 gfc_free_shape (&ss_array
->shape
, cm
->as
->rank
);
2210 gfc_cleanup_loop (&loop
);
2212 return gfc_finish_block (&block
);
2216 /* Helper function for transfer_expr that looks for the DTIO procedure
2217 either as a typebound binding or in a generic interface. If present,
2218 the address expression of the procedure is returned. It is assumed
2219 that the procedure interface has been checked during resolution. */
2222 get_dtio_proc (gfc_typespec
* ts
, gfc_code
* code
, gfc_symbol
**dtio_sub
)
2224 gfc_symbol
*derived
;
2225 bool formatted
= false;
2226 gfc_dt
*dt
= code
->ext
.dt
;
2228 /* Determine when to use the formatted DTIO procedure. */
2229 if (dt
&& (dt
->format_expr
|| dt
->format_label
))
2232 if (ts
->type
== BT_CLASS
)
2233 derived
= ts
->u
.derived
->components
->ts
.u
.derived
;
2235 derived
= ts
->u
.derived
;
2237 gfc_symtree
*tb_io_st
= gfc_find_typebound_dtio_proc (derived
,
2238 last_dt
== WRITE
, formatted
);
2239 if (ts
->type
== BT_CLASS
&& tb_io_st
)
2241 // polymorphic DTIO call (based on the dynamic type)
2243 gfc_expr
*expr
= gfc_find_and_cut_at_last_class_ref (code
->expr1
);
2244 gfc_add_vptr_component (expr
);
2245 gfc_add_component_ref (expr
,
2246 tb_io_st
->n
.tb
->u
.generic
->specific_st
->name
);
2247 *dtio_sub
= tb_io_st
->n
.tb
->u
.generic
->specific
->u
.specific
->n
.sym
;
2248 gfc_init_se (&se
, NULL
);
2249 se
.want_pointer
= 1;
2250 gfc_conv_expr (&se
, expr
);
2251 gfc_free_expr (expr
);
2256 // non-polymorphic DTIO call (based on the declared type)
2257 *dtio_sub
= gfc_find_specific_dtio_proc (derived
, last_dt
== WRITE
,
2261 return gfc_build_addr_expr (NULL
, gfc_get_symbol_decl (*dtio_sub
));
2267 /* Generate the call for a scalar transfer node. */
2270 transfer_expr (gfc_se
* se
, gfc_typespec
* ts
, tree addr_expr
,
2271 gfc_code
* code
, tree vptr
)
2273 tree tmp
, function
, arg2
, arg3
, field
, expr
;
2277 /* It is possible to get a C_NULL_PTR or C_NULL_FUNPTR expression here if
2278 the user says something like: print *, 'c_null_ptr: ', c_null_ptr
2279 We need to translate the expression to a constant if it's either
2280 C_NULL_PTR or C_NULL_FUNPTR. We could also get a user variable of
2281 type C_PTR or C_FUNPTR, in which case the ts->type may no longer be
2282 BT_DERIVED (could have been changed by gfc_conv_expr). */
2283 if ((ts
->type
== BT_DERIVED
|| ts
->type
== BT_INTEGER
)
2284 && ts
->u
.derived
!= NULL
2285 && (ts
->is_iso_c
== 1 || ts
->u
.derived
->ts
.is_iso_c
== 1))
2287 ts
->type
= BT_INTEGER
;
2288 ts
->kind
= gfc_index_integer_kind
;
2291 /* gfortran reaches here for "print *, c_loc(xxx)". */
2292 if (ts
->type
== BT_VOID
2293 && code
->expr1
&& code
->expr1
->ts
.type
== BT_VOID
2294 && code
->expr1
->symtree
2295 && strcmp (code
->expr1
->symtree
->name
, "c_loc") == 0)
2297 ts
->type
= BT_INTEGER
;
2298 ts
->kind
= gfc_index_integer_kind
;
2309 arg2
= build_int_cst (integer_type_node
, kind
);
2310 if (last_dt
== READ
)
2311 function
= iocall
[IOCALL_X_INTEGER
];
2313 function
= iocall
[IOCALL_X_INTEGER_WRITE
];
2318 arg2
= build_int_cst (integer_type_node
, kind
);
2319 if (last_dt
== READ
)
2321 if (gfc_real16_is_float128
&& ts
->kind
== 16)
2322 function
= iocall
[IOCALL_X_REAL128
];
2324 function
= iocall
[IOCALL_X_REAL
];
2328 if (gfc_real16_is_float128
&& ts
->kind
== 16)
2329 function
= iocall
[IOCALL_X_REAL128_WRITE
];
2331 function
= iocall
[IOCALL_X_REAL_WRITE
];
2337 arg2
= build_int_cst (integer_type_node
, kind
);
2338 if (last_dt
== READ
)
2340 if (gfc_real16_is_float128
&& ts
->kind
== 16)
2341 function
= iocall
[IOCALL_X_COMPLEX128
];
2343 function
= iocall
[IOCALL_X_COMPLEX
];
2347 if (gfc_real16_is_float128
&& ts
->kind
== 16)
2348 function
= iocall
[IOCALL_X_COMPLEX128_WRITE
];
2350 function
= iocall
[IOCALL_X_COMPLEX_WRITE
];
2356 arg2
= build_int_cst (integer_type_node
, kind
);
2357 if (last_dt
== READ
)
2358 function
= iocall
[IOCALL_X_LOGICAL
];
2360 function
= iocall
[IOCALL_X_LOGICAL_WRITE
];
2367 if (se
->string_length
)
2368 arg2
= se
->string_length
;
2371 tmp
= build_fold_indirect_ref_loc (input_location
,
2373 gcc_assert (TREE_CODE (TREE_TYPE (tmp
)) == ARRAY_TYPE
);
2374 arg2
= TYPE_MAX_VALUE (TYPE_DOMAIN (TREE_TYPE (tmp
)));
2375 arg2
= fold_convert (gfc_charlen_type_node
, arg2
);
2377 arg3
= build_int_cst (integer_type_node
, kind
);
2378 if (last_dt
== READ
)
2379 function
= iocall
[IOCALL_X_CHARACTER_WIDE
];
2381 function
= iocall
[IOCALL_X_CHARACTER_WIDE_WRITE
];
2383 tmp
= gfc_build_addr_expr (NULL_TREE
, dt_parm
);
2384 tmp
= build_call_expr_loc (input_location
,
2385 function
, 4, tmp
, addr_expr
, arg2
, arg3
);
2386 gfc_add_expr_to_block (&se
->pre
, tmp
);
2387 gfc_add_block_to_block (&se
->pre
, &se
->post
);
2392 if (se
->string_length
)
2393 arg2
= se
->string_length
;
2396 tmp
= build_fold_indirect_ref_loc (input_location
,
2398 gcc_assert (TREE_CODE (TREE_TYPE (tmp
)) == ARRAY_TYPE
);
2399 arg2
= TYPE_MAX_VALUE (TYPE_DOMAIN (TREE_TYPE (tmp
)));
2401 if (last_dt
== READ
)
2402 function
= iocall
[IOCALL_X_CHARACTER
];
2404 function
= iocall
[IOCALL_X_CHARACTER_WRITE
];
2410 if (ts
->u
.derived
->components
== NULL
)
2412 if (gfc_bt_struct (ts
->type
) || ts
->type
== BT_CLASS
)
2414 gfc_symbol
*derived
;
2415 gfc_symbol
*dtio_sub
= NULL
;
2416 /* Test for a specific DTIO subroutine. */
2417 if (ts
->type
== BT_DERIVED
)
2418 derived
= ts
->u
.derived
;
2420 derived
= ts
->u
.derived
->components
->ts
.u
.derived
;
2422 if (derived
->attr
.has_dtio_procs
)
2423 arg2
= get_dtio_proc (ts
, code
, &dtio_sub
);
2425 if ((dtio_sub
!= NULL
) && (last_dt
!= IOLENGTH
))
2428 decl
= build_fold_indirect_ref_loc (input_location
,
2430 /* Remember that the first dummy of the DTIO subroutines
2431 is CLASS(derived) for extensible derived types, so the
2432 conversion must be done here for derived type and for
2433 scalarized CLASS array element io-list objects. */
2434 if ((ts
->type
== BT_DERIVED
2435 && !(ts
->u
.derived
->attr
.sequence
2436 || ts
->u
.derived
->attr
.is_bind_c
))
2437 || (ts
->type
== BT_CLASS
2438 && !GFC_CLASS_TYPE_P (TREE_TYPE (decl
))))
2439 gfc_conv_derived_to_class (se
, code
->expr1
,
2440 dtio_sub
->formal
->sym
->ts
,
2441 vptr
, false, false);
2442 addr_expr
= se
->expr
;
2443 function
= iocall
[IOCALL_X_DERIVED
];
2446 else if (gfc_bt_struct (ts
->type
))
2448 /* Recurse into the elements of the derived type. */
2449 expr
= gfc_evaluate_now (addr_expr
, &se
->pre
);
2450 expr
= build_fold_indirect_ref_loc (input_location
, expr
);
2452 /* Make sure that the derived type has been built. An external
2453 function, if only referenced in an io statement, requires this
2454 check (see PR58771). */
2455 if (ts
->u
.derived
->backend_decl
== NULL_TREE
)
2456 (void) gfc_typenode_for_spec (ts
);
2458 for (c
= ts
->u
.derived
->components
; c
; c
= c
->next
)
2460 /* Ignore hidden string lengths. */
2461 if (c
->name
[0] == '_')
2464 field
= c
->backend_decl
;
2465 gcc_assert (field
&& TREE_CODE (field
) == FIELD_DECL
);
2467 tmp
= fold_build3_loc (UNKNOWN_LOCATION
,
2468 COMPONENT_REF
, TREE_TYPE (field
),
2469 expr
, field
, NULL_TREE
);
2471 if (c
->attr
.dimension
)
2473 tmp
= transfer_array_component (tmp
, c
, & code
->loc
);
2474 gfc_add_expr_to_block (&se
->pre
, tmp
);
2478 tree strlen
= NULL_TREE
;
2480 if (!c
->attr
.pointer
&& !c
->attr
.pdt_string
)
2481 tmp
= gfc_build_addr_expr (NULL_TREE
, tmp
);
2483 /* Use the hidden string length for pdt strings. */
2484 if (c
->attr
.pdt_string
2485 && gfc_deferred_strlen (c
, &strlen
)
2486 && strlen
!= NULL_TREE
)
2488 strlen
= fold_build3_loc (UNKNOWN_LOCATION
,
2491 expr
, strlen
, NULL_TREE
);
2492 se
->string_length
= strlen
;
2495 transfer_expr (se
, &c
->ts
, tmp
, code
, NULL_TREE
);
2497 /* Reset so that the pdt string length does not propagate
2498 through to other strings. */
2499 if (c
->attr
.pdt_string
&& strlen
)
2500 se
->string_length
= NULL_TREE
;
2505 /* If a CLASS object gets through to here, fall through and ICE. */
2509 gfc_internal_error ("Bad IO basetype (%d)", ts
->type
);
2512 tmp
= gfc_build_addr_expr (NULL_TREE
, dt_parm
);
2513 tmp
= build_call_expr_loc (input_location
,
2514 function
, 3, tmp
, addr_expr
, arg2
);
2515 gfc_add_expr_to_block (&se
->pre
, tmp
);
2516 gfc_add_block_to_block (&se
->pre
, &se
->post
);
2521 /* Generate a call to pass an array descriptor to the IO library. The
2522 array should be of one of the intrinsic types. */
2525 transfer_array_desc (gfc_se
* se
, gfc_typespec
* ts
, tree addr_expr
)
2527 tree tmp
, charlen_arg
, kind_arg
, io_call
;
2529 if (ts
->type
== BT_CHARACTER
)
2530 charlen_arg
= se
->string_length
;
2532 charlen_arg
= build_int_cst (gfc_charlen_type_node
, 0);
2534 kind_arg
= build_int_cst (integer_type_node
, ts
->kind
);
2536 tmp
= gfc_build_addr_expr (NULL_TREE
, dt_parm
);
2537 if (last_dt
== READ
)
2538 io_call
= iocall
[IOCALL_X_ARRAY
];
2540 io_call
= iocall
[IOCALL_X_ARRAY_WRITE
];
2542 tmp
= build_call_expr_loc (UNKNOWN_LOCATION
,
2544 tmp
, addr_expr
, kind_arg
, charlen_arg
);
2545 gfc_add_expr_to_block (&se
->pre
, tmp
);
2546 gfc_add_block_to_block (&se
->pre
, &se
->post
);
2550 /* gfc_trans_transfer()-- Translate a TRANSFER code node */
2553 gfc_trans_transfer (gfc_code
* code
)
2555 stmtblock_t block
, body
;
2565 gfc_start_block (&block
);
2566 gfc_init_block (&body
);
2570 gfc_init_se (&se
, NULL
);
2572 if (expr
->rank
== 0)
2574 /* Transfer a scalar value. */
2575 if (expr
->ts
.type
== BT_CLASS
)
2577 se
.want_pointer
= 1;
2578 gfc_conv_expr (&se
, expr
);
2579 vptr
= gfc_get_vptr_from_expr (se
.expr
);
2584 gfc_conv_expr_reference (&se
, expr
);
2586 transfer_expr (&se
, &expr
->ts
, se
.expr
, code
, vptr
);
2590 /* Transfer an array. If it is an array of an intrinsic
2591 type, pass the descriptor to the library. Otherwise
2592 scalarize the transfer. */
2593 if (expr
->ref
&& !gfc_is_proc_ptr_comp (expr
))
2595 for (ref
= expr
->ref
; ref
&& ref
->type
!= REF_ARRAY
;
2597 gcc_assert (ref
&& ref
->type
== REF_ARRAY
);
2600 if (expr
->ts
.type
!= BT_CLASS
2601 && expr
->expr_type
== EXPR_VARIABLE
2602 && gfc_expr_attr (expr
).pointer
)
2606 if (!(gfc_bt_struct (expr
->ts
.type
)
2607 || expr
->ts
.type
== BT_CLASS
)
2608 && ref
&& ref
->next
== NULL
2609 && !is_subref_array (expr
))
2611 bool seen_vector
= false;
2613 if (ref
&& ref
->u
.ar
.type
== AR_SECTION
)
2615 for (n
= 0; n
< ref
->u
.ar
.dimen
; n
++)
2616 if (ref
->u
.ar
.dimen_type
[n
] == DIMEN_VECTOR
)
2623 if (seen_vector
&& last_dt
== READ
)
2625 /* Create a temp, read to that and copy it back. */
2626 gfc_conv_subref_array_arg (&se
, expr
, 0, INTENT_OUT
, false);
2631 /* Get the descriptor. */
2632 gfc_conv_expr_descriptor (&se
, expr
);
2633 tmp
= gfc_build_addr_expr (NULL_TREE
, se
.expr
);
2636 transfer_array_desc (&se
, &expr
->ts
, tmp
);
2637 goto finish_block_label
;
2641 /* Initialize the scalarizer. */
2642 ss
= gfc_walk_expr (expr
);
2643 gfc_init_loopinfo (&loop
);
2644 gfc_add_ss_to_loop (&loop
, ss
);
2646 /* Initialize the loop. */
2647 gfc_conv_ss_startstride (&loop
);
2648 gfc_conv_loop_setup (&loop
, &code
->expr1
->where
);
2650 /* The main loop body. */
2651 gfc_mark_ss_chain_used (ss
, 1);
2652 gfc_start_scalarized_body (&loop
, &body
);
2654 gfc_copy_loopinfo_to_se (&se
, &loop
);
2657 gfc_conv_expr_reference (&se
, expr
);
2659 if (expr
->ts
.type
== BT_CLASS
)
2660 vptr
= gfc_get_vptr_from_expr (ss
->info
->data
.array
.descriptor
);
2663 transfer_expr (&se
, &expr
->ts
, se
.expr
, code
, vptr
);
2668 gfc_add_block_to_block (&body
, &se
.pre
);
2669 gfc_add_block_to_block (&body
, &se
.post
);
2672 tmp
= gfc_finish_block (&body
);
2675 gcc_assert (expr
->rank
!= 0);
2676 gcc_assert (se
.ss
== gfc_ss_terminator
);
2677 gfc_trans_scalarizing_loops (&loop
, &body
);
2679 gfc_add_block_to_block (&loop
.pre
, &loop
.post
);
2680 tmp
= gfc_finish_block (&loop
.pre
);
2681 gfc_cleanup_loop (&loop
);
2684 gfc_add_expr_to_block (&block
, tmp
);
2686 return gfc_finish_block (&block
);
2689 #include "gt-fortran-trans-io.h"