1 /* IO Code translation/library interface
2 Copyright (C) 2002-2015 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"
36 /* Members of the ioparm structure. */
65 typedef struct GTY(()) gfc_st_parameter_field
{
68 enum ioparam_type param_type
;
69 enum iofield_type type
;
73 gfc_st_parameter_field
;
75 typedef struct GTY(()) gfc_st_parameter
{
83 #define IOPARM(param_type, name, mask, type) IOPARM_##param_type##_##name,
89 static GTY(()) gfc_st_parameter st_parameter
[] =
100 static GTY(()) gfc_st_parameter_field st_parameter_field
[] =
102 #define IOPARM(param_type, name, mask, type) \
103 { #name, mask, IOPARM_ptype_##param_type, IOPARM_type_##type, NULL, NULL },
104 #include "ioparm.def"
106 { NULL
, 0, (enum ioparam_type
) 0, (enum iofield_type
) 0, NULL
, NULL
}
109 /* Library I/O subroutines */
118 IOCALL_X_INTEGER_WRITE
,
120 IOCALL_X_LOGICAL_WRITE
,
122 IOCALL_X_CHARACTER_WRITE
,
123 IOCALL_X_CHARACTER_WIDE
,
124 IOCALL_X_CHARACTER_WIDE_WRITE
,
128 IOCALL_X_COMPLEX_WRITE
,
130 IOCALL_X_REAL128_WRITE
,
132 IOCALL_X_COMPLEX128_WRITE
,
134 IOCALL_X_ARRAY_WRITE
,
139 IOCALL_IOLENGTH_DONE
,
145 IOCALL_SET_NML_VAL_DIM
,
150 static GTY(()) tree iocall
[IOCALL_NUM
];
152 /* Variable for keeping track of what the last data transfer statement
153 was. Used for deciding which subroutine to call when the data
154 transfer is complete. */
155 static enum { READ
, WRITE
, IOLENGTH
} last_dt
;
157 /* The data transfer parameter block that should be shared by all
158 data transfer calls belonging to the same read/write/iolength. */
159 static GTY(()) tree dt_parm
;
160 static stmtblock_t
*dt_post_end_block
;
163 gfc_build_st_parameter (enum ioparam_type ptype
, tree
*types
)
166 gfc_st_parameter_field
*p
;
169 tree t
= make_node (RECORD_TYPE
);
172 len
= strlen (st_parameter
[ptype
].name
);
173 gcc_assert (len
<= sizeof (name
) - sizeof ("__st_parameter_"));
174 memcpy (name
, "__st_parameter_", sizeof ("__st_parameter_"));
175 memcpy (name
+ sizeof ("__st_parameter_") - 1, st_parameter
[ptype
].name
,
177 TYPE_NAME (t
) = get_identifier (name
);
179 for (type
= 0, p
= st_parameter_field
; type
< IOPARM_field_num
; type
++, p
++)
180 if (p
->param_type
== ptype
)
183 case IOPARM_type_int4
:
184 case IOPARM_type_intio
:
185 case IOPARM_type_pint4
:
186 case IOPARM_type_pintio
:
187 case IOPARM_type_parray
:
188 case IOPARM_type_pchar
:
189 case IOPARM_type_pad
:
190 p
->field
= gfc_add_field_to_struct (t
, get_identifier (p
->name
),
191 types
[p
->type
], &chain
);
193 case IOPARM_type_char1
:
194 p
->field
= gfc_add_field_to_struct (t
, get_identifier (p
->name
),
195 pchar_type_node
, &chain
);
197 case IOPARM_type_char2
:
198 len
= strlen (p
->name
);
199 gcc_assert (len
<= sizeof (name
) - sizeof ("_len"));
200 memcpy (name
, p
->name
, len
);
201 memcpy (name
+ len
, "_len", sizeof ("_len"));
202 p
->field_len
= gfc_add_field_to_struct (t
, get_identifier (name
),
203 gfc_charlen_type_node
,
205 if (p
->type
== IOPARM_type_char2
)
206 p
->field
= gfc_add_field_to_struct (t
, get_identifier (p
->name
),
207 pchar_type_node
, &chain
);
209 case IOPARM_type_common
:
211 = gfc_add_field_to_struct (t
,
212 get_identifier (p
->name
),
213 st_parameter
[IOPARM_ptype_common
].type
,
216 case IOPARM_type_num
:
221 st_parameter
[ptype
].type
= t
;
225 /* Build code to test an error condition and call generate_error if needed.
226 Note: This builds calls to generate_error in the runtime library function.
227 The function generate_error is dependent on certain parameters in the
228 st_parameter_common flags to be set. (See libgfortran/runtime/error.c)
229 Therefore, the code to set these flags must be generated before
230 this function is used. */
233 gfc_trans_io_runtime_check (bool has_iostat
, tree cond
, tree var
,
234 int error_code
, const char * msgid
,
235 stmtblock_t
* pblock
)
240 tree arg1
, arg2
, arg3
;
243 if (integer_zerop (cond
))
246 /* The code to generate the error. */
247 gfc_start_block (&block
);
250 gfc_add_expr_to_block (&block
, build_predict_expr (PRED_FORTRAN_FAIL_IO
,
253 gfc_add_expr_to_block (&block
, build_predict_expr (PRED_NORETURN
,
256 arg1
= gfc_build_addr_expr (NULL_TREE
, var
);
258 arg2
= build_int_cst (integer_type_node
, error_code
),
260 message
= xasprintf ("%s", _(msgid
));
261 arg3
= gfc_build_addr_expr (pchar_type_node
,
262 gfc_build_localized_cstring_const (message
));
265 tmp
= build_call_expr_loc (input_location
,
266 gfor_fndecl_generate_error
, 3, arg1
, arg2
, arg3
);
268 gfc_add_expr_to_block (&block
, tmp
);
270 body
= gfc_finish_block (&block
);
272 if (integer_onep (cond
))
274 gfc_add_expr_to_block (pblock
, body
);
278 tmp
= build3_v (COND_EXPR
, cond
, body
, build_empty_stmt (input_location
));
279 gfc_add_expr_to_block (pblock
, tmp
);
284 /* Create function decls for IO library functions. */
287 gfc_build_io_library_fndecls (void)
289 tree types
[IOPARM_type_num
], pad_idx
, gfc_int4_type_node
;
290 tree gfc_intio_type_node
;
291 tree parm_type
, dt_parm_type
;
292 HOST_WIDE_INT pad_size
;
295 types
[IOPARM_type_int4
] = gfc_int4_type_node
= gfc_get_int_type (4);
296 types
[IOPARM_type_intio
] = gfc_intio_type_node
297 = gfc_get_int_type (gfc_intio_kind
);
298 types
[IOPARM_type_pint4
] = build_pointer_type (gfc_int4_type_node
);
299 types
[IOPARM_type_pintio
]
300 = build_pointer_type (gfc_intio_type_node
);
301 types
[IOPARM_type_parray
] = pchar_type_node
;
302 types
[IOPARM_type_pchar
] = pchar_type_node
;
303 pad_size
= 16 * TREE_INT_CST_LOW (TYPE_SIZE_UNIT (pchar_type_node
));
304 pad_size
+= 32 * TREE_INT_CST_LOW (TYPE_SIZE_UNIT (integer_type_node
));
305 pad_idx
= build_index_type (size_int (pad_size
- 1));
306 types
[IOPARM_type_pad
] = build_array_type (char_type_node
, pad_idx
);
308 /* pad actually contains pointers and integers so it needs to have an
309 alignment that is at least as large as the needed alignment for those
310 types. See the st_parameter_dt structure in libgfortran/io/io.h for
311 what really goes into this space. */
312 TYPE_ALIGN (types
[IOPARM_type_pad
]) = MAX (TYPE_ALIGN (pchar_type_node
),
313 TYPE_ALIGN (gfc_get_int_type (gfc_intio_kind
)));
315 for (ptype
= IOPARM_ptype_common
; ptype
< IOPARM_ptype_num
; ptype
++)
316 gfc_build_st_parameter ((enum ioparam_type
) ptype
, types
);
318 /* Define the transfer functions. */
320 dt_parm_type
= build_pointer_type (st_parameter
[IOPARM_ptype_dt
].type
);
322 iocall
[IOCALL_X_INTEGER
] = gfc_build_library_function_decl_with_spec (
323 get_identifier (PREFIX("transfer_integer")), ".wW",
324 void_type_node
, 3, dt_parm_type
, pvoid_type_node
, gfc_int4_type_node
);
326 iocall
[IOCALL_X_INTEGER_WRITE
] = gfc_build_library_function_decl_with_spec (
327 get_identifier (PREFIX("transfer_integer_write")), ".wR",
328 void_type_node
, 3, dt_parm_type
, pvoid_type_node
, gfc_int4_type_node
);
330 iocall
[IOCALL_X_LOGICAL
] = gfc_build_library_function_decl_with_spec (
331 get_identifier (PREFIX("transfer_logical")), ".wW",
332 void_type_node
, 3, dt_parm_type
, pvoid_type_node
, gfc_int4_type_node
);
334 iocall
[IOCALL_X_LOGICAL_WRITE
] = gfc_build_library_function_decl_with_spec (
335 get_identifier (PREFIX("transfer_logical_write")), ".wR",
336 void_type_node
, 3, dt_parm_type
, pvoid_type_node
, gfc_int4_type_node
);
338 iocall
[IOCALL_X_CHARACTER
] = gfc_build_library_function_decl_with_spec (
339 get_identifier (PREFIX("transfer_character")), ".wW",
340 void_type_node
, 3, dt_parm_type
, pvoid_type_node
, gfc_int4_type_node
);
342 iocall
[IOCALL_X_CHARACTER_WRITE
] = gfc_build_library_function_decl_with_spec (
343 get_identifier (PREFIX("transfer_character_write")), ".wR",
344 void_type_node
, 3, dt_parm_type
, pvoid_type_node
, gfc_int4_type_node
);
346 iocall
[IOCALL_X_CHARACTER_WIDE
] = gfc_build_library_function_decl_with_spec (
347 get_identifier (PREFIX("transfer_character_wide")), ".wW",
348 void_type_node
, 4, dt_parm_type
, pvoid_type_node
,
349 gfc_charlen_type_node
, gfc_int4_type_node
);
351 iocall
[IOCALL_X_CHARACTER_WIDE_WRITE
] =
352 gfc_build_library_function_decl_with_spec (
353 get_identifier (PREFIX("transfer_character_wide_write")), ".wR",
354 void_type_node
, 4, dt_parm_type
, pvoid_type_node
,
355 gfc_charlen_type_node
, gfc_int4_type_node
);
357 iocall
[IOCALL_X_REAL
] = gfc_build_library_function_decl_with_spec (
358 get_identifier (PREFIX("transfer_real")), ".wW",
359 void_type_node
, 3, dt_parm_type
, pvoid_type_node
, gfc_int4_type_node
);
361 iocall
[IOCALL_X_REAL_WRITE
] = gfc_build_library_function_decl_with_spec (
362 get_identifier (PREFIX("transfer_real_write")), ".wR",
363 void_type_node
, 3, dt_parm_type
, pvoid_type_node
, gfc_int4_type_node
);
365 iocall
[IOCALL_X_COMPLEX
] = gfc_build_library_function_decl_with_spec (
366 get_identifier (PREFIX("transfer_complex")), ".wW",
367 void_type_node
, 3, dt_parm_type
, pvoid_type_node
, gfc_int4_type_node
);
369 iocall
[IOCALL_X_COMPLEX_WRITE
] = gfc_build_library_function_decl_with_spec (
370 get_identifier (PREFIX("transfer_complex_write")), ".wR",
371 void_type_node
, 3, dt_parm_type
, pvoid_type_node
, gfc_int4_type_node
);
373 /* Version for __float128. */
374 iocall
[IOCALL_X_REAL128
] = gfc_build_library_function_decl_with_spec (
375 get_identifier (PREFIX("transfer_real128")), ".wW",
376 void_type_node
, 3, dt_parm_type
, pvoid_type_node
, gfc_int4_type_node
);
378 iocall
[IOCALL_X_REAL128_WRITE
] = gfc_build_library_function_decl_with_spec (
379 get_identifier (PREFIX("transfer_real128_write")), ".wR",
380 void_type_node
, 3, dt_parm_type
, pvoid_type_node
, gfc_int4_type_node
);
382 iocall
[IOCALL_X_COMPLEX128
] = gfc_build_library_function_decl_with_spec (
383 get_identifier (PREFIX("transfer_complex128")), ".wW",
384 void_type_node
, 3, dt_parm_type
, pvoid_type_node
, gfc_int4_type_node
);
386 iocall
[IOCALL_X_COMPLEX128_WRITE
] = gfc_build_library_function_decl_with_spec (
387 get_identifier (PREFIX("transfer_complex128_write")), ".wR",
388 void_type_node
, 3, dt_parm_type
, pvoid_type_node
, gfc_int4_type_node
);
390 iocall
[IOCALL_X_ARRAY
] = gfc_build_library_function_decl_with_spec (
391 get_identifier (PREFIX("transfer_array")), ".ww",
392 void_type_node
, 4, dt_parm_type
, pvoid_type_node
,
393 integer_type_node
, gfc_charlen_type_node
);
395 iocall
[IOCALL_X_ARRAY_WRITE
] = gfc_build_library_function_decl_with_spec (
396 get_identifier (PREFIX("transfer_array_write")), ".wr",
397 void_type_node
, 4, dt_parm_type
, pvoid_type_node
,
398 integer_type_node
, gfc_charlen_type_node
);
400 /* Library entry points */
402 iocall
[IOCALL_READ
] = gfc_build_library_function_decl_with_spec (
403 get_identifier (PREFIX("st_read")), ".w",
404 void_type_node
, 1, dt_parm_type
);
406 iocall
[IOCALL_WRITE
] = gfc_build_library_function_decl_with_spec (
407 get_identifier (PREFIX("st_write")), ".w",
408 void_type_node
, 1, dt_parm_type
);
410 parm_type
= build_pointer_type (st_parameter
[IOPARM_ptype_open
].type
);
411 iocall
[IOCALL_OPEN
] = gfc_build_library_function_decl_with_spec (
412 get_identifier (PREFIX("st_open")), ".w",
413 void_type_node
, 1, parm_type
);
415 parm_type
= build_pointer_type (st_parameter
[IOPARM_ptype_close
].type
);
416 iocall
[IOCALL_CLOSE
] = gfc_build_library_function_decl_with_spec (
417 get_identifier (PREFIX("st_close")), ".w",
418 void_type_node
, 1, parm_type
);
420 parm_type
= build_pointer_type (st_parameter
[IOPARM_ptype_inquire
].type
);
421 iocall
[IOCALL_INQUIRE
] = gfc_build_library_function_decl_with_spec (
422 get_identifier (PREFIX("st_inquire")), ".w",
423 void_type_node
, 1, parm_type
);
425 iocall
[IOCALL_IOLENGTH
] = gfc_build_library_function_decl_with_spec(
426 get_identifier (PREFIX("st_iolength")), ".w",
427 void_type_node
, 1, dt_parm_type
);
429 /* TODO: Change when asynchronous I/O is implemented. */
430 parm_type
= build_pointer_type (st_parameter
[IOPARM_ptype_wait
].type
);
431 iocall
[IOCALL_WAIT
] = gfc_build_library_function_decl_with_spec (
432 get_identifier (PREFIX("st_wait")), ".X",
433 void_type_node
, 1, parm_type
);
435 parm_type
= build_pointer_type (st_parameter
[IOPARM_ptype_filepos
].type
);
436 iocall
[IOCALL_REWIND
] = gfc_build_library_function_decl_with_spec (
437 get_identifier (PREFIX("st_rewind")), ".w",
438 void_type_node
, 1, parm_type
);
440 iocall
[IOCALL_BACKSPACE
] = gfc_build_library_function_decl_with_spec (
441 get_identifier (PREFIX("st_backspace")), ".w",
442 void_type_node
, 1, parm_type
);
444 iocall
[IOCALL_ENDFILE
] = gfc_build_library_function_decl_with_spec (
445 get_identifier (PREFIX("st_endfile")), ".w",
446 void_type_node
, 1, parm_type
);
448 iocall
[IOCALL_FLUSH
] = gfc_build_library_function_decl_with_spec (
449 get_identifier (PREFIX("st_flush")), ".w",
450 void_type_node
, 1, parm_type
);
452 /* Library helpers */
454 iocall
[IOCALL_READ_DONE
] = gfc_build_library_function_decl_with_spec (
455 get_identifier (PREFIX("st_read_done")), ".w",
456 void_type_node
, 1, dt_parm_type
);
458 iocall
[IOCALL_WRITE_DONE
] = gfc_build_library_function_decl_with_spec (
459 get_identifier (PREFIX("st_write_done")), ".w",
460 void_type_node
, 1, dt_parm_type
);
462 iocall
[IOCALL_IOLENGTH_DONE
] = gfc_build_library_function_decl_with_spec (
463 get_identifier (PREFIX("st_iolength_done")), ".w",
464 void_type_node
, 1, dt_parm_type
);
466 iocall
[IOCALL_SET_NML_VAL
] = gfc_build_library_function_decl_with_spec (
467 get_identifier (PREFIX("st_set_nml_var")), ".w.R",
468 void_type_node
, 6, dt_parm_type
, pvoid_type_node
, pvoid_type_node
,
469 gfc_int4_type_node
, gfc_charlen_type_node
, gfc_int4_type_node
);
471 iocall
[IOCALL_SET_NML_VAL_DIM
] = gfc_build_library_function_decl_with_spec (
472 get_identifier (PREFIX("st_set_nml_var_dim")), ".w",
473 void_type_node
, 5, dt_parm_type
, gfc_int4_type_node
,
474 gfc_array_index_type
, gfc_array_index_type
, gfc_array_index_type
);
478 /* Generate code to store an integer constant into the
479 st_parameter_XXX structure. */
482 set_parameter_const (stmtblock_t
*block
, tree var
, enum iofield type
,
486 gfc_st_parameter_field
*p
= &st_parameter_field
[type
];
488 if (p
->param_type
== IOPARM_ptype_common
)
489 var
= fold_build3_loc (input_location
, COMPONENT_REF
,
490 st_parameter
[IOPARM_ptype_common
].type
,
491 var
, TYPE_FIELDS (TREE_TYPE (var
)), NULL_TREE
);
492 tmp
= fold_build3_loc (input_location
, COMPONENT_REF
, TREE_TYPE (p
->field
),
493 var
, p
->field
, NULL_TREE
);
494 gfc_add_modify (block
, tmp
, build_int_cst (TREE_TYPE (p
->field
), val
));
499 /* Generate code to store a non-string I/O parameter into the
500 st_parameter_XXX structure. This is a pass by value. */
503 set_parameter_value (stmtblock_t
*block
, tree var
, enum iofield type
,
508 gfc_st_parameter_field
*p
= &st_parameter_field
[type
];
509 tree dest_type
= TREE_TYPE (p
->field
);
511 gfc_init_se (&se
, NULL
);
512 gfc_conv_expr_val (&se
, e
);
514 se
.expr
= convert (dest_type
, se
.expr
);
515 gfc_add_block_to_block (block
, &se
.pre
);
517 if (p
->param_type
== IOPARM_ptype_common
)
518 var
= fold_build3_loc (input_location
, COMPONENT_REF
,
519 st_parameter
[IOPARM_ptype_common
].type
,
520 var
, TYPE_FIELDS (TREE_TYPE (var
)), NULL_TREE
);
522 tmp
= fold_build3_loc (input_location
, COMPONENT_REF
, dest_type
, var
,
523 p
->field
, NULL_TREE
);
524 gfc_add_modify (block
, tmp
, se
.expr
);
529 /* Similar to set_parameter_value except generate runtime
533 set_parameter_value_chk (stmtblock_t
*block
, bool has_iostat
, tree var
,
534 enum iofield type
, gfc_expr
*e
)
538 gfc_st_parameter_field
*p
= &st_parameter_field
[type
];
539 tree dest_type
= TREE_TYPE (p
->field
);
541 gfc_init_se (&se
, NULL
);
542 gfc_conv_expr_val (&se
, e
);
544 /* If we're storing a UNIT number, we need to check it first. */
545 if (type
== IOPARM_common_unit
&& e
->ts
.kind
> 4)
550 /* Don't evaluate the UNIT number multiple times. */
551 se
.expr
= gfc_evaluate_now (se
.expr
, &se
.pre
);
553 /* UNIT numbers should be greater than the min. */
554 i
= gfc_validate_kind (BT_INTEGER
, 4, false);
555 val
= gfc_conv_mpz_to_tree (gfc_integer_kinds
[i
].pedantic_min_int
, 4);
556 cond
= fold_build2_loc (input_location
, LT_EXPR
, boolean_type_node
,
558 fold_convert (TREE_TYPE (se
.expr
), val
));
559 gfc_trans_io_runtime_check (has_iostat
, cond
, var
, LIBERROR_BAD_UNIT
,
560 "Unit number in I/O statement too small",
563 /* UNIT numbers should be less than the max. */
564 val
= gfc_conv_mpz_to_tree (gfc_integer_kinds
[i
].huge
, 4);
565 cond
= fold_build2_loc (input_location
, GT_EXPR
, boolean_type_node
,
567 fold_convert (TREE_TYPE (se
.expr
), val
));
568 gfc_trans_io_runtime_check (has_iostat
, cond
, var
, LIBERROR_BAD_UNIT
,
569 "Unit number in I/O statement too large",
573 se
.expr
= convert (dest_type
, se
.expr
);
574 gfc_add_block_to_block (block
, &se
.pre
);
576 if (p
->param_type
== IOPARM_ptype_common
)
577 var
= fold_build3_loc (input_location
, COMPONENT_REF
,
578 st_parameter
[IOPARM_ptype_common
].type
,
579 var
, TYPE_FIELDS (TREE_TYPE (var
)), NULL_TREE
);
581 tmp
= fold_build3_loc (input_location
, COMPONENT_REF
, dest_type
, var
,
582 p
->field
, NULL_TREE
);
583 gfc_add_modify (block
, tmp
, se
.expr
);
588 /* Build code to check the unit range if KIND=8 is used. Similar to
589 set_parameter_value_chk but we do not generate error calls for
590 inquire statements. */
593 set_parameter_value_inquire (stmtblock_t
*block
, tree var
,
594 enum iofield type
, gfc_expr
*e
)
597 gfc_st_parameter_field
*p
= &st_parameter_field
[type
];
598 tree dest_type
= TREE_TYPE (p
->field
);
600 gfc_init_se (&se
, NULL
);
601 gfc_conv_expr_val (&se
, e
);
603 /* If we're inquiring on a UNIT number, we need to check to make
604 sure it exists for larger than kind = 4. */
605 if (type
== IOPARM_common_unit
&& e
->ts
.kind
> 4)
607 stmtblock_t newblock
;
608 tree cond1
, cond2
, cond3
, val
, body
;
611 /* Don't evaluate the UNIT number multiple times. */
612 se
.expr
= gfc_evaluate_now (se
.expr
, &se
.pre
);
614 /* UNIT numbers should be greater than zero. */
615 i
= gfc_validate_kind (BT_INTEGER
, 4, false);
616 cond1
= build2_loc (input_location
, LT_EXPR
, boolean_type_node
,
618 fold_convert (TREE_TYPE (se
.expr
),
620 /* UNIT numbers should be less than the max. */
621 val
= gfc_conv_mpz_to_tree (gfc_integer_kinds
[i
].huge
, 4);
622 cond2
= build2_loc (input_location
, GT_EXPR
, boolean_type_node
,
624 fold_convert (TREE_TYPE (se
.expr
), val
));
625 cond3
= build2_loc (input_location
, TRUTH_OR_EXPR
,
626 boolean_type_node
, cond1
, cond2
);
628 gfc_start_block (&newblock
);
630 /* The unit number GFC_INVALID_UNIT is reserved. No units can
631 ever have this value. It is used here to signal to the
632 runtime library that the inquire unit number is outside the
633 allowable range and so cannot exist. It is needed when
634 -fdefault-integer-8 is used. */
635 set_parameter_const (&newblock
, var
, IOPARM_common_unit
,
638 body
= gfc_finish_block (&newblock
);
640 cond3
= gfc_unlikely (cond3
, PRED_FORTRAN_FAIL_IO
);
641 var
= build3_v (COND_EXPR
, cond3
, body
, build_empty_stmt (input_location
));
642 gfc_add_expr_to_block (&se
.pre
, var
);
645 se
.expr
= convert (dest_type
, se
.expr
);
646 gfc_add_block_to_block (block
, &se
.pre
);
652 /* Generate code to store a non-string I/O parameter into the
653 st_parameter_XXX structure. This is pass by reference. */
656 set_parameter_ref (stmtblock_t
*block
, stmtblock_t
*postblock
,
657 tree var
, enum iofield type
, gfc_expr
*e
)
661 gfc_st_parameter_field
*p
= &st_parameter_field
[type
];
663 gcc_assert (e
->ts
.type
== BT_INTEGER
|| e
->ts
.type
== BT_LOGICAL
);
664 gfc_init_se (&se
, NULL
);
665 gfc_conv_expr_lhs (&se
, e
);
667 gfc_add_block_to_block (block
, &se
.pre
);
669 if (TYPE_MODE (TREE_TYPE (se
.expr
))
670 == TYPE_MODE (TREE_TYPE (TREE_TYPE (p
->field
))))
672 addr
= convert (TREE_TYPE (p
->field
), gfc_build_addr_expr (NULL_TREE
, se
.expr
));
674 /* If this is for the iostat variable initialize the
675 user variable to LIBERROR_OK which is zero. */
676 if (type
== IOPARM_common_iostat
)
677 gfc_add_modify (block
, se
.expr
,
678 build_int_cst (TREE_TYPE (se
.expr
), LIBERROR_OK
));
682 /* The type used by the library has different size
683 from the type of the variable supplied by the user.
684 Need to use a temporary. */
685 tree tmpvar
= gfc_create_var (TREE_TYPE (TREE_TYPE (p
->field
)),
686 st_parameter_field
[type
].name
);
688 /* If this is for the iostat variable, initialize the
689 user variable to LIBERROR_OK which is zero. */
690 if (type
== IOPARM_common_iostat
)
691 gfc_add_modify (block
, tmpvar
,
692 build_int_cst (TREE_TYPE (tmpvar
), LIBERROR_OK
));
694 addr
= gfc_build_addr_expr (NULL_TREE
, tmpvar
);
695 /* After the I/O operation, we set the variable from the temporary. */
696 tmp
= convert (TREE_TYPE (se
.expr
), tmpvar
);
697 gfc_add_modify (postblock
, se
.expr
, tmp
);
700 if (p
->param_type
== IOPARM_ptype_common
)
701 var
= fold_build3_loc (input_location
, COMPONENT_REF
,
702 st_parameter
[IOPARM_ptype_common
].type
,
703 var
, TYPE_FIELDS (TREE_TYPE (var
)), NULL_TREE
);
704 tmp
= fold_build3_loc (input_location
, COMPONENT_REF
, TREE_TYPE (p
->field
),
705 var
, p
->field
, NULL_TREE
);
706 gfc_add_modify (block
, tmp
, addr
);
710 /* Given an array expr, find its address and length to get a string. If the
711 array is full, the string's address is the address of array's first element
712 and the length is the size of the whole array. If it is an element, the
713 string's address is the element's address and the length is the rest size of
717 gfc_convert_array_to_string (gfc_se
* se
, gfc_expr
* e
)
723 tree type
, array
, tmp
;
727 /* If it is an element, we need its address and size of the rest. */
728 gcc_assert (e
->expr_type
== EXPR_VARIABLE
);
729 gcc_assert (e
->ref
->u
.ar
.type
== AR_ELEMENT
);
730 sym
= e
->symtree
->n
.sym
;
731 rank
= sym
->as
->rank
- 1;
732 gfc_conv_expr (se
, e
);
734 array
= sym
->backend_decl
;
735 type
= TREE_TYPE (array
);
737 if (GFC_ARRAY_TYPE_P (type
))
738 size
= GFC_TYPE_ARRAY_SIZE (type
);
741 gcc_assert (GFC_DESCRIPTOR_TYPE_P (type
));
742 size
= gfc_conv_array_stride (array
, rank
);
743 tmp
= fold_build2_loc (input_location
, MINUS_EXPR
,
744 gfc_array_index_type
,
745 gfc_conv_array_ubound (array
, rank
),
746 gfc_conv_array_lbound (array
, rank
));
747 tmp
= fold_build2_loc (input_location
, PLUS_EXPR
,
748 gfc_array_index_type
, tmp
,
750 size
= fold_build2_loc (input_location
, MULT_EXPR
,
751 gfc_array_index_type
, tmp
, size
);
755 size
= fold_build2_loc (input_location
, MINUS_EXPR
,
756 gfc_array_index_type
, size
,
757 TREE_OPERAND (se
->expr
, 1));
758 se
->expr
= gfc_build_addr_expr (NULL_TREE
, se
->expr
);
759 tmp
= TYPE_SIZE_UNIT (gfc_get_element_type (type
));
760 size
= fold_build2_loc (input_location
, MULT_EXPR
,
761 gfc_array_index_type
, size
,
762 fold_convert (gfc_array_index_type
, tmp
));
763 se
->string_length
= fold_convert (gfc_charlen_type_node
, size
);
767 gfc_conv_array_parameter (se
, e
, true, NULL
, NULL
, &size
);
768 se
->string_length
= fold_convert (gfc_charlen_type_node
, size
);
772 /* Generate code to store a string and its length into the
773 st_parameter_XXX structure. */
776 set_string (stmtblock_t
* block
, stmtblock_t
* postblock
, tree var
,
777 enum iofield type
, gfc_expr
* e
)
783 gfc_st_parameter_field
*p
= &st_parameter_field
[type
];
785 gfc_init_se (&se
, NULL
);
787 if (p
->param_type
== IOPARM_ptype_common
)
788 var
= fold_build3_loc (input_location
, COMPONENT_REF
,
789 st_parameter
[IOPARM_ptype_common
].type
,
790 var
, TYPE_FIELDS (TREE_TYPE (var
)), NULL_TREE
);
791 io
= fold_build3_loc (input_location
, COMPONENT_REF
, TREE_TYPE (p
->field
),
792 var
, p
->field
, NULL_TREE
);
793 len
= fold_build3_loc (input_location
, COMPONENT_REF
,
794 TREE_TYPE (p
->field_len
),
795 var
, p
->field_len
, NULL_TREE
);
797 /* Integer variable assigned a format label. */
798 if (e
->ts
.type
== BT_INTEGER
800 && e
->symtree
->n
.sym
->attr
.assign
== 1)
805 gfc_conv_label_variable (&se
, e
);
806 tmp
= GFC_DECL_STRING_LEN (se
.expr
);
807 cond
= fold_build2_loc (input_location
, LT_EXPR
, boolean_type_node
,
808 tmp
, build_int_cst (TREE_TYPE (tmp
), 0));
810 msg
= xasprintf ("Label assigned to variable '%s' (%%ld) is not a format "
811 "label", e
->symtree
->name
);
812 gfc_trans_runtime_check (true, false, cond
, &se
.pre
, &e
->where
, msg
,
813 fold_convert (long_integer_type_node
, tmp
));
816 gfc_add_modify (&se
.pre
, io
,
817 fold_convert (TREE_TYPE (io
), GFC_DECL_ASSIGN_ADDR (se
.expr
)));
818 gfc_add_modify (&se
.pre
, len
, GFC_DECL_STRING_LEN (se
.expr
));
822 /* General character. */
823 if (e
->ts
.type
== BT_CHARACTER
&& e
->rank
== 0)
824 gfc_conv_expr (&se
, e
);
825 /* Array assigned Hollerith constant or character array. */
826 else if (e
->rank
> 0 || (e
->symtree
&& e
->symtree
->n
.sym
->as
->rank
> 0))
827 gfc_convert_array_to_string (&se
, e
);
831 gfc_conv_string_parameter (&se
);
832 gfc_add_modify (&se
.pre
, io
, fold_convert (TREE_TYPE (io
), se
.expr
));
833 gfc_add_modify (&se
.pre
, len
, se
.string_length
);
836 gfc_add_block_to_block (block
, &se
.pre
);
837 gfc_add_block_to_block (postblock
, &se
.post
);
842 /* Generate code to store the character (array) and the character length
843 for an internal unit. */
846 set_internal_unit (stmtblock_t
* block
, stmtblock_t
* post_block
,
847 tree var
, gfc_expr
* e
)
854 gfc_st_parameter_field
*p
;
857 gfc_init_se (&se
, NULL
);
859 p
= &st_parameter_field
[IOPARM_dt_internal_unit
];
861 io
= fold_build3_loc (input_location
, COMPONENT_REF
, TREE_TYPE (p
->field
),
862 var
, p
->field
, NULL_TREE
);
863 len
= fold_build3_loc (input_location
, COMPONENT_REF
, TREE_TYPE (p
->field_len
),
864 var
, p
->field_len
, NULL_TREE
);
865 p
= &st_parameter_field
[IOPARM_dt_internal_unit_desc
];
866 desc
= fold_build3_loc (input_location
, COMPONENT_REF
, TREE_TYPE (p
->field
),
867 var
, p
->field
, NULL_TREE
);
869 gcc_assert (e
->ts
.type
== BT_CHARACTER
);
871 /* Character scalars. */
874 gfc_conv_expr (&se
, e
);
875 gfc_conv_string_parameter (&se
);
877 se
.expr
= build_int_cst (pchar_type_node
, 0);
880 /* Character array. */
881 else if (e
->rank
> 0)
883 if (is_subref_array (e
))
885 /* Use a temporary for components of arrays of derived types
886 or substring array references. */
887 gfc_conv_subref_array_arg (&se
, e
, 0,
888 last_dt
== READ
? INTENT_IN
: INTENT_OUT
, false);
889 tmp
= build_fold_indirect_ref_loc (input_location
,
891 se
.expr
= gfc_build_addr_expr (pchar_type_node
, tmp
);
892 tmp
= gfc_conv_descriptor_data_get (tmp
);
896 /* Return the data pointer and rank from the descriptor. */
897 gfc_conv_expr_descriptor (&se
, e
);
898 tmp
= gfc_conv_descriptor_data_get (se
.expr
);
899 se
.expr
= gfc_build_addr_expr (pchar_type_node
, se
.expr
);
905 /* The cast is needed for character substrings and the descriptor
907 gfc_add_modify (&se
.pre
, io
, fold_convert (TREE_TYPE (io
), tmp
));
908 gfc_add_modify (&se
.pre
, len
,
909 fold_convert (TREE_TYPE (len
), se
.string_length
));
910 gfc_add_modify (&se
.pre
, desc
, se
.expr
);
912 gfc_add_block_to_block (block
, &se
.pre
);
913 gfc_add_block_to_block (post_block
, &se
.post
);
917 /* Add a case to a IO-result switch. */
920 add_case (int label_value
, gfc_st_label
* label
, stmtblock_t
* body
)
925 return; /* No label, no case */
927 value
= build_int_cst (integer_type_node
, label_value
);
929 /* Make a backend label for this case. */
930 tmp
= gfc_build_label_decl (NULL_TREE
);
932 /* And the case itself. */
933 tmp
= build_case_label (value
, NULL_TREE
, tmp
);
934 gfc_add_expr_to_block (body
, tmp
);
936 /* Jump to the label. */
937 tmp
= build1_v (GOTO_EXPR
, gfc_get_label_decl (label
));
938 gfc_add_expr_to_block (body
, tmp
);
942 /* Generate a switch statement that branches to the correct I/O
943 result label. The last statement of an I/O call stores the
944 result into a variable because there is often cleanup that
945 must be done before the switch, so a temporary would have to
946 be created anyway. */
949 io_result (stmtblock_t
* block
, tree var
, gfc_st_label
* err_label
,
950 gfc_st_label
* end_label
, gfc_st_label
* eor_label
)
954 gfc_st_parameter_field
*p
= &st_parameter_field
[IOPARM_common_flags
];
956 /* If no labels are specified, ignore the result instead
957 of building an empty switch. */
958 if (err_label
== NULL
960 && eor_label
== NULL
)
963 /* Build a switch statement. */
964 gfc_start_block (&body
);
966 /* The label values here must be the same as the values
967 in the library_return enum in the runtime library */
968 add_case (1, err_label
, &body
);
969 add_case (2, end_label
, &body
);
970 add_case (3, eor_label
, &body
);
972 tmp
= gfc_finish_block (&body
);
974 var
= fold_build3_loc (input_location
, COMPONENT_REF
,
975 st_parameter
[IOPARM_ptype_common
].type
,
976 var
, TYPE_FIELDS (TREE_TYPE (var
)), NULL_TREE
);
977 rc
= fold_build3_loc (input_location
, COMPONENT_REF
, TREE_TYPE (p
->field
),
978 var
, p
->field
, NULL_TREE
);
979 rc
= fold_build2_loc (input_location
, BIT_AND_EXPR
, TREE_TYPE (rc
),
980 rc
, build_int_cst (TREE_TYPE (rc
),
981 IOPARM_common_libreturn_mask
));
983 tmp
= fold_build3_loc (input_location
, SWITCH_EXPR
, NULL_TREE
,
986 gfc_add_expr_to_block (block
, tmp
);
990 /* Store the current file and line number to variables so that if a
991 library call goes awry, we can tell the user where the problem is. */
994 set_error_locus (stmtblock_t
* block
, tree var
, locus
* where
)
997 tree str
, locus_file
;
999 gfc_st_parameter_field
*p
= &st_parameter_field
[IOPARM_common_filename
];
1001 locus_file
= fold_build3_loc (input_location
, COMPONENT_REF
,
1002 st_parameter
[IOPARM_ptype_common
].type
,
1003 var
, TYPE_FIELDS (TREE_TYPE (var
)), NULL_TREE
);
1004 locus_file
= fold_build3_loc (input_location
, COMPONENT_REF
,
1005 TREE_TYPE (p
->field
), locus_file
,
1006 p
->field
, NULL_TREE
);
1007 f
= where
->lb
->file
;
1008 str
= gfc_build_cstring_const (f
->filename
);
1010 str
= gfc_build_addr_expr (pchar_type_node
, str
);
1011 gfc_add_modify (block
, locus_file
, str
);
1013 line
= LOCATION_LINE (where
->lb
->location
);
1014 set_parameter_const (block
, var
, IOPARM_common_line
, line
);
1018 /* Translate an OPEN statement. */
1021 gfc_trans_open (gfc_code
* code
)
1023 stmtblock_t block
, post_block
;
1026 unsigned int mask
= 0;
1028 gfc_start_block (&block
);
1029 gfc_init_block (&post_block
);
1031 var
= gfc_create_var (st_parameter
[IOPARM_ptype_open
].type
, "open_parm");
1033 set_error_locus (&block
, var
, &code
->loc
);
1037 mask
|= set_string (&block
, &post_block
, var
, IOPARM_common_iomsg
,
1041 mask
|= set_parameter_ref (&block
, &post_block
, var
, IOPARM_common_iostat
,
1045 mask
|= IOPARM_common_err
;
1048 mask
|= set_string (&block
, &post_block
, var
, IOPARM_open_file
, p
->file
);
1051 mask
|= set_string (&block
, &post_block
, var
, IOPARM_open_status
,
1055 mask
|= set_string (&block
, &post_block
, var
, IOPARM_open_access
,
1059 mask
|= set_string (&block
, &post_block
, var
, IOPARM_open_form
, p
->form
);
1062 mask
|= set_parameter_value (&block
, var
, IOPARM_open_recl_in
,
1066 mask
|= set_string (&block
, &post_block
, var
, IOPARM_open_blank
,
1070 mask
|= set_string (&block
, &post_block
, var
, IOPARM_open_position
,
1074 mask
|= set_string (&block
, &post_block
, var
, IOPARM_open_action
,
1078 mask
|= set_string (&block
, &post_block
, var
, IOPARM_open_delim
,
1082 mask
|= set_string (&block
, &post_block
, var
, IOPARM_open_pad
, p
->pad
);
1085 mask
|= set_string (&block
, &post_block
, var
, IOPARM_open_decimal
,
1089 mask
|= set_string (&block
, &post_block
, var
, IOPARM_open_encoding
,
1093 mask
|= set_string (&block
, &post_block
, var
, IOPARM_open_round
, p
->round
);
1096 mask
|= set_string (&block
, &post_block
, var
, IOPARM_open_sign
, p
->sign
);
1098 if (p
->asynchronous
)
1099 mask
|= set_string (&block
, &post_block
, var
, IOPARM_open_asynchronous
,
1103 mask
|= set_string (&block
, &post_block
, var
, IOPARM_open_convert
,
1107 mask
|= set_parameter_ref (&block
, &post_block
, var
, IOPARM_open_newunit
,
1110 set_parameter_const (&block
, var
, IOPARM_common_flags
, mask
);
1113 set_parameter_value_chk (&block
, p
->iostat
, var
, IOPARM_common_unit
, p
->unit
);
1115 set_parameter_const (&block
, var
, IOPARM_common_unit
, 0);
1117 tmp
= gfc_build_addr_expr (NULL_TREE
, var
);
1118 tmp
= build_call_expr_loc (input_location
,
1119 iocall
[IOCALL_OPEN
], 1, tmp
);
1120 gfc_add_expr_to_block (&block
, tmp
);
1122 gfc_add_block_to_block (&block
, &post_block
);
1124 io_result (&block
, var
, p
->err
, NULL
, NULL
);
1126 return gfc_finish_block (&block
);
1130 /* Translate a CLOSE statement. */
1133 gfc_trans_close (gfc_code
* code
)
1135 stmtblock_t block
, post_block
;
1138 unsigned int mask
= 0;
1140 gfc_start_block (&block
);
1141 gfc_init_block (&post_block
);
1143 var
= gfc_create_var (st_parameter
[IOPARM_ptype_close
].type
, "close_parm");
1145 set_error_locus (&block
, var
, &code
->loc
);
1146 p
= code
->ext
.close
;
1149 mask
|= set_string (&block
, &post_block
, var
, IOPARM_common_iomsg
,
1153 mask
|= set_parameter_ref (&block
, &post_block
, var
, IOPARM_common_iostat
,
1157 mask
|= IOPARM_common_err
;
1160 mask
|= set_string (&block
, &post_block
, var
, IOPARM_close_status
,
1163 set_parameter_const (&block
, var
, IOPARM_common_flags
, mask
);
1166 set_parameter_value_chk (&block
, p
->iostat
, var
, IOPARM_common_unit
, p
->unit
);
1168 set_parameter_const (&block
, var
, IOPARM_common_unit
, 0);
1170 tmp
= gfc_build_addr_expr (NULL_TREE
, var
);
1171 tmp
= build_call_expr_loc (input_location
,
1172 iocall
[IOCALL_CLOSE
], 1, tmp
);
1173 gfc_add_expr_to_block (&block
, tmp
);
1175 gfc_add_block_to_block (&block
, &post_block
);
1177 io_result (&block
, var
, p
->err
, NULL
, NULL
);
1179 return gfc_finish_block (&block
);
1183 /* Common subroutine for building a file positioning statement. */
1186 build_filepos (tree function
, gfc_code
* code
)
1188 stmtblock_t block
, post_block
;
1191 unsigned int mask
= 0;
1193 p
= code
->ext
.filepos
;
1195 gfc_start_block (&block
);
1196 gfc_init_block (&post_block
);
1198 var
= gfc_create_var (st_parameter
[IOPARM_ptype_filepos
].type
,
1201 set_error_locus (&block
, var
, &code
->loc
);
1204 mask
|= set_string (&block
, &post_block
, var
, IOPARM_common_iomsg
,
1208 mask
|= set_parameter_ref (&block
, &post_block
, var
,
1209 IOPARM_common_iostat
, p
->iostat
);
1212 mask
|= IOPARM_common_err
;
1214 set_parameter_const (&block
, var
, IOPARM_common_flags
, mask
);
1217 set_parameter_value_chk (&block
, p
->iostat
, var
, IOPARM_common_unit
,
1220 set_parameter_const (&block
, var
, IOPARM_common_unit
, 0);
1222 tmp
= gfc_build_addr_expr (NULL_TREE
, var
);
1223 tmp
= build_call_expr_loc (input_location
,
1225 gfc_add_expr_to_block (&block
, tmp
);
1227 gfc_add_block_to_block (&block
, &post_block
);
1229 io_result (&block
, var
, p
->err
, NULL
, NULL
);
1231 return gfc_finish_block (&block
);
1235 /* Translate a BACKSPACE statement. */
1238 gfc_trans_backspace (gfc_code
* code
)
1240 return build_filepos (iocall
[IOCALL_BACKSPACE
], code
);
1244 /* Translate an ENDFILE statement. */
1247 gfc_trans_endfile (gfc_code
* code
)
1249 return build_filepos (iocall
[IOCALL_ENDFILE
], code
);
1253 /* Translate a REWIND statement. */
1256 gfc_trans_rewind (gfc_code
* code
)
1258 return build_filepos (iocall
[IOCALL_REWIND
], code
);
1262 /* Translate a FLUSH statement. */
1265 gfc_trans_flush (gfc_code
* code
)
1267 return build_filepos (iocall
[IOCALL_FLUSH
], code
);
1271 /* Translate the non-IOLENGTH form of an INQUIRE statement. */
1274 gfc_trans_inquire (gfc_code
* code
)
1276 stmtblock_t block
, post_block
;
1279 unsigned int mask
= 0, mask2
= 0;
1281 gfc_start_block (&block
);
1282 gfc_init_block (&post_block
);
1284 var
= gfc_create_var (st_parameter
[IOPARM_ptype_inquire
].type
,
1287 set_error_locus (&block
, var
, &code
->loc
);
1288 p
= code
->ext
.inquire
;
1291 mask
|= set_string (&block
, &post_block
, var
, IOPARM_common_iomsg
,
1295 mask
|= set_parameter_ref (&block
, &post_block
, var
, IOPARM_common_iostat
,
1299 mask
|= IOPARM_common_err
;
1302 if (p
->unit
&& p
->file
)
1303 gfc_error ("INQUIRE statement at %L cannot contain both FILE and UNIT specifiers", &code
->loc
);
1306 mask
|= set_string (&block
, &post_block
, var
, IOPARM_inquire_file
,
1310 mask
|= set_parameter_ref (&block
, &post_block
, var
, IOPARM_inquire_exist
,
1314 mask
|= set_parameter_ref (&block
, &post_block
, var
, IOPARM_inquire_opened
,
1318 mask
|= set_parameter_ref (&block
, &post_block
, var
, IOPARM_inquire_number
,
1322 mask
|= set_parameter_ref (&block
, &post_block
, var
, IOPARM_inquire_named
,
1326 mask
|= set_string (&block
, &post_block
, var
, IOPARM_inquire_name
,
1330 mask
|= set_string (&block
, &post_block
, var
, IOPARM_inquire_access
,
1334 mask
|= set_string (&block
, &post_block
, var
, IOPARM_inquire_sequential
,
1338 mask
|= set_string (&block
, &post_block
, var
, IOPARM_inquire_direct
,
1342 mask
|= set_string (&block
, &post_block
, var
, IOPARM_inquire_form
,
1346 mask
|= set_string (&block
, &post_block
, var
, IOPARM_inquire_formatted
,
1350 mask
|= set_string (&block
, &post_block
, var
, IOPARM_inquire_unformatted
,
1354 mask
|= set_parameter_ref (&block
, &post_block
, var
,
1355 IOPARM_inquire_recl_out
, p
->recl
);
1358 mask
|= set_parameter_ref (&block
, &post_block
, var
,
1359 IOPARM_inquire_nextrec
, p
->nextrec
);
1362 mask
|= set_string (&block
, &post_block
, var
, IOPARM_inquire_blank
,
1366 mask
|= set_string (&block
, &post_block
, var
, IOPARM_inquire_delim
,
1370 mask
|= set_string (&block
, &post_block
, var
, IOPARM_inquire_position
,
1374 mask
|= set_string (&block
, &post_block
, var
, IOPARM_inquire_action
,
1378 mask
|= set_string (&block
, &post_block
, var
, IOPARM_inquire_read
,
1382 mask
|= set_string (&block
, &post_block
, var
, IOPARM_inquire_write
,
1386 mask
|= set_string (&block
, &post_block
, var
, IOPARM_inquire_readwrite
,
1390 mask
|= set_string (&block
, &post_block
, var
, IOPARM_inquire_pad
,
1394 mask
|= set_string (&block
, &post_block
, var
, IOPARM_inquire_convert
,
1398 mask
|= set_parameter_ref (&block
, &post_block
, var
,
1399 IOPARM_inquire_strm_pos_out
, p
->strm_pos
);
1401 /* The second series of flags. */
1402 if (p
->asynchronous
)
1403 mask2
|= set_string (&block
, &post_block
, var
, IOPARM_inquire_asynchronous
,
1407 mask2
|= set_string (&block
, &post_block
, var
, IOPARM_inquire_decimal
,
1411 mask2
|= set_string (&block
, &post_block
, var
, IOPARM_inquire_encoding
,
1415 mask2
|= set_string (&block
, &post_block
, var
, IOPARM_inquire_round
,
1419 mask2
|= set_string (&block
, &post_block
, var
, IOPARM_inquire_sign
,
1423 mask2
|= set_parameter_ref (&block
, &post_block
, var
,
1424 IOPARM_inquire_pending
, p
->pending
);
1427 mask2
|= set_parameter_ref (&block
, &post_block
, var
, IOPARM_inquire_size
,
1431 mask2
|= set_parameter_ref (&block
, &post_block
,var
, IOPARM_inquire_id
,
1434 mask2
|= set_string (&block
, &post_block
, var
, IOPARM_inquire_iqstream
,
1438 mask
|= set_parameter_const (&block
, var
, IOPARM_inquire_flags2
, mask2
);
1440 set_parameter_const (&block
, var
, IOPARM_common_flags
, mask
);
1444 set_parameter_value (&block
, var
, IOPARM_common_unit
, p
->unit
);
1445 set_parameter_value_inquire (&block
, var
, IOPARM_common_unit
, p
->unit
);
1448 set_parameter_const (&block
, var
, IOPARM_common_unit
, 0);
1450 tmp
= gfc_build_addr_expr (NULL_TREE
, var
);
1451 tmp
= build_call_expr_loc (input_location
,
1452 iocall
[IOCALL_INQUIRE
], 1, tmp
);
1453 gfc_add_expr_to_block (&block
, tmp
);
1455 gfc_add_block_to_block (&block
, &post_block
);
1457 io_result (&block
, var
, p
->err
, NULL
, NULL
);
1459 return gfc_finish_block (&block
);
1464 gfc_trans_wait (gfc_code
* code
)
1466 stmtblock_t block
, post_block
;
1469 unsigned int mask
= 0;
1471 gfc_start_block (&block
);
1472 gfc_init_block (&post_block
);
1474 var
= gfc_create_var (st_parameter
[IOPARM_ptype_wait
].type
,
1477 set_error_locus (&block
, var
, &code
->loc
);
1480 /* Set parameters here. */
1482 mask
|= set_string (&block
, &post_block
, var
, IOPARM_common_iomsg
,
1486 mask
|= set_parameter_ref (&block
, &post_block
, var
, IOPARM_common_iostat
,
1490 mask
|= IOPARM_common_err
;
1493 mask
|= set_parameter_value (&block
, var
, IOPARM_wait_id
, p
->id
);
1495 set_parameter_const (&block
, var
, IOPARM_common_flags
, mask
);
1498 set_parameter_value_chk (&block
, p
->iostat
, var
, IOPARM_common_unit
, p
->unit
);
1500 tmp
= gfc_build_addr_expr (NULL_TREE
, var
);
1501 tmp
= build_call_expr_loc (input_location
,
1502 iocall
[IOCALL_WAIT
], 1, tmp
);
1503 gfc_add_expr_to_block (&block
, tmp
);
1505 gfc_add_block_to_block (&block
, &post_block
);
1507 io_result (&block
, var
, p
->err
, NULL
, NULL
);
1509 return gfc_finish_block (&block
);
1514 /* nml_full_name builds up the fully qualified name of a
1515 derived type component. '+' is used to denote a type extension. */
1518 nml_full_name (const char* var_name
, const char* cmp_name
, bool parent
)
1520 int full_name_length
;
1523 full_name_length
= strlen (var_name
) + strlen (cmp_name
) + 1;
1524 full_name
= XCNEWVEC (char, full_name_length
+ 1);
1525 strcpy (full_name
, var_name
);
1526 full_name
= strcat (full_name
, parent
? "+" : "%");
1527 full_name
= strcat (full_name
, cmp_name
);
1532 /* nml_get_addr_expr builds an address expression from the
1533 gfc_symbol or gfc_component backend_decl's. An offset is
1534 provided so that the address of an element of an array of
1535 derived types is returned. This is used in the runtime to
1536 determine that span of the derived type. */
1539 nml_get_addr_expr (gfc_symbol
* sym
, gfc_component
* c
,
1542 tree decl
= NULL_TREE
;
1547 sym
->attr
.referenced
= 1;
1548 decl
= gfc_get_symbol_decl (sym
);
1550 /* If this is the enclosing function declaration, use
1551 the fake result instead. */
1552 if (decl
== current_function_decl
)
1553 decl
= gfc_get_fake_result_decl (sym
, 0);
1554 else if (decl
== DECL_CONTEXT (current_function_decl
))
1555 decl
= gfc_get_fake_result_decl (sym
, 1);
1558 decl
= c
->backend_decl
;
1560 gcc_assert (decl
&& ((TREE_CODE (decl
) == FIELD_DECL
1561 || TREE_CODE (decl
) == VAR_DECL
1562 || TREE_CODE (decl
) == PARM_DECL
)
1563 || TREE_CODE (decl
) == COMPONENT_REF
));
1567 /* Build indirect reference, if dummy argument. */
1569 if (POINTER_TYPE_P (TREE_TYPE(tmp
)))
1570 tmp
= build_fold_indirect_ref_loc (input_location
, tmp
);
1572 /* Treat the component of a derived type, using base_addr for
1573 the derived type. */
1575 if (TREE_CODE (decl
) == FIELD_DECL
)
1576 tmp
= fold_build3_loc (input_location
, COMPONENT_REF
, TREE_TYPE (tmp
),
1577 base_addr
, tmp
, NULL_TREE
);
1579 if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (tmp
)))
1580 tmp
= gfc_conv_array_data (tmp
);
1583 if (!POINTER_TYPE_P (TREE_TYPE (tmp
)))
1584 tmp
= gfc_build_addr_expr (NULL_TREE
, tmp
);
1586 if (TREE_CODE (TREE_TYPE (tmp
)) == ARRAY_TYPE
)
1587 tmp
= gfc_build_array_ref (tmp
, gfc_index_zero_node
, NULL
);
1589 if (!POINTER_TYPE_P (TREE_TYPE (tmp
)))
1590 tmp
= build_fold_indirect_ref_loc (input_location
,
1594 gcc_assert (tmp
&& POINTER_TYPE_P (TREE_TYPE (tmp
)));
1600 /* For an object VAR_NAME whose base address is BASE_ADDR, generate a
1601 call to iocall[IOCALL_SET_NML_VAL]. For derived type variable, recursively
1602 generate calls to iocall[IOCALL_SET_NML_VAL] for each component. */
1604 #define IARG(i) build_int_cst (gfc_array_index_type, i)
1607 transfer_namelist_element (stmtblock_t
* block
, const char * var_name
,
1608 gfc_symbol
* sym
, gfc_component
* c
,
1611 gfc_typespec
* ts
= NULL
;
1612 gfc_array_spec
* as
= NULL
;
1613 tree addr_expr
= NULL
;
1619 tree decl
= NULL_TREE
;
1620 tree gfc_int4_type_node
= gfc_get_int_type (4);
1625 gcc_assert (sym
|| c
);
1627 /* Build the namelist object name. */
1629 string
= gfc_build_cstring_const (var_name
);
1630 string
= gfc_build_addr_expr (pchar_type_node
, string
);
1632 /* Build ts, as and data address using symbol or component. */
1634 ts
= (sym
) ? &sym
->ts
: &c
->ts
;
1635 as
= (sym
) ? sym
->as
: c
->as
;
1637 addr_expr
= nml_get_addr_expr (sym
, c
, base_addr
);
1644 decl
= (sym
) ? sym
->backend_decl
: c
->backend_decl
;
1645 if (sym
&& sym
->attr
.dummy
)
1646 decl
= build_fold_indirect_ref_loc (input_location
, decl
);
1647 dt
= TREE_TYPE (decl
);
1648 dtype
= gfc_get_dtype (dt
);
1653 dtype
= IARG (itype
<< GFC_DTYPE_TYPE_SHIFT
);
1656 /* Build up the arguments for the transfer call.
1657 The call for the scalar part transfers:
1658 (address, name, type, kind or string_length, dtype) */
1660 dt_parm_addr
= gfc_build_addr_expr (NULL_TREE
, dt_parm
);
1662 if (ts
->type
== BT_CHARACTER
)
1663 tmp
= ts
->u
.cl
->backend_decl
;
1665 tmp
= build_int_cst (gfc_charlen_type_node
, 0);
1666 tmp
= build_call_expr_loc (input_location
,
1667 iocall
[IOCALL_SET_NML_VAL
], 6,
1668 dt_parm_addr
, addr_expr
, string
,
1669 build_int_cst (gfc_int4_type_node
, ts
->kind
),
1671 gfc_add_expr_to_block (block
, tmp
);
1673 /* If the object is an array, transfer rank times:
1674 (null pointer, name, stride, lbound, ubound) */
1676 for ( n_dim
= 0 ; n_dim
< rank
; n_dim
++ )
1678 tmp
= build_call_expr_loc (input_location
,
1679 iocall
[IOCALL_SET_NML_VAL_DIM
], 5,
1681 build_int_cst (gfc_int4_type_node
, n_dim
),
1682 gfc_conv_array_stride (decl
, n_dim
),
1683 gfc_conv_array_lbound (decl
, n_dim
),
1684 gfc_conv_array_ubound (decl
, n_dim
));
1685 gfc_add_expr_to_block (block
, tmp
);
1688 if (ts
->type
== BT_DERIVED
&& ts
->u
.derived
->components
)
1692 /* Provide the RECORD_TYPE to build component references. */
1694 tree expr
= build_fold_indirect_ref_loc (input_location
,
1697 for (cmp
= ts
->u
.derived
->components
; cmp
; cmp
= cmp
->next
)
1699 char *full_name
= nml_full_name (var_name
, cmp
->name
,
1700 ts
->u
.derived
->attr
.extension
);
1701 transfer_namelist_element (block
,
1711 /* Create a data transfer statement. Not all of the fields are valid
1712 for both reading and writing, but improper use has been filtered
1716 build_dt (tree function
, gfc_code
* code
)
1718 stmtblock_t block
, post_block
, post_end_block
, post_iu_block
;
1723 unsigned int mask
= 0;
1725 gfc_start_block (&block
);
1726 gfc_init_block (&post_block
);
1727 gfc_init_block (&post_end_block
);
1728 gfc_init_block (&post_iu_block
);
1730 var
= gfc_create_var (st_parameter
[IOPARM_ptype_dt
].type
, "dt_parm");
1732 set_error_locus (&block
, var
, &code
->loc
);
1734 if (last_dt
== IOLENGTH
)
1738 inq
= code
->ext
.inquire
;
1740 /* First check that preconditions are met. */
1741 gcc_assert (inq
!= NULL
);
1742 gcc_assert (inq
->iolength
!= NULL
);
1744 /* Connect to the iolength variable. */
1745 mask
|= set_parameter_ref (&block
, &post_end_block
, var
,
1746 IOPARM_dt_iolength
, inq
->iolength
);
1752 gcc_assert (dt
!= NULL
);
1755 if (dt
&& dt
->io_unit
)
1757 if (dt
->io_unit
->ts
.type
== BT_CHARACTER
)
1759 mask
|= set_internal_unit (&block
, &post_iu_block
,
1761 set_parameter_const (&block
, var
, IOPARM_common_unit
,
1762 dt
->io_unit
->ts
.kind
== 1 ? 0 : -1);
1766 set_parameter_const (&block
, var
, IOPARM_common_unit
, 0);
1771 mask
|= set_string (&block
, &post_block
, var
, IOPARM_common_iomsg
,
1775 mask
|= set_parameter_ref (&block
, &post_end_block
, var
,
1776 IOPARM_common_iostat
, dt
->iostat
);
1779 mask
|= IOPARM_common_err
;
1782 mask
|= IOPARM_common_eor
;
1785 mask
|= IOPARM_common_end
;
1788 mask
|= set_parameter_ref (&block
, &post_end_block
, var
,
1789 IOPARM_dt_id
, dt
->id
);
1792 mask
|= set_parameter_value (&block
, var
, IOPARM_dt_pos
, dt
->pos
);
1794 if (dt
->asynchronous
)
1795 mask
|= set_string (&block
, &post_block
, var
,
1796 IOPARM_dt_asynchronous
, dt
->asynchronous
);
1799 mask
|= set_string (&block
, &post_block
, var
, IOPARM_dt_blank
,
1803 mask
|= set_string (&block
, &post_block
, var
, IOPARM_dt_decimal
,
1807 mask
|= set_string (&block
, &post_block
, var
, IOPARM_dt_delim
,
1811 mask
|= set_string (&block
, &post_block
, var
, IOPARM_dt_pad
,
1815 mask
|= set_string (&block
, &post_block
, var
, IOPARM_dt_round
,
1819 mask
|= set_string (&block
, &post_block
, var
, IOPARM_dt_sign
,
1823 mask
|= set_parameter_value (&block
, var
, IOPARM_dt_rec
, dt
->rec
);
1826 mask
|= set_string (&block
, &post_block
, var
, IOPARM_dt_advance
,
1829 if (dt
->format_expr
)
1830 mask
|= set_string (&block
, &post_end_block
, var
, IOPARM_dt_format
,
1833 if (dt
->format_label
)
1835 if (dt
->format_label
== &format_asterisk
)
1836 mask
|= IOPARM_dt_list_format
;
1838 mask
|= set_string (&block
, &post_block
, var
, IOPARM_dt_format
,
1839 dt
->format_label
->format
);
1843 mask
|= set_parameter_ref (&block
, &post_end_block
, var
,
1844 IOPARM_dt_size
, dt
->size
);
1848 if (dt
->format_expr
|| dt
->format_label
)
1849 gfc_internal_error ("build_dt: format with namelist");
1851 nmlname
= gfc_get_character_expr (gfc_default_character_kind
, NULL
,
1853 strlen (dt
->namelist
->name
));
1855 mask
|= set_string (&block
, &post_block
, var
, IOPARM_dt_namelist_name
,
1858 gfc_free_expr (nmlname
);
1860 if (last_dt
== READ
)
1861 mask
|= IOPARM_dt_namelist_read_mode
;
1863 set_parameter_const (&block
, var
, IOPARM_common_flags
, mask
);
1867 for (nml
= dt
->namelist
->namelist
; nml
; nml
= nml
->next
)
1868 transfer_namelist_element (&block
, nml
->sym
->name
, nml
->sym
,
1872 set_parameter_const (&block
, var
, IOPARM_common_flags
, mask
);
1874 if (dt
->io_unit
&& dt
->io_unit
->ts
.type
== BT_INTEGER
)
1875 set_parameter_value_chk (&block
, dt
->iostat
, var
,
1876 IOPARM_common_unit
, dt
->io_unit
);
1879 set_parameter_const (&block
, var
, IOPARM_common_flags
, mask
);
1881 tmp
= gfc_build_addr_expr (NULL_TREE
, var
);
1882 tmp
= build_call_expr_loc (UNKNOWN_LOCATION
,
1884 gfc_add_expr_to_block (&block
, tmp
);
1886 gfc_add_block_to_block (&block
, &post_block
);
1889 dt_post_end_block
= &post_end_block
;
1891 /* Set implied do loop exit condition. */
1892 if (last_dt
== READ
|| last_dt
== WRITE
)
1894 gfc_st_parameter_field
*p
= &st_parameter_field
[IOPARM_common_flags
];
1896 tmp
= fold_build3_loc (input_location
, COMPONENT_REF
,
1897 st_parameter
[IOPARM_ptype_common
].type
,
1898 dt_parm
, TYPE_FIELDS (TREE_TYPE (dt_parm
)),
1900 tmp
= fold_build3_loc (input_location
, COMPONENT_REF
,
1901 TREE_TYPE (p
->field
), tmp
, p
->field
, NULL_TREE
);
1902 tmp
= fold_build2_loc (input_location
, BIT_AND_EXPR
, TREE_TYPE (tmp
),
1903 tmp
, build_int_cst (TREE_TYPE (tmp
),
1904 IOPARM_common_libreturn_mask
));
1909 gfc_add_expr_to_block (&block
, gfc_trans_code_cond (code
->block
->next
, tmp
));
1911 gfc_add_block_to_block (&block
, &post_iu_block
);
1914 dt_post_end_block
= NULL
;
1916 return gfc_finish_block (&block
);
1920 /* Translate the IOLENGTH form of an INQUIRE statement. We treat
1921 this as a third sort of data transfer statement, except that
1922 lengths are summed instead of actually transferring any data. */
1925 gfc_trans_iolength (gfc_code
* code
)
1928 return build_dt (iocall
[IOCALL_IOLENGTH
], code
);
1932 /* Translate a READ statement. */
1935 gfc_trans_read (gfc_code
* code
)
1938 return build_dt (iocall
[IOCALL_READ
], code
);
1942 /* Translate a WRITE statement */
1945 gfc_trans_write (gfc_code
* code
)
1948 return build_dt (iocall
[IOCALL_WRITE
], code
);
1952 /* Finish a data transfer statement. */
1955 gfc_trans_dt_end (gfc_code
* code
)
1960 gfc_init_block (&block
);
1965 function
= iocall
[IOCALL_READ_DONE
];
1969 function
= iocall
[IOCALL_WRITE_DONE
];
1973 function
= iocall
[IOCALL_IOLENGTH_DONE
];
1980 tmp
= gfc_build_addr_expr (NULL_TREE
, dt_parm
);
1981 tmp
= build_call_expr_loc (input_location
,
1983 gfc_add_expr_to_block (&block
, tmp
);
1984 gfc_add_block_to_block (&block
, dt_post_end_block
);
1985 gfc_init_block (dt_post_end_block
);
1987 if (last_dt
!= IOLENGTH
)
1989 gcc_assert (code
->ext
.dt
!= NULL
);
1990 io_result (&block
, dt_parm
, code
->ext
.dt
->err
,
1991 code
->ext
.dt
->end
, code
->ext
.dt
->eor
);
1994 return gfc_finish_block (&block
);
1998 transfer_expr (gfc_se
* se
, gfc_typespec
* ts
, tree addr_expr
, gfc_code
* code
);
2000 /* Given an array field in a derived type variable, generate the code
2001 for the loop that iterates over array elements, and the code that
2002 accesses those array elements. Use transfer_expr to generate code
2003 for transferring that element. Because elements may also be
2004 derived types, transfer_expr and transfer_array_component are mutually
2008 transfer_array_component (tree expr
, gfc_component
* cm
, locus
* where
)
2017 gfc_array_info
*ss_array
;
2019 gfc_start_block (&block
);
2020 gfc_init_se (&se
, NULL
);
2022 /* Create and initialize Scalarization Status. Unlike in
2023 gfc_trans_transfer, we can't simply use gfc_walk_expr to take
2024 care of this task, because we don't have a gfc_expr at hand.
2025 Build one manually, as in gfc_trans_subarray_assign. */
2027 ss
= gfc_get_array_ss (gfc_ss_terminator
, NULL
, cm
->as
->rank
,
2029 ss_array
= &ss
->info
->data
.array
;
2030 ss_array
->shape
= gfc_get_shape (cm
->as
->rank
);
2031 ss_array
->descriptor
= expr
;
2032 ss_array
->data
= gfc_conv_array_data (expr
);
2033 ss_array
->offset
= gfc_conv_array_offset (expr
);
2034 for (n
= 0; n
< cm
->as
->rank
; n
++)
2036 ss_array
->start
[n
] = gfc_conv_array_lbound (expr
, n
);
2037 ss_array
->stride
[n
] = gfc_index_one_node
;
2039 mpz_init (ss_array
->shape
[n
]);
2040 mpz_sub (ss_array
->shape
[n
], cm
->as
->upper
[n
]->value
.integer
,
2041 cm
->as
->lower
[n
]->value
.integer
);
2042 mpz_add_ui (ss_array
->shape
[n
], ss_array
->shape
[n
], 1);
2045 /* Once we got ss, we use scalarizer to create the loop. */
2047 gfc_init_loopinfo (&loop
);
2048 gfc_add_ss_to_loop (&loop
, ss
);
2049 gfc_conv_ss_startstride (&loop
);
2050 gfc_conv_loop_setup (&loop
, where
);
2051 gfc_mark_ss_chain_used (ss
, 1);
2052 gfc_start_scalarized_body (&loop
, &body
);
2054 gfc_copy_loopinfo_to_se (&se
, &loop
);
2057 /* gfc_conv_tmp_array_ref assumes that se.expr contains the array. */
2059 gfc_conv_tmp_array_ref (&se
);
2061 /* Now se.expr contains an element of the array. Take the address and pass
2062 it to the IO routines. */
2063 tmp
= gfc_build_addr_expr (NULL_TREE
, se
.expr
);
2064 transfer_expr (&se
, &cm
->ts
, tmp
, NULL
);
2066 /* We are done now with the loop body. Wrap up the scalarizer and
2069 gfc_add_block_to_block (&body
, &se
.pre
);
2070 gfc_add_block_to_block (&body
, &se
.post
);
2072 gfc_trans_scalarizing_loops (&loop
, &body
);
2074 gfc_add_block_to_block (&block
, &loop
.pre
);
2075 gfc_add_block_to_block (&block
, &loop
.post
);
2077 gcc_assert (ss_array
->shape
!= NULL
);
2078 gfc_free_shape (&ss_array
->shape
, cm
->as
->rank
);
2079 gfc_cleanup_loop (&loop
);
2081 return gfc_finish_block (&block
);
2084 /* Generate the call for a scalar transfer node. */
2087 transfer_expr (gfc_se
* se
, gfc_typespec
* ts
, tree addr_expr
, gfc_code
* code
)
2089 tree tmp
, function
, arg2
, arg3
, field
, expr
;
2093 /* It is possible to get a C_NULL_PTR or C_NULL_FUNPTR expression here if
2094 the user says something like: print *, 'c_null_ptr: ', c_null_ptr
2095 We need to translate the expression to a constant if it's either
2096 C_NULL_PTR or C_NULL_FUNPTR. We could also get a user variable of
2097 type C_PTR or C_FUNPTR, in which case the ts->type may no longer be
2098 BT_DERIVED (could have been changed by gfc_conv_expr). */
2099 if ((ts
->type
== BT_DERIVED
|| ts
->type
== BT_INTEGER
)
2100 && ts
->u
.derived
!= NULL
2101 && (ts
->is_iso_c
== 1 || ts
->u
.derived
->ts
.is_iso_c
== 1))
2103 ts
->type
= BT_INTEGER
;
2104 ts
->kind
= gfc_index_integer_kind
;
2115 arg2
= build_int_cst (integer_type_node
, kind
);
2116 if (last_dt
== READ
)
2117 function
= iocall
[IOCALL_X_INTEGER
];
2119 function
= iocall
[IOCALL_X_INTEGER_WRITE
];
2124 arg2
= build_int_cst (integer_type_node
, kind
);
2125 if (last_dt
== READ
)
2127 if (gfc_real16_is_float128
&& ts
->kind
== 16)
2128 function
= iocall
[IOCALL_X_REAL128
];
2130 function
= iocall
[IOCALL_X_REAL
];
2134 if (gfc_real16_is_float128
&& ts
->kind
== 16)
2135 function
= iocall
[IOCALL_X_REAL128_WRITE
];
2137 function
= iocall
[IOCALL_X_REAL_WRITE
];
2143 arg2
= build_int_cst (integer_type_node
, kind
);
2144 if (last_dt
== READ
)
2146 if (gfc_real16_is_float128
&& ts
->kind
== 16)
2147 function
= iocall
[IOCALL_X_COMPLEX128
];
2149 function
= iocall
[IOCALL_X_COMPLEX
];
2153 if (gfc_real16_is_float128
&& ts
->kind
== 16)
2154 function
= iocall
[IOCALL_X_COMPLEX128_WRITE
];
2156 function
= iocall
[IOCALL_X_COMPLEX_WRITE
];
2162 arg2
= build_int_cst (integer_type_node
, kind
);
2163 if (last_dt
== READ
)
2164 function
= iocall
[IOCALL_X_LOGICAL
];
2166 function
= iocall
[IOCALL_X_LOGICAL_WRITE
];
2173 if (se
->string_length
)
2174 arg2
= se
->string_length
;
2177 tmp
= build_fold_indirect_ref_loc (input_location
,
2179 gcc_assert (TREE_CODE (TREE_TYPE (tmp
)) == ARRAY_TYPE
);
2180 arg2
= TYPE_MAX_VALUE (TYPE_DOMAIN (TREE_TYPE (tmp
)));
2181 arg2
= fold_convert (gfc_charlen_type_node
, arg2
);
2183 arg3
= build_int_cst (integer_type_node
, kind
);
2184 if (last_dt
== READ
)
2185 function
= iocall
[IOCALL_X_CHARACTER_WIDE
];
2187 function
= iocall
[IOCALL_X_CHARACTER_WIDE_WRITE
];
2189 tmp
= gfc_build_addr_expr (NULL_TREE
, dt_parm
);
2190 tmp
= build_call_expr_loc (input_location
,
2191 function
, 4, tmp
, addr_expr
, arg2
, arg3
);
2192 gfc_add_expr_to_block (&se
->pre
, tmp
);
2193 gfc_add_block_to_block (&se
->pre
, &se
->post
);
2198 if (se
->string_length
)
2199 arg2
= se
->string_length
;
2202 tmp
= build_fold_indirect_ref_loc (input_location
,
2204 gcc_assert (TREE_CODE (TREE_TYPE (tmp
)) == ARRAY_TYPE
);
2205 arg2
= TYPE_MAX_VALUE (TYPE_DOMAIN (TREE_TYPE (tmp
)));
2207 if (last_dt
== READ
)
2208 function
= iocall
[IOCALL_X_CHARACTER
];
2210 function
= iocall
[IOCALL_X_CHARACTER_WRITE
];
2215 if (ts
->u
.derived
->components
== NULL
)
2218 /* Recurse into the elements of the derived type. */
2219 expr
= gfc_evaluate_now (addr_expr
, &se
->pre
);
2220 expr
= build_fold_indirect_ref_loc (input_location
,
2223 /* Make sure that the derived type has been built. An external
2224 function, if only referenced in an io statement, requires this
2225 check (see PR58771). */
2226 if (ts
->u
.derived
->backend_decl
== NULL_TREE
)
2227 (void) gfc_typenode_for_spec (ts
);
2229 for (c
= ts
->u
.derived
->components
; c
; c
= c
->next
)
2231 field
= c
->backend_decl
;
2232 gcc_assert (field
&& TREE_CODE (field
) == FIELD_DECL
);
2234 tmp
= fold_build3_loc (UNKNOWN_LOCATION
,
2235 COMPONENT_REF
, TREE_TYPE (field
),
2236 expr
, field
, NULL_TREE
);
2238 if (c
->attr
.dimension
)
2240 tmp
= transfer_array_component (tmp
, c
, & code
->loc
);
2241 gfc_add_expr_to_block (&se
->pre
, tmp
);
2245 if (!c
->attr
.pointer
)
2246 tmp
= gfc_build_addr_expr (NULL_TREE
, tmp
);
2247 transfer_expr (se
, &c
->ts
, tmp
, code
);
2253 gfc_internal_error ("Bad IO basetype (%d)", ts
->type
);
2256 tmp
= gfc_build_addr_expr (NULL_TREE
, dt_parm
);
2257 tmp
= build_call_expr_loc (input_location
,
2258 function
, 3, tmp
, addr_expr
, arg2
);
2259 gfc_add_expr_to_block (&se
->pre
, tmp
);
2260 gfc_add_block_to_block (&se
->pre
, &se
->post
);
2265 /* Generate a call to pass an array descriptor to the IO library. The
2266 array should be of one of the intrinsic types. */
2269 transfer_array_desc (gfc_se
* se
, gfc_typespec
* ts
, tree addr_expr
)
2271 tree tmp
, charlen_arg
, kind_arg
, io_call
;
2273 if (ts
->type
== BT_CHARACTER
)
2274 charlen_arg
= se
->string_length
;
2276 charlen_arg
= build_int_cst (gfc_charlen_type_node
, 0);
2278 kind_arg
= build_int_cst (integer_type_node
, ts
->kind
);
2280 tmp
= gfc_build_addr_expr (NULL_TREE
, dt_parm
);
2281 if (last_dt
== READ
)
2282 io_call
= iocall
[IOCALL_X_ARRAY
];
2284 io_call
= iocall
[IOCALL_X_ARRAY_WRITE
];
2286 tmp
= build_call_expr_loc (UNKNOWN_LOCATION
,
2288 tmp
, addr_expr
, kind_arg
, charlen_arg
);
2289 gfc_add_expr_to_block (&se
->pre
, tmp
);
2290 gfc_add_block_to_block (&se
->pre
, &se
->post
);
2294 /* gfc_trans_transfer()-- Translate a TRANSFER code node */
2297 gfc_trans_transfer (gfc_code
* code
)
2299 stmtblock_t block
, body
;
2308 gfc_start_block (&block
);
2309 gfc_init_block (&body
);
2313 gfc_init_se (&se
, NULL
);
2315 if (expr
->rank
== 0)
2317 /* Transfer a scalar value. */
2318 gfc_conv_expr_reference (&se
, expr
);
2319 transfer_expr (&se
, &expr
->ts
, se
.expr
, code
);
2323 /* Transfer an array. If it is an array of an intrinsic
2324 type, pass the descriptor to the library. Otherwise
2325 scalarize the transfer. */
2326 if (expr
->ref
&& !gfc_is_proc_ptr_comp (expr
))
2328 for (ref
= expr
->ref
; ref
&& ref
->type
!= REF_ARRAY
;
2330 gcc_assert (ref
&& ref
->type
== REF_ARRAY
);
2333 if (expr
->ts
.type
!= BT_DERIVED
2334 && ref
&& ref
->next
== NULL
2335 && !is_subref_array (expr
))
2337 bool seen_vector
= false;
2339 if (ref
&& ref
->u
.ar
.type
== AR_SECTION
)
2341 for (n
= 0; n
< ref
->u
.ar
.dimen
; n
++)
2342 if (ref
->u
.ar
.dimen_type
[n
] == DIMEN_VECTOR
)
2349 if (seen_vector
&& last_dt
== READ
)
2351 /* Create a temp, read to that and copy it back. */
2352 gfc_conv_subref_array_arg (&se
, expr
, 0, INTENT_OUT
, false);
2357 /* Get the descriptor. */
2358 gfc_conv_expr_descriptor (&se
, expr
);
2359 tmp
= gfc_build_addr_expr (NULL_TREE
, se
.expr
);
2362 transfer_array_desc (&se
, &expr
->ts
, tmp
);
2363 goto finish_block_label
;
2366 /* Initialize the scalarizer. */
2367 ss
= gfc_walk_expr (expr
);
2368 gfc_init_loopinfo (&loop
);
2369 gfc_add_ss_to_loop (&loop
, ss
);
2371 /* Initialize the loop. */
2372 gfc_conv_ss_startstride (&loop
);
2373 gfc_conv_loop_setup (&loop
, &code
->expr1
->where
);
2375 /* The main loop body. */
2376 gfc_mark_ss_chain_used (ss
, 1);
2377 gfc_start_scalarized_body (&loop
, &body
);
2379 gfc_copy_loopinfo_to_se (&se
, &loop
);
2382 gfc_conv_expr_reference (&se
, expr
);
2383 transfer_expr (&se
, &expr
->ts
, se
.expr
, code
);
2388 gfc_add_block_to_block (&body
, &se
.pre
);
2389 gfc_add_block_to_block (&body
, &se
.post
);
2392 tmp
= gfc_finish_block (&body
);
2395 gcc_assert (expr
->rank
!= 0);
2396 gcc_assert (se
.ss
== gfc_ss_terminator
);
2397 gfc_trans_scalarizing_loops (&loop
, &body
);
2399 gfc_add_block_to_block (&loop
.pre
, &loop
.post
);
2400 tmp
= gfc_finish_block (&loop
.pre
);
2401 gfc_cleanup_loop (&loop
);
2404 gfc_add_expr_to_block (&block
, tmp
);
2406 return gfc_finish_block (&block
);
2409 #include "gt-fortran-trans-io.h"