1 /* IO Code translation/library interface
2 Copyright (C) 2002-2024 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_UNSIGNED_WRITE
,
123 IOCALL_X_LOGICAL_WRITE
,
125 IOCALL_X_CHARACTER_WRITE
,
126 IOCALL_X_CHARACTER_WIDE
,
127 IOCALL_X_CHARACTER_WIDE_WRITE
,
131 IOCALL_X_COMPLEX_WRITE
,
133 IOCALL_X_REAL128_WRITE
,
135 IOCALL_X_COMPLEX128_WRITE
,
137 IOCALL_X_ARRAY_WRITE
,
143 IOCALL_IOLENGTH_DONE
,
149 IOCALL_SET_NML_DTIO_VAL
,
150 IOCALL_SET_NML_VAL_DIM
,
155 static GTY(()) tree iocall
[IOCALL_NUM
];
157 /* Variable for keeping track of what the last data transfer statement
158 was. Used for deciding which subroutine to call when the data
159 transfer is complete. */
160 static enum { READ
, WRITE
, IOLENGTH
} last_dt
;
162 /* The data transfer parameter block that should be shared by all
163 data transfer calls belonging to the same read/write/iolength. */
164 static GTY(()) tree dt_parm
;
165 static stmtblock_t
*dt_post_end_block
;
168 gfc_build_st_parameter (enum ioparam_type ptype
, tree
*types
)
171 gfc_st_parameter_field
*p
;
174 tree t
= make_node (RECORD_TYPE
);
177 len
= strlen (st_parameter
[ptype
].name
);
178 gcc_assert (len
<= sizeof (name
) - sizeof ("__st_parameter_"));
179 memcpy (name
, "__st_parameter_", sizeof ("__st_parameter_"));
180 memcpy (name
+ sizeof ("__st_parameter_") - 1, st_parameter
[ptype
].name
,
182 TYPE_NAME (t
) = get_identifier (name
);
184 for (type
= 0, p
= st_parameter_field
; type
< IOPARM_field_num
; type
++, p
++)
185 if (p
->param_type
== ptype
)
188 case IOPARM_type_int4
:
189 case IOPARM_type_intio
:
190 case IOPARM_type_pint4
:
191 case IOPARM_type_pintio
:
192 case IOPARM_type_parray
:
193 case IOPARM_type_pchar
:
194 case IOPARM_type_pad
:
195 p
->field
= gfc_add_field_to_struct (t
, get_identifier (p
->name
),
196 types
[p
->type
], &chain
);
198 case IOPARM_type_char1
:
199 p
->field
= gfc_add_field_to_struct (t
, get_identifier (p
->name
),
200 pchar_type_node
, &chain
);
202 case IOPARM_type_char2
:
203 len
= strlen (p
->name
);
204 gcc_assert (len
<= sizeof (name
) - sizeof ("_len"));
205 memcpy (name
, p
->name
, len
);
206 memcpy (name
+ len
, "_len", sizeof ("_len"));
207 p
->field_len
= gfc_add_field_to_struct (t
, get_identifier (name
),
208 gfc_charlen_type_node
,
210 if (p
->type
== IOPARM_type_char2
)
211 p
->field
= gfc_add_field_to_struct (t
, get_identifier (p
->name
),
212 pchar_type_node
, &chain
);
214 case IOPARM_type_common
:
216 = gfc_add_field_to_struct (t
,
217 get_identifier (p
->name
),
218 st_parameter
[IOPARM_ptype_common
].type
,
221 case IOPARM_type_num
:
225 /* -Wpadded warnings on these artificially created structures are not
226 helpful; suppress them. */
227 int save_warn_padded
= warn_padded
;
230 warn_padded
= save_warn_padded
;
231 st_parameter
[ptype
].type
= t
;
235 /* Build code to test an error condition and call generate_error if needed.
236 Note: This builds calls to generate_error in the runtime library function.
237 The function generate_error is dependent on certain parameters in the
238 st_parameter_common flags to be set. (See libgfortran/runtime/error.cc)
239 Therefore, the code to set these flags must be generated before
240 this function is used. */
243 gfc_trans_io_runtime_check (bool has_iostat
, tree cond
, tree var
,
244 int error_code
, const char * msgid
,
245 stmtblock_t
* pblock
)
250 tree arg1
, arg2
, arg3
;
253 if (integer_zerop (cond
))
256 /* The code to generate the error. */
257 gfc_start_block (&block
);
260 gfc_add_expr_to_block (&block
, build_predict_expr (PRED_FORTRAN_FAIL_IO
,
263 gfc_add_expr_to_block (&block
, build_predict_expr (PRED_NORETURN
,
266 arg1
= gfc_build_addr_expr (NULL_TREE
, var
);
268 arg2
= build_int_cst (integer_type_node
, error_code
),
270 message
= xasprintf ("%s", _(msgid
));
271 arg3
= gfc_build_addr_expr (pchar_type_node
,
272 gfc_build_localized_cstring_const (message
));
275 tmp
= build_call_expr_loc (input_location
,
276 gfor_fndecl_generate_error
, 3, arg1
, arg2
, arg3
);
278 gfc_add_expr_to_block (&block
, tmp
);
280 body
= gfc_finish_block (&block
);
282 if (integer_onep (cond
))
284 gfc_add_expr_to_block (pblock
, body
);
288 tmp
= build3_v (COND_EXPR
, cond
, body
, build_empty_stmt (input_location
));
289 gfc_add_expr_to_block (pblock
, tmp
);
294 /* Create function decls for IO library functions. */
297 gfc_build_io_library_fndecls (void)
299 tree types
[IOPARM_type_num
], pad_idx
, gfc_int4_type_node
;
300 tree gfc_intio_type_node
;
301 tree parm_type
, dt_parm_type
;
302 HOST_WIDE_INT pad_size
;
305 types
[IOPARM_type_int4
] = gfc_int4_type_node
= gfc_get_int_type (4);
306 types
[IOPARM_type_intio
] = gfc_intio_type_node
307 = gfc_get_int_type (gfc_intio_kind
);
308 types
[IOPARM_type_pint4
] = build_pointer_type (gfc_int4_type_node
);
309 types
[IOPARM_type_pintio
]
310 = build_pointer_type (gfc_intio_type_node
);
311 types
[IOPARM_type_parray
] = pchar_type_node
;
312 types
[IOPARM_type_pchar
] = pchar_type_node
;
313 pad_size
= 16 * TREE_INT_CST_LOW (TYPE_SIZE_UNIT (pchar_type_node
));
314 pad_size
+= 32 * TREE_INT_CST_LOW (TYPE_SIZE_UNIT (integer_type_node
));
315 pad_idx
= build_index_type (size_int (pad_size
- 1));
316 types
[IOPARM_type_pad
] = build_array_type (char_type_node
, pad_idx
);
318 /* pad actually contains pointers and integers so it needs to have an
319 alignment that is at least as large as the needed alignment for those
320 types. See the st_parameter_dt structure in libgfortran/io/io.h for
321 what really goes into this space. */
322 SET_TYPE_ALIGN (types
[IOPARM_type_pad
], MAX (TYPE_ALIGN (pchar_type_node
),
323 TYPE_ALIGN (gfc_get_int_type (gfc_intio_kind
))));
325 for (ptype
= IOPARM_ptype_common
; ptype
< IOPARM_ptype_num
; ptype
++)
326 gfc_build_st_parameter ((enum ioparam_type
) ptype
, types
);
328 /* Define the transfer functions. */
330 dt_parm_type
= build_pointer_type (st_parameter
[IOPARM_ptype_dt
].type
);
332 iocall
[IOCALL_X_INTEGER
] = gfc_build_library_function_decl_with_spec (
333 get_identifier (PREFIX("transfer_integer")), ". w W . ",
334 void_type_node
, 3, dt_parm_type
, pvoid_type_node
, gfc_int4_type_node
);
336 iocall
[IOCALL_X_INTEGER_WRITE
] = gfc_build_library_function_decl_with_spec (
337 get_identifier (PREFIX("transfer_integer_write")), ". w R . ",
338 void_type_node
, 3, dt_parm_type
, pvoid_type_node
, gfc_int4_type_node
);
340 iocall
[IOCALL_X_UNSIGNED
] = gfc_build_library_function_decl_with_spec (
341 get_identifier (PREFIX("transfer_unsigned")), ". w W . ",
342 void_type_node
, 3, dt_parm_type
, pvoid_type_node
, gfc_int4_type_node
);
344 iocall
[IOCALL_X_UNSIGNED_WRITE
] = gfc_build_library_function_decl_with_spec (
345 get_identifier (PREFIX("transfer_unsigned_write")), ". w R . ",
346 void_type_node
, 3, dt_parm_type
, pvoid_type_node
, gfc_int4_type_node
);
348 iocall
[IOCALL_X_LOGICAL
] = gfc_build_library_function_decl_with_spec (
349 get_identifier (PREFIX("transfer_logical")), ". w W . ",
350 void_type_node
, 3, dt_parm_type
, pvoid_type_node
, gfc_int4_type_node
);
352 iocall
[IOCALL_X_LOGICAL_WRITE
] = gfc_build_library_function_decl_with_spec (
353 get_identifier (PREFIX("transfer_logical_write")), ". w R . ",
354 void_type_node
, 3, dt_parm_type
, pvoid_type_node
, gfc_int4_type_node
);
356 iocall
[IOCALL_X_CHARACTER
] = gfc_build_library_function_decl_with_spec (
357 get_identifier (PREFIX("transfer_character")), ". w W . ",
358 void_type_node
, 3, dt_parm_type
, pvoid_type_node
, gfc_charlen_type_node
);
360 iocall
[IOCALL_X_CHARACTER_WRITE
] = gfc_build_library_function_decl_with_spec (
361 get_identifier (PREFIX("transfer_character_write")), ". w R . ",
362 void_type_node
, 3, dt_parm_type
, pvoid_type_node
, gfc_charlen_type_node
);
364 iocall
[IOCALL_X_CHARACTER_WIDE
] = gfc_build_library_function_decl_with_spec (
365 get_identifier (PREFIX("transfer_character_wide")), ". w W . . ",
366 void_type_node
, 4, dt_parm_type
, pvoid_type_node
,
367 gfc_charlen_type_node
, gfc_int4_type_node
);
369 iocall
[IOCALL_X_CHARACTER_WIDE_WRITE
] =
370 gfc_build_library_function_decl_with_spec (
371 get_identifier (PREFIX("transfer_character_wide_write")), ". w R . . ",
372 void_type_node
, 4, dt_parm_type
, pvoid_type_node
,
373 gfc_charlen_type_node
, gfc_int4_type_node
);
375 iocall
[IOCALL_X_REAL
] = gfc_build_library_function_decl_with_spec (
376 get_identifier (PREFIX("transfer_real")), ". w W . ",
377 void_type_node
, 3, dt_parm_type
, pvoid_type_node
, gfc_int4_type_node
);
379 iocall
[IOCALL_X_REAL_WRITE
] = gfc_build_library_function_decl_with_spec (
380 get_identifier (PREFIX("transfer_real_write")), ". w R . ",
381 void_type_node
, 3, dt_parm_type
, pvoid_type_node
, gfc_int4_type_node
);
383 iocall
[IOCALL_X_COMPLEX
] = gfc_build_library_function_decl_with_spec (
384 get_identifier (PREFIX("transfer_complex")), ". w W . ",
385 void_type_node
, 3, dt_parm_type
, pvoid_type_node
, gfc_int4_type_node
);
387 iocall
[IOCALL_X_COMPLEX_WRITE
] = gfc_build_library_function_decl_with_spec (
388 get_identifier (PREFIX("transfer_complex_write")), ". w R . ",
389 void_type_node
, 3, dt_parm_type
, pvoid_type_node
, gfc_int4_type_node
);
391 /* Version for __float128. */
392 iocall
[IOCALL_X_REAL128
] = gfc_build_library_function_decl_with_spec (
393 get_identifier (PREFIX("transfer_real128")), ". w W . ",
394 void_type_node
, 3, dt_parm_type
, pvoid_type_node
, gfc_int4_type_node
);
396 iocall
[IOCALL_X_REAL128_WRITE
] = gfc_build_library_function_decl_with_spec (
397 get_identifier (PREFIX("transfer_real128_write")), ". w R . ",
398 void_type_node
, 3, dt_parm_type
, pvoid_type_node
, gfc_int4_type_node
);
400 iocall
[IOCALL_X_COMPLEX128
] = gfc_build_library_function_decl_with_spec (
401 get_identifier (PREFIX("transfer_complex128")), ". w W . ",
402 void_type_node
, 3, dt_parm_type
, pvoid_type_node
, gfc_int4_type_node
);
404 iocall
[IOCALL_X_COMPLEX128_WRITE
] = gfc_build_library_function_decl_with_spec (
405 get_identifier (PREFIX("transfer_complex128_write")), ". w R . ",
406 void_type_node
, 3, dt_parm_type
, pvoid_type_node
, gfc_int4_type_node
);
408 iocall
[IOCALL_X_ARRAY
] = gfc_build_library_function_decl_with_spec (
409 get_identifier (PREFIX("transfer_array")), ". w w . . ",
410 void_type_node
, 4, dt_parm_type
, pvoid_type_node
,
411 integer_type_node
, gfc_charlen_type_node
);
413 iocall
[IOCALL_X_ARRAY_WRITE
] = gfc_build_library_function_decl_with_spec (
414 get_identifier (PREFIX("transfer_array_write")), ". w r . . ",
415 void_type_node
, 4, dt_parm_type
, pvoid_type_node
,
416 integer_type_node
, gfc_charlen_type_node
);
418 iocall
[IOCALL_X_DERIVED
] = gfc_build_library_function_decl_with_spec (
419 get_identifier (PREFIX("transfer_derived")), ". w r ",
420 void_type_node
, 2, dt_parm_type
, pvoid_type_node
);
422 /* Library entry points */
424 iocall
[IOCALL_READ
] = gfc_build_library_function_decl_with_spec (
425 get_identifier (PREFIX("st_read")), ". w ",
426 void_type_node
, 1, dt_parm_type
);
428 iocall
[IOCALL_WRITE
] = gfc_build_library_function_decl_with_spec (
429 get_identifier (PREFIX("st_write")), ". w ",
430 void_type_node
, 1, dt_parm_type
);
432 parm_type
= build_pointer_type (st_parameter
[IOPARM_ptype_open
].type
);
433 iocall
[IOCALL_OPEN
] = gfc_build_library_function_decl_with_spec (
434 get_identifier (PREFIX("st_open")), ". w ",
435 void_type_node
, 1, parm_type
);
437 parm_type
= build_pointer_type (st_parameter
[IOPARM_ptype_close
].type
);
438 iocall
[IOCALL_CLOSE
] = gfc_build_library_function_decl_with_spec (
439 get_identifier (PREFIX("st_close")), ". w ",
440 void_type_node
, 1, parm_type
);
442 parm_type
= build_pointer_type (st_parameter
[IOPARM_ptype_inquire
].type
);
443 iocall
[IOCALL_INQUIRE
] = gfc_build_library_function_decl_with_spec (
444 get_identifier (PREFIX("st_inquire")), ". w ",
445 void_type_node
, 1, parm_type
);
447 iocall
[IOCALL_IOLENGTH
] = gfc_build_library_function_decl_with_spec(
448 get_identifier (PREFIX("st_iolength")), ". w ",
449 void_type_node
, 1, dt_parm_type
);
451 parm_type
= build_pointer_type (st_parameter
[IOPARM_ptype_wait
].type
);
452 iocall
[IOCALL_WAIT
] = gfc_build_library_function_decl_with_spec (
453 get_identifier (PREFIX("st_wait_async")), ". w ",
454 void_type_node
, 1, parm_type
);
456 parm_type
= build_pointer_type (st_parameter
[IOPARM_ptype_filepos
].type
);
457 iocall
[IOCALL_REWIND
] = gfc_build_library_function_decl_with_spec (
458 get_identifier (PREFIX("st_rewind")), ". w ",
459 void_type_node
, 1, parm_type
);
461 iocall
[IOCALL_BACKSPACE
] = gfc_build_library_function_decl_with_spec (
462 get_identifier (PREFIX("st_backspace")), ". w ",
463 void_type_node
, 1, parm_type
);
465 iocall
[IOCALL_ENDFILE
] = gfc_build_library_function_decl_with_spec (
466 get_identifier (PREFIX("st_endfile")), ". w ",
467 void_type_node
, 1, parm_type
);
469 iocall
[IOCALL_FLUSH
] = gfc_build_library_function_decl_with_spec (
470 get_identifier (PREFIX("st_flush")), ". w ",
471 void_type_node
, 1, parm_type
);
473 /* Library helpers */
475 iocall
[IOCALL_READ_DONE
] = gfc_build_library_function_decl_with_spec (
476 get_identifier (PREFIX("st_read_done")), ". w ",
477 void_type_node
, 1, dt_parm_type
);
479 iocall
[IOCALL_WRITE_DONE
] = gfc_build_library_function_decl_with_spec (
480 get_identifier (PREFIX("st_write_done")), ". w ",
481 void_type_node
, 1, dt_parm_type
);
483 iocall
[IOCALL_IOLENGTH_DONE
] = gfc_build_library_function_decl_with_spec (
484 get_identifier (PREFIX("st_iolength_done")), ". w ",
485 void_type_node
, 1, dt_parm_type
);
487 iocall
[IOCALL_SET_NML_VAL
] = gfc_build_library_function_decl_with_spec (
488 get_identifier (PREFIX("st_set_nml_var")), ". w . R . . . ",
489 void_type_node
, 6, dt_parm_type
, pvoid_type_node
, pvoid_type_node
,
490 gfc_int4_type_node
, gfc_charlen_type_node
, get_dtype_type_node());
492 iocall
[IOCALL_SET_NML_DTIO_VAL
] = gfc_build_library_function_decl_with_spec (
493 get_identifier (PREFIX("st_set_nml_dtio_var")), ". w . R . . . . . ",
494 void_type_node
, 8, dt_parm_type
, pvoid_type_node
, pvoid_type_node
,
495 gfc_int4_type_node
, gfc_charlen_type_node
, get_dtype_type_node(),
496 pvoid_type_node
, pvoid_type_node
);
498 iocall
[IOCALL_SET_NML_VAL_DIM
] = gfc_build_library_function_decl_with_spec (
499 get_identifier (PREFIX("st_set_nml_var_dim")), ". w . . . . ",
500 void_type_node
, 5, dt_parm_type
, gfc_int4_type_node
,
501 gfc_array_index_type
, gfc_array_index_type
, gfc_array_index_type
);
506 set_parameter_tree (stmtblock_t
*block
, tree var
, enum iofield type
, tree value
)
509 gfc_st_parameter_field
*p
= &st_parameter_field
[type
];
511 if (p
->param_type
== IOPARM_ptype_common
)
512 var
= fold_build3_loc (input_location
, COMPONENT_REF
,
513 st_parameter
[IOPARM_ptype_common
].type
,
514 var
, TYPE_FIELDS (TREE_TYPE (var
)), NULL_TREE
);
515 tmp
= fold_build3_loc (input_location
, COMPONENT_REF
, TREE_TYPE (p
->field
),
516 var
, p
->field
, NULL_TREE
);
517 gfc_add_modify (block
, tmp
, value
);
521 /* Generate code to store an integer constant into the
522 st_parameter_XXX structure. */
525 set_parameter_const (stmtblock_t
*block
, tree var
, enum iofield type
,
528 gfc_st_parameter_field
*p
= &st_parameter_field
[type
];
530 set_parameter_tree (block
, var
, type
,
531 build_int_cst (TREE_TYPE (p
->field
), val
));
536 /* Generate code to store a non-string I/O parameter into the
537 st_parameter_XXX structure. This is a pass by value. */
540 set_parameter_value (stmtblock_t
*block
, tree var
, enum iofield type
,
545 gfc_st_parameter_field
*p
= &st_parameter_field
[type
];
546 tree dest_type
= TREE_TYPE (p
->field
);
548 gfc_init_se (&se
, NULL
);
549 gfc_conv_expr_val (&se
, e
);
551 se
.expr
= convert (dest_type
, se
.expr
);
552 gfc_add_block_to_block (block
, &se
.pre
);
554 if (p
->param_type
== IOPARM_ptype_common
)
555 var
= fold_build3_loc (input_location
, COMPONENT_REF
,
556 st_parameter
[IOPARM_ptype_common
].type
,
557 var
, TYPE_FIELDS (TREE_TYPE (var
)), NULL_TREE
);
559 tmp
= fold_build3_loc (input_location
, COMPONENT_REF
, dest_type
, var
,
560 p
->field
, NULL_TREE
);
561 gfc_add_modify (block
, tmp
, se
.expr
);
566 /* Similar to set_parameter_value except generate runtime
570 set_parameter_value_chk (stmtblock_t
*block
, bool has_iostat
, tree var
,
571 enum iofield type
, gfc_expr
*e
)
575 gfc_st_parameter_field
*p
= &st_parameter_field
[type
];
576 tree dest_type
= TREE_TYPE (p
->field
);
578 gfc_init_se (&se
, NULL
);
579 gfc_conv_expr_val (&se
, e
);
581 /* If we're storing a UNIT number, we need to check it first. */
582 if (type
== IOPARM_common_unit
&& e
->ts
.kind
> 4)
587 /* Don't evaluate the UNIT number multiple times. */
588 se
.expr
= gfc_evaluate_now (se
.expr
, &se
.pre
);
590 /* UNIT numbers should be greater than the min. */
591 i
= gfc_validate_kind (BT_INTEGER
, 4, false);
592 val
= gfc_conv_mpz_to_tree (gfc_integer_kinds
[i
].pedantic_min_int
, 4);
593 cond
= fold_build2_loc (input_location
, LT_EXPR
, logical_type_node
,
595 fold_convert (TREE_TYPE (se
.expr
), val
));
596 gfc_trans_io_runtime_check (has_iostat
, cond
, var
, LIBERROR_BAD_UNIT
,
597 "Unit number in I/O statement too small",
600 /* UNIT numbers should be less than the max. */
601 val
= gfc_conv_mpz_to_tree (gfc_integer_kinds
[i
].huge
, 4);
602 cond
= fold_build2_loc (input_location
, GT_EXPR
, logical_type_node
,
604 fold_convert (TREE_TYPE (se
.expr
), val
));
605 gfc_trans_io_runtime_check (has_iostat
, cond
, var
, LIBERROR_BAD_UNIT
,
606 "Unit number in I/O statement too large",
610 se
.expr
= convert (dest_type
, se
.expr
);
611 gfc_add_block_to_block (block
, &se
.pre
);
613 if (p
->param_type
== IOPARM_ptype_common
)
614 var
= fold_build3_loc (input_location
, COMPONENT_REF
,
615 st_parameter
[IOPARM_ptype_common
].type
,
616 var
, TYPE_FIELDS (TREE_TYPE (var
)), NULL_TREE
);
618 tmp
= fold_build3_loc (input_location
, COMPONENT_REF
, dest_type
, var
,
619 p
->field
, NULL_TREE
);
620 gfc_add_modify (block
, tmp
, se
.expr
);
625 /* Build code to check the unit range if KIND=8 is used. Similar to
626 set_parameter_value_chk but we do not generate error calls for
627 inquire statements. */
630 set_parameter_value_inquire (stmtblock_t
*block
, tree var
,
631 enum iofield type
, gfc_expr
*e
)
634 gfc_st_parameter_field
*p
= &st_parameter_field
[type
];
635 tree dest_type
= TREE_TYPE (p
->field
);
637 gfc_init_se (&se
, NULL
);
638 gfc_conv_expr_val (&se
, e
);
640 /* If we're inquiring on a UNIT number, we need to check to make
641 sure it exists for larger than kind = 4. */
642 if (type
== IOPARM_common_unit
&& e
->ts
.kind
> 4)
644 stmtblock_t newblock
;
645 tree cond1
, cond2
, cond3
, val
, body
;
648 /* Don't evaluate the UNIT number multiple times. */
649 se
.expr
= gfc_evaluate_now (se
.expr
, &se
.pre
);
651 /* UNIT numbers should be greater than the min. */
652 i
= gfc_validate_kind (BT_INTEGER
, 4, false);
653 val
= gfc_conv_mpz_to_tree (gfc_integer_kinds
[i
].pedantic_min_int
, 4);
654 cond1
= build2_loc (input_location
, LT_EXPR
, logical_type_node
,
656 fold_convert (TREE_TYPE (se
.expr
), val
));
657 /* UNIT numbers should be less than the max. */
658 val
= gfc_conv_mpz_to_tree (gfc_integer_kinds
[i
].huge
, 4);
659 cond2
= build2_loc (input_location
, GT_EXPR
, logical_type_node
,
661 fold_convert (TREE_TYPE (se
.expr
), val
));
662 cond3
= build2_loc (input_location
, TRUTH_OR_EXPR
,
663 logical_type_node
, cond1
, cond2
);
665 gfc_start_block (&newblock
);
667 /* The unit number GFC_INVALID_UNIT is reserved. No units can
668 ever have this value. It is used here to signal to the
669 runtime library that the inquire unit number is outside the
670 allowable range and so cannot exist. It is needed when
671 -fdefault-integer-8 is used. */
672 set_parameter_const (&newblock
, var
, IOPARM_common_unit
,
675 body
= gfc_finish_block (&newblock
);
677 cond3
= gfc_unlikely (cond3
, PRED_FORTRAN_FAIL_IO
);
678 var
= build3_v (COND_EXPR
, cond3
, body
, build_empty_stmt (input_location
));
679 gfc_add_expr_to_block (&se
.pre
, var
);
682 se
.expr
= convert (dest_type
, se
.expr
);
683 gfc_add_block_to_block (block
, &se
.pre
);
689 /* Generate code to store a non-string I/O parameter into the
690 st_parameter_XXX structure. This is pass by reference. */
693 set_parameter_ref (stmtblock_t
*block
, stmtblock_t
*postblock
,
694 tree var
, enum iofield type
, gfc_expr
*e
)
698 gfc_st_parameter_field
*p
= &st_parameter_field
[type
];
700 gcc_assert (e
->ts
.type
== BT_INTEGER
|| e
->ts
.type
== BT_LOGICAL
);
701 gfc_init_se (&se
, NULL
);
702 gfc_conv_expr_lhs (&se
, e
);
704 gfc_add_block_to_block (block
, &se
.pre
);
706 if (TYPE_MODE (TREE_TYPE (se
.expr
))
707 == TYPE_MODE (TREE_TYPE (TREE_TYPE (p
->field
))))
709 addr
= convert (TREE_TYPE (p
->field
), gfc_build_addr_expr (NULL_TREE
, se
.expr
));
711 /* If this is for the iostat variable initialize the
712 user variable to LIBERROR_OK which is zero. */
713 if (type
== IOPARM_common_iostat
)
714 gfc_add_modify (block
, se
.expr
,
715 build_int_cst (TREE_TYPE (se
.expr
), LIBERROR_OK
));
719 /* The type used by the library has different size
720 from the type of the variable supplied by the user.
721 Need to use a temporary. */
722 tree tmpvar
= gfc_create_var (TREE_TYPE (TREE_TYPE (p
->field
)),
723 st_parameter_field
[type
].name
);
725 /* If this is for the iostat variable, initialize the
726 user variable to LIBERROR_OK which is zero. */
727 if (type
== IOPARM_common_iostat
)
728 gfc_add_modify (block
, tmpvar
,
729 build_int_cst (TREE_TYPE (tmpvar
), LIBERROR_OK
));
731 addr
= gfc_build_addr_expr (NULL_TREE
, tmpvar
);
732 /* After the I/O operation, we set the variable from the temporary. */
733 tmp
= convert (TREE_TYPE (se
.expr
), tmpvar
);
734 gfc_add_modify (postblock
, se
.expr
, tmp
);
737 set_parameter_tree (block
, var
, type
, addr
);
741 /* Given an array expr, find its address and length to get a string. If the
742 array is full, the string's address is the address of array's first element
743 and the length is the size of the whole array. If it is an element, the
744 string's address is the element's address and the length is the rest size of
748 gfc_convert_array_to_string (gfc_se
* se
, gfc_expr
* e
)
753 tree type
, array
, tmp
;
757 /* If it is an element, we need its address and size of the rest. */
758 gcc_assert (e
->expr_type
== EXPR_VARIABLE
);
759 gcc_assert (e
->ref
->u
.ar
.type
== AR_ELEMENT
);
760 sym
= e
->symtree
->n
.sym
;
761 rank
= sym
->as
->rank
- 1;
762 gfc_conv_expr (se
, e
);
764 array
= sym
->backend_decl
;
765 type
= TREE_TYPE (array
);
768 if (GFC_ARRAY_TYPE_P (type
))
769 elts_count
= GFC_TYPE_ARRAY_SIZE (type
);
772 gcc_assert (GFC_DESCRIPTOR_TYPE_P (type
));
773 tree stride
= gfc_conv_array_stride (array
, rank
);
774 tmp
= fold_build2_loc (input_location
, MINUS_EXPR
,
775 gfc_array_index_type
,
776 gfc_conv_array_ubound (array
, rank
),
777 gfc_conv_array_lbound (array
, rank
));
778 tmp
= fold_build2_loc (input_location
, PLUS_EXPR
,
779 gfc_array_index_type
, tmp
,
781 elts_count
= fold_build2_loc (input_location
, MULT_EXPR
,
782 gfc_array_index_type
, tmp
, stride
);
784 gcc_assert (elts_count
);
786 tree elt_size
= TYPE_SIZE_UNIT (gfc_get_element_type (type
));
787 elt_size
= fold_convert (gfc_array_index_type
, elt_size
);
790 if (TREE_CODE (se
->expr
) == ARRAY_REF
)
792 tree index
= TREE_OPERAND (se
->expr
, 1);
793 index
= fold_convert (gfc_array_index_type
, index
);
795 elts_count
= fold_build2_loc (input_location
, MINUS_EXPR
,
796 gfc_array_index_type
,
799 size
= fold_build2_loc (input_location
, MULT_EXPR
,
800 gfc_array_index_type
, elts_count
, elt_size
);
804 gcc_assert (INDIRECT_REF_P (se
->expr
));
805 tree ptr
= TREE_OPERAND (se
->expr
, 0);
807 gcc_assert (TREE_CODE (ptr
) == POINTER_PLUS_EXPR
);
808 tree offset
= fold_convert_loc (input_location
, gfc_array_index_type
,
809 TREE_OPERAND (ptr
, 1));
811 size
= fold_build2_loc (input_location
, MULT_EXPR
,
812 gfc_array_index_type
, elts_count
, elt_size
);
813 size
= fold_build2_loc (input_location
, MINUS_EXPR
,
814 gfc_array_index_type
, size
, offset
);
818 se
->expr
= gfc_build_addr_expr (NULL_TREE
, se
->expr
);
819 se
->string_length
= fold_convert (gfc_charlen_type_node
, size
);
824 gfc_conv_array_parameter (se
, e
, true, NULL
, NULL
, &size
);
825 se
->string_length
= fold_convert (gfc_charlen_type_node
, size
);
829 /* Generate code to store a string and its length into the
830 st_parameter_XXX structure. */
833 set_string (stmtblock_t
* block
, stmtblock_t
* postblock
, tree var
,
834 enum iofield type
, gfc_expr
* e
)
840 gfc_st_parameter_field
*p
= &st_parameter_field
[type
];
842 gfc_init_se (&se
, NULL
);
844 if (p
->param_type
== IOPARM_ptype_common
)
845 var
= fold_build3_loc (input_location
, COMPONENT_REF
,
846 st_parameter
[IOPARM_ptype_common
].type
,
847 var
, TYPE_FIELDS (TREE_TYPE (var
)), NULL_TREE
);
848 io
= fold_build3_loc (input_location
, COMPONENT_REF
, TREE_TYPE (p
->field
),
849 var
, p
->field
, NULL_TREE
);
850 len
= fold_build3_loc (input_location
, COMPONENT_REF
,
851 TREE_TYPE (p
->field_len
),
852 var
, p
->field_len
, NULL_TREE
);
854 /* Integer variable assigned a format label. */
855 if (e
->ts
.type
== BT_INTEGER
857 && e
->symtree
->n
.sym
->attr
.assign
== 1)
862 gfc_conv_label_variable (&se
, e
);
863 tmp
= GFC_DECL_STRING_LEN (se
.expr
);
864 cond
= fold_build2_loc (input_location
, LT_EXPR
, logical_type_node
,
865 tmp
, build_int_cst (TREE_TYPE (tmp
), 0));
867 msg
= xasprintf ("Label assigned to variable '%s' (%%ld) is not a format "
868 "label", e
->symtree
->name
);
869 gfc_trans_runtime_check (true, false, cond
, &se
.pre
, &e
->where
, msg
,
870 fold_convert (long_integer_type_node
, tmp
));
873 gfc_add_modify (&se
.pre
, io
,
874 fold_convert (TREE_TYPE (io
), GFC_DECL_ASSIGN_ADDR (se
.expr
)));
875 gfc_add_modify (&se
.pre
, len
, GFC_DECL_STRING_LEN (se
.expr
));
879 /* General character. */
880 if (e
->ts
.type
== BT_CHARACTER
&& e
->rank
== 0)
881 gfc_conv_expr (&se
, e
);
882 /* Array assigned Hollerith constant or character array. */
883 else if (e
->rank
> 0 || (e
->symtree
&& e
->symtree
->n
.sym
->as
->rank
> 0))
884 gfc_convert_array_to_string (&se
, e
);
888 gfc_conv_string_parameter (&se
);
889 gfc_add_modify (&se
.pre
, io
, fold_convert (TREE_TYPE (io
), se
.expr
));
890 gfc_add_modify (&se
.pre
, len
, fold_convert (TREE_TYPE (len
),
894 gfc_add_block_to_block (block
, &se
.pre
);
895 gfc_add_block_to_block (postblock
, &se
.post
);
900 /* Generate code to store the character (array) and the character length
901 for an internal unit. */
904 set_internal_unit (stmtblock_t
* block
, stmtblock_t
* post_block
,
905 tree var
, gfc_expr
* e
)
912 gfc_st_parameter_field
*p
;
915 gfc_init_se (&se
, NULL
);
917 p
= &st_parameter_field
[IOPARM_dt_internal_unit
];
919 io
= fold_build3_loc (input_location
, COMPONENT_REF
, TREE_TYPE (p
->field
),
920 var
, p
->field
, NULL_TREE
);
921 len
= fold_build3_loc (input_location
, COMPONENT_REF
, TREE_TYPE (p
->field_len
),
922 var
, p
->field_len
, NULL_TREE
);
923 p
= &st_parameter_field
[IOPARM_dt_internal_unit_desc
];
924 desc
= fold_build3_loc (input_location
, COMPONENT_REF
, TREE_TYPE (p
->field
),
925 var
, p
->field
, NULL_TREE
);
927 gcc_assert (e
->ts
.type
== BT_CHARACTER
);
929 /* Character scalars. */
932 gfc_conv_expr (&se
, e
);
933 gfc_conv_string_parameter (&se
);
935 se
.expr
= build_int_cst (pchar_type_node
, 0);
938 /* Character array. */
939 else if (e
->rank
> 0)
941 if (is_subref_array (e
))
943 /* Use a temporary for components of arrays of derived types
944 or substring array references. */
945 gfc_conv_subref_array_arg (&se
, e
, 0,
946 last_dt
== READ
? INTENT_IN
: INTENT_OUT
, false);
947 tmp
= build_fold_indirect_ref_loc (input_location
,
949 se
.expr
= gfc_build_addr_expr (pchar_type_node
, tmp
);
950 tmp
= gfc_conv_descriptor_data_get (tmp
);
954 /* Return the data pointer and rank from the descriptor. */
955 gfc_conv_expr_descriptor (&se
, e
);
956 tmp
= gfc_conv_descriptor_data_get (se
.expr
);
957 se
.expr
= gfc_build_addr_expr (pchar_type_node
, se
.expr
);
963 /* The cast is needed for character substrings and the descriptor
965 gfc_add_modify (&se
.pre
, io
, fold_convert (TREE_TYPE (io
), tmp
));
966 gfc_add_modify (&se
.pre
, len
,
967 fold_convert (TREE_TYPE (len
), se
.string_length
));
968 gfc_add_modify (&se
.pre
, desc
, se
.expr
);
970 gfc_add_block_to_block (block
, &se
.pre
);
971 gfc_add_block_to_block (post_block
, &se
.post
);
975 /* Add a case to a IO-result switch. */
978 add_case (int label_value
, gfc_st_label
* label
, stmtblock_t
* body
)
983 return; /* No label, no case */
985 value
= build_int_cst (integer_type_node
, label_value
);
987 /* Make a backend label for this case. */
988 tmp
= gfc_build_label_decl (NULL_TREE
);
990 /* And the case itself. */
991 tmp
= build_case_label (value
, NULL_TREE
, tmp
);
992 gfc_add_expr_to_block (body
, tmp
);
994 /* Jump to the label. */
995 tmp
= build1_v (GOTO_EXPR
, gfc_get_label_decl (label
));
996 gfc_add_expr_to_block (body
, tmp
);
1000 /* Generate a switch statement that branches to the correct I/O
1001 result label. The last statement of an I/O call stores the
1002 result into a variable because there is often cleanup that
1003 must be done before the switch, so a temporary would have to
1004 be created anyway. */
1007 io_result (stmtblock_t
* block
, tree var
, gfc_st_label
* err_label
,
1008 gfc_st_label
* end_label
, gfc_st_label
* eor_label
)
1012 gfc_st_parameter_field
*p
= &st_parameter_field
[IOPARM_common_flags
];
1014 /* If no labels are specified, ignore the result instead
1015 of building an empty switch. */
1016 if (err_label
== NULL
1017 && end_label
== NULL
1018 && eor_label
== NULL
)
1021 /* Build a switch statement. */
1022 gfc_start_block (&body
);
1024 /* The label values here must be the same as the values
1025 in the library_return enum in the runtime library */
1026 add_case (1, err_label
, &body
);
1027 add_case (2, end_label
, &body
);
1028 add_case (3, eor_label
, &body
);
1030 tmp
= gfc_finish_block (&body
);
1032 var
= fold_build3_loc (input_location
, COMPONENT_REF
,
1033 st_parameter
[IOPARM_ptype_common
].type
,
1034 var
, TYPE_FIELDS (TREE_TYPE (var
)), NULL_TREE
);
1035 rc
= fold_build3_loc (input_location
, COMPONENT_REF
, TREE_TYPE (p
->field
),
1036 var
, p
->field
, NULL_TREE
);
1037 rc
= fold_build2_loc (input_location
, BIT_AND_EXPR
, TREE_TYPE (rc
),
1038 rc
, build_int_cst (TREE_TYPE (rc
),
1039 IOPARM_common_libreturn_mask
));
1041 tmp
= fold_build2_loc (input_location
, SWITCH_EXPR
, NULL_TREE
, rc
, tmp
);
1043 gfc_add_expr_to_block (block
, tmp
);
1047 /* Store the current file and line number to variables so that if a
1048 library call goes awry, we can tell the user where the problem is. */
1051 set_error_locus (stmtblock_t
* block
, tree var
, locus
* where
)
1054 tree str
, locus_file
;
1056 gfc_st_parameter_field
*p
= &st_parameter_field
[IOPARM_common_filename
];
1058 locus_file
= fold_build3_loc (input_location
, COMPONENT_REF
,
1059 st_parameter
[IOPARM_ptype_common
].type
,
1060 var
, TYPE_FIELDS (TREE_TYPE (var
)), NULL_TREE
);
1061 locus_file
= fold_build3_loc (input_location
, COMPONENT_REF
,
1062 TREE_TYPE (p
->field
), locus_file
,
1063 p
->field
, NULL_TREE
);
1064 f
= where
->lb
->file
;
1065 str
= gfc_build_cstring_const (f
->filename
);
1067 str
= gfc_build_addr_expr (pchar_type_node
, str
);
1068 gfc_add_modify (block
, locus_file
, str
);
1070 line
= LOCATION_LINE (where
->lb
->location
);
1071 set_parameter_const (block
, var
, IOPARM_common_line
, line
);
1075 /* Translate an OPEN statement. */
1078 gfc_trans_open (gfc_code
* code
)
1080 stmtblock_t block
, post_block
;
1083 unsigned int mask
= 0;
1085 gfc_start_block (&block
);
1086 gfc_init_block (&post_block
);
1088 var
= gfc_create_var (st_parameter
[IOPARM_ptype_open
].type
, "open_parm");
1090 set_error_locus (&block
, var
, &code
->loc
);
1094 mask
|= set_string (&block
, &post_block
, var
, IOPARM_common_iomsg
,
1098 mask
|= set_parameter_ref (&block
, &post_block
, var
, IOPARM_common_iostat
,
1102 mask
|= IOPARM_common_err
;
1105 mask
|= set_string (&block
, &post_block
, var
, IOPARM_open_file
, p
->file
);
1108 mask
|= set_string (&block
, &post_block
, var
, IOPARM_open_status
,
1112 mask
|= set_string (&block
, &post_block
, var
, IOPARM_open_access
,
1116 mask
|= set_string (&block
, &post_block
, var
, IOPARM_open_form
, p
->form
);
1119 mask
|= set_parameter_value (&block
, var
, IOPARM_open_recl_in
,
1123 mask
|= set_string (&block
, &post_block
, var
, IOPARM_open_blank
,
1127 mask
|= set_string (&block
, &post_block
, var
, IOPARM_open_position
,
1131 mask
|= set_string (&block
, &post_block
, var
, IOPARM_open_action
,
1135 mask
|= set_string (&block
, &post_block
, var
, IOPARM_open_delim
,
1139 mask
|= set_string (&block
, &post_block
, var
, IOPARM_open_pad
, p
->pad
);
1142 mask
|= set_string (&block
, &post_block
, var
, IOPARM_open_decimal
,
1146 mask
|= set_string (&block
, &post_block
, var
, IOPARM_open_encoding
,
1150 mask
|= set_string (&block
, &post_block
, var
, IOPARM_open_round
, p
->round
);
1153 mask
|= set_string (&block
, &post_block
, var
, IOPARM_open_sign
, p
->sign
);
1155 if (p
->asynchronous
)
1156 mask
|= set_string (&block
, &post_block
, var
, IOPARM_open_asynchronous
,
1160 mask
|= set_string (&block
, &post_block
, var
, IOPARM_open_convert
,
1164 mask
|= set_parameter_ref (&block
, &post_block
, var
, IOPARM_open_newunit
,
1168 mask
|= set_string (&block
, &post_block
, var
, IOPARM_open_cc
, p
->cc
);
1171 mask
|= set_string (&block
, &post_block
, var
, IOPARM_open_share
, p
->share
);
1173 mask
|= set_parameter_const (&block
, var
, IOPARM_open_readonly
, p
->readonly
);
1175 set_parameter_const (&block
, var
, IOPARM_common_flags
, mask
);
1178 set_parameter_value_chk (&block
, p
->iostat
, var
, IOPARM_common_unit
, p
->unit
);
1180 set_parameter_const (&block
, var
, IOPARM_common_unit
, 0);
1182 tmp
= gfc_build_addr_expr (NULL_TREE
, var
);
1183 tmp
= build_call_expr_loc (input_location
,
1184 iocall
[IOCALL_OPEN
], 1, tmp
);
1185 gfc_add_expr_to_block (&block
, tmp
);
1187 gfc_add_block_to_block (&block
, &post_block
);
1189 io_result (&block
, var
, p
->err
, NULL
, NULL
);
1191 return gfc_finish_block (&block
);
1195 /* Translate a CLOSE statement. */
1198 gfc_trans_close (gfc_code
* code
)
1200 stmtblock_t block
, post_block
;
1203 unsigned int mask
= 0;
1205 gfc_start_block (&block
);
1206 gfc_init_block (&post_block
);
1208 var
= gfc_create_var (st_parameter
[IOPARM_ptype_close
].type
, "close_parm");
1210 set_error_locus (&block
, var
, &code
->loc
);
1211 p
= code
->ext
.close
;
1214 mask
|= set_string (&block
, &post_block
, var
, IOPARM_common_iomsg
,
1218 mask
|= set_parameter_ref (&block
, &post_block
, var
, IOPARM_common_iostat
,
1222 mask
|= IOPARM_common_err
;
1225 mask
|= set_string (&block
, &post_block
, var
, IOPARM_close_status
,
1228 set_parameter_const (&block
, var
, IOPARM_common_flags
, mask
);
1231 set_parameter_value_chk (&block
, p
->iostat
, var
, IOPARM_common_unit
, p
->unit
);
1233 set_parameter_const (&block
, var
, IOPARM_common_unit
, 0);
1235 tmp
= gfc_build_addr_expr (NULL_TREE
, var
);
1236 tmp
= build_call_expr_loc (input_location
,
1237 iocall
[IOCALL_CLOSE
], 1, tmp
);
1238 gfc_add_expr_to_block (&block
, tmp
);
1240 gfc_add_block_to_block (&block
, &post_block
);
1242 io_result (&block
, var
, p
->err
, NULL
, NULL
);
1244 return gfc_finish_block (&block
);
1248 /* Common subroutine for building a file positioning statement. */
1251 build_filepos (tree function
, gfc_code
* code
)
1253 stmtblock_t block
, post_block
;
1256 unsigned int mask
= 0;
1258 p
= code
->ext
.filepos
;
1260 gfc_start_block (&block
);
1261 gfc_init_block (&post_block
);
1263 var
= gfc_create_var (st_parameter
[IOPARM_ptype_filepos
].type
,
1266 set_error_locus (&block
, var
, &code
->loc
);
1269 mask
|= set_string (&block
, &post_block
, var
, IOPARM_common_iomsg
,
1273 mask
|= set_parameter_ref (&block
, &post_block
, var
,
1274 IOPARM_common_iostat
, p
->iostat
);
1277 mask
|= IOPARM_common_err
;
1279 set_parameter_const (&block
, var
, IOPARM_common_flags
, mask
);
1282 set_parameter_value_chk (&block
, p
->iostat
, var
, IOPARM_common_unit
,
1285 set_parameter_const (&block
, var
, IOPARM_common_unit
, 0);
1287 tmp
= gfc_build_addr_expr (NULL_TREE
, var
);
1288 tmp
= build_call_expr_loc (input_location
,
1290 gfc_add_expr_to_block (&block
, tmp
);
1292 gfc_add_block_to_block (&block
, &post_block
);
1294 io_result (&block
, var
, p
->err
, NULL
, NULL
);
1296 return gfc_finish_block (&block
);
1300 /* Translate a BACKSPACE statement. */
1303 gfc_trans_backspace (gfc_code
* code
)
1305 return build_filepos (iocall
[IOCALL_BACKSPACE
], code
);
1309 /* Translate an ENDFILE statement. */
1312 gfc_trans_endfile (gfc_code
* code
)
1314 return build_filepos (iocall
[IOCALL_ENDFILE
], code
);
1318 /* Translate a REWIND statement. */
1321 gfc_trans_rewind (gfc_code
* code
)
1323 return build_filepos (iocall
[IOCALL_REWIND
], code
);
1327 /* Translate a FLUSH statement. */
1330 gfc_trans_flush (gfc_code
* code
)
1332 return build_filepos (iocall
[IOCALL_FLUSH
], code
);
1336 /* Translate the non-IOLENGTH form of an INQUIRE statement. */
1339 gfc_trans_inquire (gfc_code
* code
)
1341 stmtblock_t block
, post_block
;
1344 unsigned int mask
= 0, mask2
= 0;
1346 gfc_start_block (&block
);
1347 gfc_init_block (&post_block
);
1349 var
= gfc_create_var (st_parameter
[IOPARM_ptype_inquire
].type
,
1352 set_error_locus (&block
, var
, &code
->loc
);
1353 p
= code
->ext
.inquire
;
1356 mask
|= set_string (&block
, &post_block
, var
, IOPARM_common_iomsg
,
1360 mask
|= set_parameter_ref (&block
, &post_block
, var
, IOPARM_common_iostat
,
1364 mask
|= IOPARM_common_err
;
1367 if (p
->unit
&& p
->file
)
1368 gfc_error ("INQUIRE statement at %L cannot contain both FILE and UNIT specifiers", &code
->loc
);
1371 mask
|= set_string (&block
, &post_block
, var
, IOPARM_inquire_file
,
1375 mask
|= set_parameter_ref (&block
, &post_block
, var
, IOPARM_inquire_exist
,
1379 mask
|= set_parameter_ref (&block
, &post_block
, var
, IOPARM_inquire_opened
,
1383 mask
|= set_parameter_ref (&block
, &post_block
, var
, IOPARM_inquire_number
,
1387 mask
|= set_parameter_ref (&block
, &post_block
, var
, IOPARM_inquire_named
,
1391 mask
|= set_string (&block
, &post_block
, var
, IOPARM_inquire_name
,
1395 mask
|= set_string (&block
, &post_block
, var
, IOPARM_inquire_access
,
1399 mask
|= set_string (&block
, &post_block
, var
, IOPARM_inquire_sequential
,
1403 mask
|= set_string (&block
, &post_block
, var
, IOPARM_inquire_direct
,
1407 mask
|= set_string (&block
, &post_block
, var
, IOPARM_inquire_form
,
1411 mask
|= set_string (&block
, &post_block
, var
, IOPARM_inquire_formatted
,
1415 mask
|= set_string (&block
, &post_block
, var
, IOPARM_inquire_unformatted
,
1419 mask
|= set_parameter_ref (&block
, &post_block
, var
,
1420 IOPARM_inquire_recl_out
, p
->recl
);
1423 mask
|= set_parameter_ref (&block
, &post_block
, var
,
1424 IOPARM_inquire_nextrec
, p
->nextrec
);
1427 mask
|= set_string (&block
, &post_block
, var
, IOPARM_inquire_blank
,
1431 mask
|= set_string (&block
, &post_block
, var
, IOPARM_inquire_delim
,
1435 mask
|= set_string (&block
, &post_block
, var
, IOPARM_inquire_position
,
1439 mask
|= set_string (&block
, &post_block
, var
, IOPARM_inquire_action
,
1443 mask
|= set_string (&block
, &post_block
, var
, IOPARM_inquire_read
,
1447 mask
|= set_string (&block
, &post_block
, var
, IOPARM_inquire_write
,
1451 mask
|= set_string (&block
, &post_block
, var
, IOPARM_inquire_readwrite
,
1455 mask
|= set_string (&block
, &post_block
, var
, IOPARM_inquire_pad
,
1459 mask
|= set_string (&block
, &post_block
, var
, IOPARM_inquire_convert
,
1463 mask
|= set_parameter_ref (&block
, &post_block
, var
,
1464 IOPARM_inquire_strm_pos_out
, p
->strm_pos
);
1466 /* The second series of flags. */
1467 if (p
->asynchronous
)
1468 mask2
|= set_string (&block
, &post_block
, var
, IOPARM_inquire_asynchronous
,
1472 mask2
|= set_string (&block
, &post_block
, var
, IOPARM_inquire_decimal
,
1476 mask2
|= set_string (&block
, &post_block
, var
, IOPARM_inquire_encoding
,
1480 mask2
|= set_string (&block
, &post_block
, var
, IOPARM_inquire_round
,
1484 mask2
|= set_string (&block
, &post_block
, var
, IOPARM_inquire_sign
,
1488 mask2
|= set_parameter_ref (&block
, &post_block
, var
,
1489 IOPARM_inquire_pending
, p
->pending
);
1492 mask2
|= set_parameter_ref (&block
, &post_block
, var
, IOPARM_inquire_size
,
1496 mask2
|= set_parameter_ref (&block
, &post_block
,var
, IOPARM_inquire_id
,
1499 mask2
|= set_string (&block
, &post_block
, var
, IOPARM_inquire_iqstream
,
1503 mask2
|= set_string (&block
, &post_block
, var
, IOPARM_inquire_share
,
1507 mask2
|= set_string (&block
, &post_block
, var
, IOPARM_inquire_cc
, p
->cc
);
1510 mask
|= set_parameter_const (&block
, var
, IOPARM_inquire_flags2
, mask2
);
1512 set_parameter_const (&block
, var
, IOPARM_common_flags
, mask
);
1516 set_parameter_value (&block
, var
, IOPARM_common_unit
, p
->unit
);
1517 set_parameter_value_inquire (&block
, var
, IOPARM_common_unit
, p
->unit
);
1520 set_parameter_const (&block
, var
, IOPARM_common_unit
, 0);
1522 tmp
= gfc_build_addr_expr (NULL_TREE
, var
);
1523 tmp
= build_call_expr_loc (input_location
,
1524 iocall
[IOCALL_INQUIRE
], 1, tmp
);
1525 gfc_add_expr_to_block (&block
, tmp
);
1527 gfc_add_block_to_block (&block
, &post_block
);
1529 io_result (&block
, var
, p
->err
, NULL
, NULL
);
1531 return gfc_finish_block (&block
);
1536 gfc_trans_wait (gfc_code
* code
)
1538 stmtblock_t block
, post_block
;
1541 unsigned int mask
= 0;
1543 gfc_start_block (&block
);
1544 gfc_init_block (&post_block
);
1546 var
= gfc_create_var (st_parameter
[IOPARM_ptype_wait
].type
,
1549 set_error_locus (&block
, var
, &code
->loc
);
1552 /* Set parameters here. */
1554 mask
|= set_string (&block
, &post_block
, var
, IOPARM_common_iomsg
,
1558 mask
|= set_parameter_ref (&block
, &post_block
, var
, IOPARM_common_iostat
,
1562 mask
|= IOPARM_common_err
;
1565 mask
|= set_parameter_ref (&block
, &post_block
, var
, IOPARM_wait_id
, p
->id
);
1567 set_parameter_const (&block
, var
, IOPARM_common_flags
, mask
);
1570 set_parameter_value_chk (&block
, p
->iostat
, var
, IOPARM_common_unit
, p
->unit
);
1572 tmp
= gfc_build_addr_expr (NULL_TREE
, var
);
1573 tmp
= build_call_expr_loc (input_location
,
1574 iocall
[IOCALL_WAIT
], 1, tmp
);
1575 gfc_add_expr_to_block (&block
, tmp
);
1577 gfc_add_block_to_block (&block
, &post_block
);
1579 io_result (&block
, var
, p
->err
, NULL
, NULL
);
1581 return gfc_finish_block (&block
);
1586 /* nml_full_name builds up the fully qualified name of a
1587 derived type component. '+' is used to denote a type extension. */
1590 nml_full_name (const char* var_name
, const char* cmp_name
, bool parent
)
1592 int full_name_length
;
1595 full_name_length
= strlen (var_name
) + strlen (cmp_name
) + 1;
1596 full_name
= XCNEWVEC (char, full_name_length
+ 1);
1597 strcpy (full_name
, var_name
);
1598 full_name
= strcat (full_name
, parent
? "+" : "%");
1599 full_name
= strcat (full_name
, cmp_name
);
1604 /* nml_get_addr_expr builds an address expression from the
1605 gfc_symbol or gfc_component backend_decl's. An offset is
1606 provided so that the address of an element of an array of
1607 derived types is returned. This is used in the runtime to
1608 determine that span of the derived type. */
1611 nml_get_addr_expr (gfc_symbol
* sym
, gfc_component
* c
,
1614 tree decl
= NULL_TREE
;
1619 sym
->attr
.referenced
= 1;
1620 decl
= gfc_get_symbol_decl (sym
);
1622 /* If this is the enclosing function declaration, use
1623 the fake result instead. */
1624 if (decl
== current_function_decl
)
1625 decl
= gfc_get_fake_result_decl (sym
, 0);
1626 else if (decl
== DECL_CONTEXT (current_function_decl
))
1627 decl
= gfc_get_fake_result_decl (sym
, 1);
1630 decl
= c
->backend_decl
;
1632 gcc_assert (decl
&& (TREE_CODE (decl
) == FIELD_DECL
1634 || TREE_CODE (decl
) == PARM_DECL
1635 || TREE_CODE (decl
) == COMPONENT_REF
));
1639 /* Build indirect reference, if dummy argument. */
1641 if (POINTER_TYPE_P (TREE_TYPE(tmp
)))
1642 tmp
= build_fold_indirect_ref_loc (input_location
, tmp
);
1644 /* Treat the component of a derived type, using base_addr for
1645 the derived type. */
1647 if (TREE_CODE (decl
) == FIELD_DECL
)
1648 tmp
= fold_build3_loc (input_location
, COMPONENT_REF
, TREE_TYPE (tmp
),
1649 base_addr
, tmp
, NULL_TREE
);
1651 if (GFC_CLASS_TYPE_P (TREE_TYPE (tmp
))
1652 && GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (gfc_class_data_get (tmp
))))
1653 tmp
= gfc_class_data_get (tmp
);
1655 if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (tmp
)))
1656 tmp
= gfc_conv_array_data (tmp
);
1659 if (!POINTER_TYPE_P (TREE_TYPE (tmp
)))
1660 tmp
= gfc_build_addr_expr (NULL_TREE
, tmp
);
1662 if (TREE_CODE (TREE_TYPE (tmp
)) == ARRAY_TYPE
)
1663 tmp
= gfc_build_array_ref (tmp
, gfc_index_zero_node
, NULL
);
1665 if (!POINTER_TYPE_P (TREE_TYPE (tmp
)))
1666 tmp
= build_fold_indirect_ref_loc (input_location
,
1670 gcc_assert (tmp
&& POINTER_TYPE_P (TREE_TYPE (tmp
)));
1676 /* For an object VAR_NAME whose base address is BASE_ADDR, generate a
1677 call to iocall[IOCALL_SET_NML_VAL]. For derived type variable, recursively
1678 generate calls to iocall[IOCALL_SET_NML_VAL] for each component. */
1680 #define IARG(i) build_int_cst (gfc_array_index_type, i)
1683 transfer_namelist_element (stmtblock_t
* block
, const char * var_name
,
1684 gfc_symbol
* sym
, gfc_component
* c
,
1687 gfc_typespec
* ts
= NULL
;
1688 gfc_array_spec
* as
= NULL
;
1689 tree addr_expr
= NULL
;
1695 tree decl
= NULL_TREE
;
1696 tree gfc_int4_type_node
= gfc_get_int_type (4);
1697 tree dtio_proc
= null_pointer_node
;
1698 tree vtable
= null_pointer_node
;
1702 gcc_assert (sym
|| c
);
1704 /* Build the namelist object name. */
1705 if (sym
&& !sym
->attr
.use_only
&& sym
->attr
.use_rename
1706 && sym
->ns
->use_stmts
->rename
)
1707 string
= gfc_build_cstring_const (sym
->ns
->use_stmts
->rename
->local_name
);
1709 string
= gfc_build_cstring_const (var_name
);
1710 string
= gfc_build_addr_expr (pchar_type_node
, string
);
1712 /* Build ts, as and data address using symbol or component. */
1714 ts
= sym
? &sym
->ts
: &c
->ts
;
1716 if (ts
->type
!= BT_CLASS
)
1717 as
= sym
? sym
->as
: c
->as
;
1719 as
= sym
? CLASS_DATA (sym
)->as
: CLASS_DATA (c
)->as
;
1721 addr_expr
= nml_get_addr_expr (sym
, c
, base_addr
);
1728 decl
= sym
? sym
->backend_decl
: c
->backend_decl
;
1729 if (sym
&& sym
->attr
.dummy
)
1730 decl
= build_fold_indirect_ref_loc (input_location
, decl
);
1732 if (ts
->type
== BT_CLASS
)
1733 decl
= gfc_class_data_get (decl
);
1734 dt
= TREE_TYPE (decl
);
1735 dtype
= gfc_get_dtype (dt
);
1739 dt
= gfc_typenode_for_spec (ts
);
1740 dtype
= gfc_get_dtype_rank_type (0, dt
);
1743 /* Build up the arguments for the transfer call.
1744 The call for the scalar part transfers:
1745 (address, name, type, kind or string_length, dtype) */
1747 dt_parm_addr
= gfc_build_addr_expr (NULL_TREE
, dt_parm
);
1749 /* Check if the derived type has a specific DTIO for the mode.
1750 Note that although namelist io is forbidden to have a format
1751 list, the specific subroutine is of the formatted kind. */
1752 if (ts
->type
== BT_DERIVED
|| ts
->type
== BT_CLASS
)
1754 gfc_symbol
*derived
;
1755 if (ts
->type
==BT_CLASS
)
1756 derived
= ts
->u
.derived
->components
->ts
.u
.derived
;
1758 derived
= ts
->u
.derived
;
1760 gfc_symtree
*tb_io_st
= gfc_find_typebound_dtio_proc (derived
,
1761 last_dt
== WRITE
, true);
1763 if (ts
->type
== BT_CLASS
&& tb_io_st
)
1765 // polymorphic DTIO call (based on the dynamic type)
1767 gfc_symtree
*st
= gfc_find_symtree (sym
->ns
->sym_root
, sym
->name
);
1768 // build vtable expr
1769 gfc_expr
*expr
= gfc_get_variable_expr (st
);
1770 gfc_add_vptr_component (expr
);
1771 gfc_init_se (&se
, NULL
);
1772 se
.want_pointer
= 1;
1773 gfc_conv_expr (&se
, expr
);
1776 gfc_add_component_ref (expr
,
1777 tb_io_st
->n
.tb
->u
.generic
->specific_st
->name
);
1778 gfc_init_se (&se
, NULL
);
1779 se
.want_pointer
= 1;
1780 gfc_conv_expr (&se
, expr
);
1781 gfc_free_expr (expr
);
1782 dtio_proc
= se
.expr
;
1786 // non-polymorphic DTIO call (based on the declared type)
1787 gfc_symbol
*dtio_sub
= gfc_find_specific_dtio_proc (derived
,
1788 last_dt
== WRITE
, true);
1789 if (dtio_sub
!= NULL
)
1791 dtio_proc
= gfc_get_symbol_decl (dtio_sub
);
1792 dtio_proc
= gfc_build_addr_expr (NULL
, dtio_proc
);
1793 gfc_symbol
*vtab
= gfc_find_derived_vtab (derived
);
1794 vtable
= vtab
->backend_decl
;
1795 if (vtable
== NULL_TREE
)
1796 vtable
= gfc_get_symbol_decl (vtab
);
1797 vtable
= gfc_build_addr_expr (pvoid_type_node
, vtable
);
1802 if (ts
->type
== BT_CHARACTER
)
1803 tmp
= ts
->u
.cl
->backend_decl
;
1805 tmp
= build_int_cst (gfc_charlen_type_node
, 0);
1807 int abi_kind
= gfc_type_abi_kind (ts
);
1808 if (dtio_proc
== null_pointer_node
)
1809 tmp
= build_call_expr_loc (input_location
, iocall
[IOCALL_SET_NML_VAL
], 6,
1810 dt_parm_addr
, addr_expr
, string
,
1811 build_int_cst (gfc_int4_type_node
, abi_kind
),
1814 tmp
= build_call_expr_loc (input_location
, iocall
[IOCALL_SET_NML_DTIO_VAL
],
1815 8, dt_parm_addr
, addr_expr
, string
,
1816 build_int_cst (gfc_int4_type_node
, abi_kind
),
1817 tmp
, dtype
, dtio_proc
, vtable
);
1818 gfc_add_expr_to_block (block
, tmp
);
1820 /* If the object is an array, transfer rank times:
1821 (null pointer, name, stride, lbound, ubound) */
1823 for ( n_dim
= 0 ; n_dim
< rank
; n_dim
++ )
1825 tmp
= build_call_expr_loc (input_location
,
1826 iocall
[IOCALL_SET_NML_VAL_DIM
], 5,
1828 build_int_cst (gfc_int4_type_node
, n_dim
),
1829 gfc_conv_array_stride (decl
, n_dim
),
1830 gfc_conv_array_lbound (decl
, n_dim
),
1831 gfc_conv_array_ubound (decl
, n_dim
));
1832 gfc_add_expr_to_block (block
, tmp
);
1835 if (gfc_bt_struct (ts
->type
) && ts
->u
.derived
->components
1836 && dtio_proc
== null_pointer_node
)
1840 /* Provide the RECORD_TYPE to build component references. */
1842 tree expr
= build_fold_indirect_ref_loc (input_location
,
1845 for (cmp
= ts
->u
.derived
->components
; cmp
; cmp
= cmp
->next
)
1847 char *full_name
= nml_full_name (var_name
, cmp
->name
,
1848 ts
->u
.derived
->attr
.extension
);
1849 transfer_namelist_element (block
,
1859 /* Create a data transfer statement. Not all of the fields are valid
1860 for both reading and writing, but improper use has been filtered
1864 build_dt (tree function
, gfc_code
* code
)
1866 stmtblock_t block
, post_block
, post_end_block
, post_iu_block
;
1871 unsigned int mask
= 0;
1873 gfc_start_block (&block
);
1874 gfc_init_block (&post_block
);
1875 gfc_init_block (&post_end_block
);
1876 gfc_init_block (&post_iu_block
);
1878 var
= gfc_create_var (st_parameter
[IOPARM_ptype_dt
].type
, "dt_parm");
1880 set_error_locus (&block
, var
, &code
->loc
);
1882 if (last_dt
== IOLENGTH
)
1886 inq
= code
->ext
.inquire
;
1888 /* First check that preconditions are met. */
1889 gcc_assert (inq
!= NULL
);
1890 gcc_assert (inq
->iolength
!= NULL
);
1892 /* Connect to the iolength variable. */
1893 mask
|= set_parameter_ref (&block
, &post_end_block
, var
,
1894 IOPARM_dt_iolength
, inq
->iolength
);
1900 gcc_assert (dt
!= NULL
);
1903 if (dt
&& dt
->io_unit
)
1905 if (dt
->io_unit
->ts
.type
== BT_CHARACTER
)
1907 mask
|= set_internal_unit (&block
, &post_iu_block
,
1909 set_parameter_const (&block
, var
, IOPARM_common_unit
,
1910 dt
->io_unit
->ts
.kind
== 1 ?
1911 GFC_INTERNAL_UNIT
: GFC_INTERNAL_UNIT4
);
1915 set_parameter_const (&block
, var
, IOPARM_common_unit
, 0);
1920 mask
|= set_string (&block
, &post_block
, var
, IOPARM_common_iomsg
,
1924 mask
|= set_parameter_ref (&block
, &post_end_block
, var
,
1925 IOPARM_common_iostat
, dt
->iostat
);
1928 mask
|= IOPARM_common_err
;
1931 mask
|= IOPARM_common_eor
;
1934 mask
|= IOPARM_common_end
;
1937 mask
|= set_parameter_ref (&block
, &post_end_block
, var
,
1938 IOPARM_dt_id
, dt
->id
);
1941 mask
|= set_parameter_value (&block
, var
, IOPARM_dt_pos
, dt
->pos
);
1943 if (dt
->asynchronous
)
1944 mask
|= set_string (&block
, &post_block
, var
,
1945 IOPARM_dt_asynchronous
, dt
->asynchronous
);
1948 mask
|= set_string (&block
, &post_block
, var
, IOPARM_dt_blank
,
1952 mask
|= set_string (&block
, &post_block
, var
, IOPARM_dt_decimal
,
1956 mask
|= set_string (&block
, &post_block
, var
, IOPARM_dt_delim
,
1960 mask
|= set_string (&block
, &post_block
, var
, IOPARM_dt_pad
,
1964 mask
|= set_string (&block
, &post_block
, var
, IOPARM_dt_round
,
1968 mask
|= set_string (&block
, &post_block
, var
, IOPARM_dt_sign
,
1972 mask
|= set_parameter_value (&block
, var
, IOPARM_dt_rec
, dt
->rec
);
1975 mask
|= set_string (&block
, &post_block
, var
, IOPARM_dt_advance
,
1978 if (dt
->format_expr
)
1979 mask
|= set_string (&block
, &post_end_block
, var
, IOPARM_dt_format
,
1982 if (dt
->format_label
)
1984 if (dt
->format_label
== &format_asterisk
)
1985 mask
|= IOPARM_dt_list_format
;
1987 mask
|= set_string (&block
, &post_block
, var
, IOPARM_dt_format
,
1988 dt
->format_label
->format
);
1992 mask
|= set_parameter_ref (&block
, &post_end_block
, var
,
1993 IOPARM_dt_size
, dt
->size
);
1996 mask
|= IOPARM_dt_dtio
;
1999 mask
|= IOPARM_dt_dec_ext
;
2003 if (dt
->format_expr
|| dt
->format_label
)
2004 gfc_internal_error ("build_dt: format with namelist");
2006 nmlname
= gfc_get_character_expr (gfc_default_character_kind
, NULL
,
2008 strlen (dt
->namelist
->name
));
2010 mask
|= set_string (&block
, &post_block
, var
, IOPARM_dt_namelist_name
,
2013 gfc_free_expr (nmlname
);
2015 if (last_dt
== READ
)
2016 mask
|= IOPARM_dt_namelist_read_mode
;
2018 set_parameter_const (&block
, var
, IOPARM_common_flags
, mask
);
2022 for (nml
= dt
->namelist
->namelist
; nml
; nml
= nml
->next
)
2023 transfer_namelist_element (&block
, nml
->sym
->name
, nml
->sym
,
2027 set_parameter_const (&block
, var
, IOPARM_common_flags
, mask
);
2029 if (dt
->io_unit
&& dt
->io_unit
->ts
.type
== BT_INTEGER
)
2030 set_parameter_value_chk (&block
, dt
->iostat
, var
,
2031 IOPARM_common_unit
, dt
->io_unit
);
2034 set_parameter_const (&block
, var
, IOPARM_common_flags
, mask
);
2036 tmp
= gfc_build_addr_expr (NULL_TREE
, var
);
2037 tmp
= build_call_expr_loc (UNKNOWN_LOCATION
,
2039 gfc_add_expr_to_block (&block
, tmp
);
2041 gfc_add_block_to_block (&block
, &post_block
);
2044 dt_post_end_block
= &post_end_block
;
2046 /* Set implied do loop exit condition. */
2047 if (last_dt
== READ
|| last_dt
== WRITE
)
2049 gfc_st_parameter_field
*p
= &st_parameter_field
[IOPARM_common_flags
];
2051 tmp
= fold_build3_loc (input_location
, COMPONENT_REF
,
2052 st_parameter
[IOPARM_ptype_common
].type
,
2053 dt_parm
, TYPE_FIELDS (TREE_TYPE (dt_parm
)),
2055 tmp
= fold_build3_loc (input_location
, COMPONENT_REF
,
2056 TREE_TYPE (p
->field
), tmp
, p
->field
, NULL_TREE
);
2057 tmp
= fold_build2_loc (input_location
, BIT_AND_EXPR
, TREE_TYPE (tmp
),
2058 tmp
, build_int_cst (TREE_TYPE (tmp
),
2059 IOPARM_common_libreturn_mask
));
2064 gfc_add_expr_to_block (&block
, gfc_trans_code_cond (code
->block
->next
, tmp
));
2066 gfc_add_block_to_block (&block
, &post_iu_block
);
2069 dt_post_end_block
= NULL
;
2071 return gfc_finish_block (&block
);
2075 /* Translate the IOLENGTH form of an INQUIRE statement. We treat
2076 this as a third sort of data transfer statement, except that
2077 lengths are summed instead of actually transferring any data. */
2080 gfc_trans_iolength (gfc_code
* code
)
2083 return build_dt (iocall
[IOCALL_IOLENGTH
], code
);
2087 /* Translate a READ statement. */
2090 gfc_trans_read (gfc_code
* code
)
2093 return build_dt (iocall
[IOCALL_READ
], code
);
2097 /* Translate a WRITE statement */
2100 gfc_trans_write (gfc_code
* code
)
2103 return build_dt (iocall
[IOCALL_WRITE
], code
);
2107 /* Finish a data transfer statement. */
2110 gfc_trans_dt_end (gfc_code
* code
)
2115 gfc_init_block (&block
);
2120 function
= iocall
[IOCALL_READ_DONE
];
2124 function
= iocall
[IOCALL_WRITE_DONE
];
2128 function
= iocall
[IOCALL_IOLENGTH_DONE
];
2135 tmp
= gfc_build_addr_expr (NULL_TREE
, dt_parm
);
2136 tmp
= build_call_expr_loc (input_location
,
2138 gfc_add_expr_to_block (&block
, tmp
);
2139 gfc_add_block_to_block (&block
, dt_post_end_block
);
2140 gfc_init_block (dt_post_end_block
);
2142 if (last_dt
!= IOLENGTH
)
2144 gcc_assert (code
->ext
.dt
!= NULL
);
2145 io_result (&block
, dt_parm
, code
->ext
.dt
->err
,
2146 code
->ext
.dt
->end
, code
->ext
.dt
->eor
);
2149 return gfc_finish_block (&block
);
2153 transfer_expr (gfc_se
* se
, gfc_typespec
* ts
, tree addr_expr
,
2154 gfc_code
* code
, tree vptr
);
2156 /* Given an array field in a derived type variable, generate the code
2157 for the loop that iterates over array elements, and the code that
2158 accesses those array elements. Use transfer_expr to generate code
2159 for transferring that element. Because elements may also be
2160 derived types, transfer_expr and transfer_array_component are mutually
2164 transfer_array_component (tree expr
, gfc_component
* cm
, locus
* where
)
2173 gfc_array_info
*ss_array
;
2175 gfc_start_block (&block
);
2176 gfc_init_se (&se
, NULL
);
2178 /* Create and initialize Scalarization Status. Unlike in
2179 gfc_trans_transfer, we can't simply use gfc_walk_expr to take
2180 care of this task, because we don't have a gfc_expr at hand.
2181 Build one manually, as in gfc_trans_subarray_assign. */
2183 ss
= gfc_get_array_ss (gfc_ss_terminator
, NULL
, cm
->as
->rank
,
2185 ss_array
= &ss
->info
->data
.array
;
2187 if (cm
->attr
.pdt_array
)
2188 ss_array
->shape
= NULL
;
2190 ss_array
->shape
= gfc_get_shape (cm
->as
->rank
);
2192 ss_array
->descriptor
= expr
;
2193 ss_array
->data
= gfc_conv_array_data (expr
);
2194 ss_array
->offset
= gfc_conv_array_offset (expr
);
2195 for (n
= 0; n
< cm
->as
->rank
; n
++)
2197 ss_array
->start
[n
] = gfc_conv_array_lbound (expr
, n
);
2198 ss_array
->stride
[n
] = gfc_index_one_node
;
2200 if (cm
->attr
.pdt_array
)
2201 ss_array
->end
[n
] = gfc_conv_array_ubound (expr
, n
);
2204 mpz_init (ss_array
->shape
[n
]);
2205 mpz_sub (ss_array
->shape
[n
], cm
->as
->upper
[n
]->value
.integer
,
2206 cm
->as
->lower
[n
]->value
.integer
);
2207 mpz_add_ui (ss_array
->shape
[n
], ss_array
->shape
[n
], 1);
2211 /* Once we got ss, we use scalarizer to create the loop. */
2213 gfc_init_loopinfo (&loop
);
2214 gfc_add_ss_to_loop (&loop
, ss
);
2215 gfc_conv_ss_startstride (&loop
);
2216 gfc_conv_loop_setup (&loop
, where
);
2217 gfc_mark_ss_chain_used (ss
, 1);
2218 gfc_start_scalarized_body (&loop
, &body
);
2220 gfc_copy_loopinfo_to_se (&se
, &loop
);
2223 /* gfc_conv_tmp_array_ref assumes that se.expr contains the array. */
2225 gfc_conv_tmp_array_ref (&se
);
2227 /* Now se.expr contains an element of the array. Take the address and pass
2228 it to the IO routines. */
2229 tmp
= gfc_build_addr_expr (NULL_TREE
, se
.expr
);
2230 transfer_expr (&se
, &cm
->ts
, tmp
, NULL
, NULL_TREE
);
2232 /* We are done now with the loop body. Wrap up the scalarizer and
2235 gfc_add_block_to_block (&body
, &se
.pre
);
2236 gfc_add_block_to_block (&body
, &se
.post
);
2238 gfc_trans_scalarizing_loops (&loop
, &body
);
2240 gfc_add_block_to_block (&block
, &loop
.pre
);
2241 gfc_add_block_to_block (&block
, &loop
.post
);
2243 if (!cm
->attr
.pdt_array
)
2245 gcc_assert (ss_array
->shape
!= NULL
);
2246 gfc_free_shape (&ss_array
->shape
, cm
->as
->rank
);
2248 gfc_cleanup_loop (&loop
);
2250 return gfc_finish_block (&block
);
2254 /* Helper function for transfer_expr that looks for the DTIO procedure
2255 either as a typebound binding or in a generic interface. If present,
2256 the address expression of the procedure is returned. It is assumed
2257 that the procedure interface has been checked during resolution. */
2260 get_dtio_proc (gfc_typespec
* ts
, gfc_code
* code
, gfc_symbol
**dtio_sub
)
2262 gfc_symbol
*derived
;
2263 bool formatted
= false;
2264 gfc_dt
*dt
= code
->ext
.dt
;
2266 /* Determine when to use the formatted DTIO procedure. */
2267 if (dt
&& (dt
->format_expr
|| dt
->format_label
))
2270 if (ts
->type
== BT_CLASS
)
2271 derived
= ts
->u
.derived
->components
->ts
.u
.derived
;
2273 derived
= ts
->u
.derived
;
2275 gfc_symtree
*tb_io_st
= gfc_find_typebound_dtio_proc (derived
,
2276 last_dt
== WRITE
, formatted
);
2277 if (ts
->type
== BT_CLASS
&& tb_io_st
)
2279 // polymorphic DTIO call (based on the dynamic type)
2281 gfc_expr
*expr
= gfc_find_and_cut_at_last_class_ref (code
->expr1
);
2282 gfc_add_vptr_component (expr
);
2283 gfc_add_component_ref (expr
,
2284 tb_io_st
->n
.tb
->u
.generic
->specific_st
->name
);
2285 *dtio_sub
= tb_io_st
->n
.tb
->u
.generic
->specific
->u
.specific
->n
.sym
;
2286 gfc_init_se (&se
, NULL
);
2287 se
.want_pointer
= 1;
2288 gfc_conv_expr (&se
, expr
);
2289 gfc_free_expr (expr
);
2294 // non-polymorphic DTIO call (based on the declared type)
2295 *dtio_sub
= gfc_find_specific_dtio_proc (derived
, last_dt
== WRITE
,
2299 return gfc_build_addr_expr (NULL
, gfc_get_symbol_decl (*dtio_sub
));
2305 /* Generate the call for a scalar transfer node. */
2308 transfer_expr (gfc_se
* se
, gfc_typespec
* ts
, tree addr_expr
,
2309 gfc_code
* code
, tree vptr
)
2311 tree tmp
, function
, arg2
, arg3
, field
, expr
;
2315 /* It is possible to get a C_NULL_PTR or C_NULL_FUNPTR expression here if
2316 the user says something like: print *, 'c_null_ptr: ', c_null_ptr
2317 We need to translate the expression to a constant if it's either
2318 C_NULL_PTR or C_NULL_FUNPTR. We could also get a user variable of
2319 type C_PTR or C_FUNPTR, in which case the ts->type may no longer be
2320 BT_DERIVED (could have been changed by gfc_conv_expr). */
2321 if ((ts
->type
== BT_DERIVED
|| ts
->type
== BT_INTEGER
)
2322 && ts
->u
.derived
!= NULL
2323 && (ts
->is_iso_c
== 1 || ts
->u
.derived
->ts
.is_iso_c
== 1))
2325 ts
->type
= BT_INTEGER
;
2326 ts
->kind
= gfc_index_integer_kind
;
2329 /* gfortran reaches here for "print *, c_loc(xxx)". */
2330 if (ts
->type
== BT_VOID
2331 && code
->expr1
&& code
->expr1
->ts
.type
== BT_VOID
2332 && code
->expr1
->symtree
2333 && strcmp (code
->expr1
->symtree
->name
, "c_loc") == 0)
2335 ts
->type
= BT_INTEGER
;
2336 ts
->kind
= gfc_index_integer_kind
;
2339 kind
= gfc_type_abi_kind (ts
);
2347 arg2
= build_int_cst (integer_type_node
, kind
);
2348 if (last_dt
== READ
)
2349 function
= iocall
[IOCALL_X_INTEGER
];
2351 function
= iocall
[IOCALL_X_INTEGER_WRITE
];
2356 arg2
= build_int_cst (unsigned_type_node
, kind
);
2357 if (last_dt
== READ
)
2358 function
= iocall
[IOCALL_X_UNSIGNED
];
2360 function
= iocall
[IOCALL_X_UNSIGNED_WRITE
];
2365 arg2
= build_int_cst (integer_type_node
, kind
);
2366 if (last_dt
== READ
)
2368 if ((gfc_real16_is_float128
&& kind
== 16) || kind
== 17)
2369 function
= iocall
[IOCALL_X_REAL128
];
2371 function
= iocall
[IOCALL_X_REAL
];
2375 if ((gfc_real16_is_float128
&& kind
== 16) || kind
== 17)
2376 function
= iocall
[IOCALL_X_REAL128_WRITE
];
2378 function
= iocall
[IOCALL_X_REAL_WRITE
];
2384 arg2
= build_int_cst (integer_type_node
, kind
);
2385 if (last_dt
== READ
)
2387 if ((gfc_real16_is_float128
&& kind
== 16) || kind
== 17)
2388 function
= iocall
[IOCALL_X_COMPLEX128
];
2390 function
= iocall
[IOCALL_X_COMPLEX
];
2394 if ((gfc_real16_is_float128
&& kind
== 16) || kind
== 17)
2395 function
= iocall
[IOCALL_X_COMPLEX128_WRITE
];
2397 function
= iocall
[IOCALL_X_COMPLEX_WRITE
];
2403 arg2
= build_int_cst (integer_type_node
, kind
);
2404 if (last_dt
== READ
)
2405 function
= iocall
[IOCALL_X_LOGICAL
];
2407 function
= iocall
[IOCALL_X_LOGICAL_WRITE
];
2414 if (se
->string_length
)
2415 arg2
= se
->string_length
;
2418 tmp
= build_fold_indirect_ref_loc (input_location
,
2420 gcc_assert (TREE_CODE (TREE_TYPE (tmp
)) == ARRAY_TYPE
);
2421 arg2
= TYPE_MAX_VALUE (TYPE_DOMAIN (TREE_TYPE (tmp
)));
2422 arg2
= fold_convert (gfc_charlen_type_node
, arg2
);
2424 arg3
= build_int_cst (integer_type_node
, kind
);
2425 if (last_dt
== READ
)
2426 function
= iocall
[IOCALL_X_CHARACTER_WIDE
];
2428 function
= iocall
[IOCALL_X_CHARACTER_WIDE_WRITE
];
2430 tmp
= gfc_build_addr_expr (NULL_TREE
, dt_parm
);
2431 tmp
= build_call_expr_loc (input_location
,
2432 function
, 4, tmp
, addr_expr
, arg2
, arg3
);
2433 gfc_add_expr_to_block (&se
->pre
, tmp
);
2434 gfc_add_block_to_block (&se
->pre
, &se
->post
);
2439 if (se
->string_length
)
2440 arg2
= se
->string_length
;
2443 tmp
= build_fold_indirect_ref_loc (input_location
,
2445 gcc_assert (TREE_CODE (TREE_TYPE (tmp
)) == ARRAY_TYPE
);
2446 arg2
= TYPE_MAX_VALUE (TYPE_DOMAIN (TREE_TYPE (tmp
)));
2448 if (last_dt
== READ
)
2449 function
= iocall
[IOCALL_X_CHARACTER
];
2451 function
= iocall
[IOCALL_X_CHARACTER_WRITE
];
2457 if (gfc_bt_struct (ts
->type
) || ts
->type
== BT_CLASS
)
2459 gfc_symbol
*derived
;
2460 gfc_symbol
*dtio_sub
= NULL
;
2461 /* Test for a specific DTIO subroutine. */
2462 if (ts
->type
== BT_DERIVED
)
2463 derived
= ts
->u
.derived
;
2465 derived
= ts
->u
.derived
->components
->ts
.u
.derived
;
2467 if (derived
->attr
.has_dtio_procs
)
2468 arg2
= get_dtio_proc (ts
, code
, &dtio_sub
);
2470 if ((dtio_sub
!= NULL
) && (last_dt
!= IOLENGTH
))
2473 decl
= build_fold_indirect_ref_loc (input_location
,
2475 /* Remember that the first dummy of the DTIO subroutines
2476 is CLASS(derived) for extensible derived types, so the
2477 conversion must be done here for derived type and for
2478 scalarized CLASS array element io-list objects. */
2479 if ((ts
->type
== BT_DERIVED
2480 && !(ts
->u
.derived
->attr
.sequence
2481 || ts
->u
.derived
->attr
.is_bind_c
))
2482 || (ts
->type
== BT_CLASS
2483 && !GFC_CLASS_TYPE_P (TREE_TYPE (decl
))))
2484 gfc_conv_derived_to_class (se
, code
->expr1
,
2485 dtio_sub
->formal
->sym
, vptr
, false,
2487 addr_expr
= se
->expr
;
2488 function
= iocall
[IOCALL_X_DERIVED
];
2491 else if (gfc_bt_struct (ts
->type
))
2493 /* Recurse into the elements of the derived type. */
2494 expr
= gfc_evaluate_now (addr_expr
, &se
->pre
);
2495 expr
= build_fold_indirect_ref_loc (input_location
, expr
);
2497 /* Make sure that the derived type has been built. An external
2498 function, if only referenced in an io statement, requires this
2499 check (see PR58771). */
2500 if (ts
->u
.derived
->backend_decl
== NULL_TREE
)
2501 (void) gfc_typenode_for_spec (ts
);
2503 for (c
= ts
->u
.derived
->components
; c
; c
= c
->next
)
2505 /* Ignore hidden string lengths. */
2506 if (c
->name
[0] == '_')
2509 field
= c
->backend_decl
;
2510 gcc_assert (field
&& TREE_CODE (field
) == FIELD_DECL
);
2512 tmp
= fold_build3_loc (UNKNOWN_LOCATION
,
2513 COMPONENT_REF
, TREE_TYPE (field
),
2514 expr
, field
, NULL_TREE
);
2516 if (c
->attr
.dimension
)
2518 tmp
= transfer_array_component (tmp
, c
, & code
->loc
);
2519 gfc_add_expr_to_block (&se
->pre
, tmp
);
2523 tree strlen
= NULL_TREE
;
2525 if (!c
->attr
.pointer
&& !c
->attr
.pdt_string
)
2526 tmp
= gfc_build_addr_expr (NULL_TREE
, tmp
);
2528 /* Use the hidden string length for pdt strings. */
2529 if (c
->attr
.pdt_string
2530 && gfc_deferred_strlen (c
, &strlen
)
2531 && strlen
!= NULL_TREE
)
2533 strlen
= fold_build3_loc (UNKNOWN_LOCATION
,
2536 expr
, strlen
, NULL_TREE
);
2537 se
->string_length
= strlen
;
2540 transfer_expr (se
, &c
->ts
, tmp
, code
, NULL_TREE
);
2542 /* Reset so that the pdt string length does not propagate
2543 through to other strings. */
2544 if (c
->attr
.pdt_string
&& strlen
)
2545 se
->string_length
= NULL_TREE
;
2550 /* If a CLASS object gets through to here, fall through and ICE. */
2554 gfc_internal_error ("Bad IO basetype (%d)", ts
->type
);
2557 tmp
= gfc_build_addr_expr (NULL_TREE
, dt_parm
);
2558 tmp
= build_call_expr_loc (input_location
,
2559 function
, 3, tmp
, addr_expr
, arg2
);
2560 gfc_add_expr_to_block (&se
->pre
, tmp
);
2561 gfc_add_block_to_block (&se
->pre
, &se
->post
);
2566 /* Generate a call to pass an array descriptor to the IO library. The
2567 array should be of one of the intrinsic types. */
2570 transfer_array_desc (gfc_se
* se
, gfc_typespec
* ts
, tree addr_expr
)
2572 tree tmp
, charlen_arg
, kind_arg
, io_call
;
2574 if (ts
->type
== BT_CHARACTER
)
2575 charlen_arg
= se
->string_length
;
2577 charlen_arg
= build_int_cst (gfc_charlen_type_node
, 0);
2579 kind_arg
= build_int_cst (integer_type_node
, gfc_type_abi_kind (ts
));
2581 tmp
= gfc_build_addr_expr (NULL_TREE
, dt_parm
);
2582 if (last_dt
== READ
)
2583 io_call
= iocall
[IOCALL_X_ARRAY
];
2585 io_call
= iocall
[IOCALL_X_ARRAY_WRITE
];
2587 tmp
= build_call_expr_loc (UNKNOWN_LOCATION
,
2589 tmp
, addr_expr
, kind_arg
, charlen_arg
);
2590 gfc_add_expr_to_block (&se
->pre
, tmp
);
2591 gfc_add_block_to_block (&se
->pre
, &se
->post
);
2595 /* gfc_trans_transfer()-- Translate a TRANSFER code node */
2598 gfc_trans_transfer (gfc_code
* code
)
2600 stmtblock_t block
, body
;
2610 gfc_start_block (&block
);
2611 gfc_init_block (&body
);
2615 gfc_init_se (&se
, NULL
);
2617 if (expr
->rank
== 0)
2619 /* Transfer a scalar value. */
2620 if (expr
->ts
.type
== BT_CLASS
)
2622 se
.want_pointer
= 1;
2623 gfc_conv_expr (&se
, expr
);
2624 vptr
= gfc_get_vptr_from_expr (se
.expr
);
2629 gfc_conv_expr_reference (&se
, expr
);
2631 transfer_expr (&se
, &expr
->ts
, se
.expr
, code
, vptr
);
2635 /* Transfer an array. If it is an array of an intrinsic
2636 type, pass the descriptor to the library. Otherwise
2637 scalarize the transfer. */
2638 if (expr
->ref
&& !gfc_is_proc_ptr_comp (expr
))
2640 for (ref
= expr
->ref
; ref
&& ref
->type
!= REF_ARRAY
;
2642 gcc_assert (ref
&& ref
->type
== REF_ARRAY
);
2645 /* These expressions don't always have the dtype element length set
2646 correctly, rendering them useless for array transfer. */
2647 if (expr
->ts
.type
!= BT_CLASS
2648 && expr
->expr_type
== EXPR_VARIABLE
2649 && ((expr
->symtree
->n
.sym
->ts
.type
== BT_DERIVED
&& expr
->ts
.deferred
)
2650 || (expr
->symtree
->n
.sym
->assoc
2651 && expr
->symtree
->n
.sym
->assoc
->variable
)
2652 || gfc_expr_attr (expr
).pointer
))
2655 if (!(gfc_bt_struct (expr
->ts
.type
)
2656 || expr
->ts
.type
== BT_CLASS
)
2657 && ref
&& ref
->next
== NULL
2658 && !is_subref_array (expr
))
2660 bool seen_vector
= false;
2662 if (ref
&& ref
->u
.ar
.type
== AR_SECTION
)
2664 for (n
= 0; n
< ref
->u
.ar
.dimen
; n
++)
2665 if (ref
->u
.ar
.dimen_type
[n
] == DIMEN_VECTOR
)
2672 if (seen_vector
&& last_dt
== READ
)
2674 /* Create a temp, read to that and copy it back. */
2675 gfc_conv_subref_array_arg (&se
, expr
, 0, INTENT_OUT
, false);
2680 /* Get the descriptor. */
2681 gfc_conv_expr_descriptor (&se
, expr
);
2682 tmp
= gfc_build_addr_expr (NULL_TREE
, se
.expr
);
2685 transfer_array_desc (&se
, &expr
->ts
, tmp
);
2686 goto finish_block_label
;
2690 /* Initialize the scalarizer. */
2691 ss
= gfc_walk_expr (expr
);
2692 gfc_init_loopinfo (&loop
);
2693 gfc_add_ss_to_loop (&loop
, ss
);
2695 /* Initialize the loop. */
2696 gfc_conv_ss_startstride (&loop
);
2697 gfc_conv_loop_setup (&loop
, &code
->expr1
->where
);
2699 /* The main loop body. */
2700 gfc_mark_ss_chain_used (ss
, 1);
2701 gfc_start_scalarized_body (&loop
, &body
);
2703 gfc_copy_loopinfo_to_se (&se
, &loop
);
2706 gfc_conv_expr_reference (&se
, expr
);
2708 if (expr
->ts
.type
== BT_CLASS
)
2709 vptr
= gfc_get_vptr_from_expr (ss
->info
->data
.array
.descriptor
);
2712 transfer_expr (&se
, &expr
->ts
, se
.expr
, code
, vptr
);
2717 gfc_add_block_to_block (&body
, &se
.pre
);
2718 gfc_add_block_to_block (&body
, &se
.post
);
2719 gfc_add_block_to_block (&body
, &se
.finalblock
);
2722 tmp
= gfc_finish_block (&body
);
2725 gcc_assert (expr
->rank
!= 0);
2726 gcc_assert (se
.ss
== gfc_ss_terminator
);
2727 gfc_trans_scalarizing_loops (&loop
, &body
);
2729 gfc_add_block_to_block (&loop
.pre
, &loop
.post
);
2730 tmp
= gfc_finish_block (&loop
.pre
);
2731 gfc_cleanup_loop (&loop
);
2734 gfc_add_expr_to_block (&block
, tmp
);
2736 return gfc_finish_block (&block
);
2739 #include "gt-fortran-trans-io.h"