2015-12-18 Paul Thomas <pault@gcc.gnu.org>
[official-gcc.git] / gcc / fortran / trans-io.c
blobd126b27f561f18139fab4af1317dd0a2b1d4edf7
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
10 version.
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
15 for more details.
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/>. */
22 #include "config.h"
23 #include "system.h"
24 #include "coretypes.h"
25 #include "tree.h"
26 #include "gfortran.h"
27 #include "trans.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. */
38 enum ioparam_type
40 IOPARM_ptype_common,
41 IOPARM_ptype_open,
42 IOPARM_ptype_close,
43 IOPARM_ptype_filepos,
44 IOPARM_ptype_inquire,
45 IOPARM_ptype_dt,
46 IOPARM_ptype_wait,
47 IOPARM_ptype_num
50 enum iofield_type
52 IOPARM_type_int4,
53 IOPARM_type_intio,
54 IOPARM_type_pint4,
55 IOPARM_type_pintio,
56 IOPARM_type_pchar,
57 IOPARM_type_parray,
58 IOPARM_type_pad,
59 IOPARM_type_char1,
60 IOPARM_type_char2,
61 IOPARM_type_common,
62 IOPARM_type_num
65 typedef struct GTY(()) gfc_st_parameter_field {
66 const char *name;
67 unsigned int mask;
68 enum ioparam_type param_type;
69 enum iofield_type type;
70 tree field;
71 tree field_len;
73 gfc_st_parameter_field;
75 typedef struct GTY(()) gfc_st_parameter {
76 const char *name;
77 tree type;
79 gfc_st_parameter;
81 enum iofield
83 #define IOPARM(param_type, name, mask, type) IOPARM_##param_type##_##name,
84 #include "ioparm.def"
85 #undef IOPARM
86 IOPARM_field_num
89 static GTY(()) gfc_st_parameter st_parameter[] =
91 { "common", NULL },
92 { "open", NULL },
93 { "close", NULL },
94 { "filepos", NULL },
95 { "inquire", NULL },
96 { "dt", NULL },
97 { "wait", NULL }
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"
105 #undef IOPARM
106 { NULL, 0, (enum ioparam_type) 0, (enum iofield_type) 0, NULL, NULL }
109 /* Library I/O subroutines */
111 enum iocall
113 IOCALL_READ,
114 IOCALL_READ_DONE,
115 IOCALL_WRITE,
116 IOCALL_WRITE_DONE,
117 IOCALL_X_INTEGER,
118 IOCALL_X_INTEGER_WRITE,
119 IOCALL_X_LOGICAL,
120 IOCALL_X_LOGICAL_WRITE,
121 IOCALL_X_CHARACTER,
122 IOCALL_X_CHARACTER_WRITE,
123 IOCALL_X_CHARACTER_WIDE,
124 IOCALL_X_CHARACTER_WIDE_WRITE,
125 IOCALL_X_REAL,
126 IOCALL_X_REAL_WRITE,
127 IOCALL_X_COMPLEX,
128 IOCALL_X_COMPLEX_WRITE,
129 IOCALL_X_REAL128,
130 IOCALL_X_REAL128_WRITE,
131 IOCALL_X_COMPLEX128,
132 IOCALL_X_COMPLEX128_WRITE,
133 IOCALL_X_ARRAY,
134 IOCALL_X_ARRAY_WRITE,
135 IOCALL_OPEN,
136 IOCALL_CLOSE,
137 IOCALL_INQUIRE,
138 IOCALL_IOLENGTH,
139 IOCALL_IOLENGTH_DONE,
140 IOCALL_REWIND,
141 IOCALL_BACKSPACE,
142 IOCALL_ENDFILE,
143 IOCALL_FLUSH,
144 IOCALL_SET_NML_VAL,
145 IOCALL_SET_NML_VAL_DIM,
146 IOCALL_WAIT,
147 IOCALL_NUM
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;
162 static void
163 gfc_build_st_parameter (enum ioparam_type ptype, tree *types)
165 unsigned int type;
166 gfc_st_parameter_field *p;
167 char name[64];
168 size_t len;
169 tree t = make_node (RECORD_TYPE);
170 tree *chain = NULL;
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,
176 len + 1);
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)
181 switch (p->type)
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);
192 break;
193 case IOPARM_type_char1:
194 p->field = gfc_add_field_to_struct (t, get_identifier (p->name),
195 pchar_type_node, &chain);
196 /* FALLTHROUGH */
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,
204 &chain);
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);
208 break;
209 case IOPARM_type_common:
210 p->field
211 = gfc_add_field_to_struct (t,
212 get_identifier (p->name),
213 st_parameter[IOPARM_ptype_common].type,
214 &chain);
215 break;
216 case IOPARM_type_num:
217 gcc_unreachable ();
220 gfc_finish_type (t);
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. */
232 static void
233 gfc_trans_io_runtime_check (bool has_iostat, tree cond, tree var,
234 int error_code, const char * msgid,
235 stmtblock_t * pblock)
237 stmtblock_t block;
238 tree body;
239 tree tmp;
240 tree arg1, arg2, arg3;
241 char *message;
243 if (integer_zerop (cond))
244 return;
246 /* The code to generate the error. */
247 gfc_start_block (&block);
249 if (has_iostat)
250 gfc_add_expr_to_block (&block, build_predict_expr (PRED_FORTRAN_FAIL_IO,
251 NOT_TAKEN));
252 else
253 gfc_add_expr_to_block (&block, build_predict_expr (PRED_NORETURN,
254 NOT_TAKEN));
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));
263 free (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);
276 else
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. */
286 void
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;
293 unsigned int ptype;
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. */
481 static unsigned int
482 set_parameter_const (stmtblock_t *block, tree var, enum iofield type,
483 unsigned int val)
485 tree tmp;
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));
495 return p->mask;
499 /* Generate code to store a non-string I/O parameter into the
500 st_parameter_XXX structure. This is a pass by value. */
502 static unsigned int
503 set_parameter_value (stmtblock_t *block, tree var, enum iofield type,
504 gfc_expr *e)
506 gfc_se se;
507 tree tmp;
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);
525 return p->mask;
529 /* Similar to set_parameter_value except generate runtime
530 error checks. */
532 static unsigned int
533 set_parameter_value_chk (stmtblock_t *block, bool has_iostat, tree var,
534 enum iofield type, gfc_expr *e)
536 gfc_se se;
537 tree tmp;
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)
547 tree cond, val;
548 int i;
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,
557 se.expr,
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",
561 &se.pre);
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,
566 se.expr,
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",
570 &se.pre);
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);
584 return p->mask;
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. */
592 static unsigned int
593 set_parameter_value_inquire (stmtblock_t *block, tree var,
594 enum iofield type, gfc_expr *e)
596 gfc_se se;
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;
609 int i;
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,
617 se.expr,
618 fold_convert (TREE_TYPE (se.expr),
619 integer_zero_node));
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,
623 se.expr,
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,
636 GFC_INVALID_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);
648 return p->mask;
652 /* Generate code to store a non-string I/O parameter into the
653 st_parameter_XXX structure. This is pass by reference. */
655 static unsigned int
656 set_parameter_ref (stmtblock_t *block, stmtblock_t *postblock,
657 tree var, enum iofield type, gfc_expr *e)
659 gfc_se se;
660 tree tmp, addr;
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));
680 else
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);
707 return p->mask;
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
714 the array. */
716 static void
717 gfc_convert_array_to_string (gfc_se * se, gfc_expr * e)
719 tree size;
721 if (e->rank == 0)
723 tree type, array, tmp;
724 gfc_symbol *sym;
725 int rank;
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);
739 else
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,
749 gfc_index_one_node);
750 size = fold_build2_loc (input_location, MULT_EXPR,
751 gfc_array_index_type, tmp, size);
753 gcc_assert (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);
764 return;
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. */
775 static unsigned int
776 set_string (stmtblock_t * block, stmtblock_t * postblock, tree var,
777 enum iofield type, gfc_expr * e)
779 gfc_se se;
780 tree tmp;
781 tree io;
782 tree len;
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
799 && e->rank == 0
800 && e->symtree->n.sym->attr.assign == 1)
802 char * msg;
803 tree cond;
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));
814 free (msg);
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));
820 else
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);
828 else
829 gcc_unreachable ();
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);
838 return p->mask;
842 /* Generate code to store the character (array) and the character length
843 for an internal unit. */
845 static unsigned int
846 set_internal_unit (stmtblock_t * block, stmtblock_t * post_block,
847 tree var, gfc_expr * e)
849 gfc_se se;
850 tree io;
851 tree len;
852 tree desc;
853 tree tmp;
854 gfc_st_parameter_field *p;
855 unsigned int mask;
857 gfc_init_se (&se, NULL);
859 p = &st_parameter_field[IOPARM_dt_internal_unit];
860 mask = p->mask;
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. */
872 if (e->rank == 0)
874 gfc_conv_expr (&se, e);
875 gfc_conv_string_parameter (&se);
876 tmp = se.expr;
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,
890 se.expr);
891 se.expr = gfc_build_addr_expr (pchar_type_node, tmp);
892 tmp = gfc_conv_descriptor_data_get (tmp);
894 else
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);
902 else
903 gcc_unreachable ();
905 /* The cast is needed for character substrings and the descriptor
906 data. */
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);
914 return mask;
917 /* Add a case to a IO-result switch. */
919 static void
920 add_case (int label_value, gfc_st_label * label, stmtblock_t * body)
922 tree tmp, value;
924 if (label == NULL)
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. */
948 static void
949 io_result (stmtblock_t * block, tree var, gfc_st_label * err_label,
950 gfc_st_label * end_label, gfc_st_label * eor_label)
952 stmtblock_t body;
953 tree tmp, rc;
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
959 && end_label == NULL
960 && eor_label == NULL)
961 return;
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,
984 rc, tmp, 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. */
993 static void
994 set_error_locus (stmtblock_t * block, tree var, locus * where)
996 gfc_file *f;
997 tree str, locus_file;
998 int line;
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. */
1020 tree
1021 gfc_trans_open (gfc_code * code)
1023 stmtblock_t block, post_block;
1024 gfc_open *p;
1025 tree tmp, var;
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);
1034 p = code->ext.open;
1036 if (p->iomsg)
1037 mask |= set_string (&block, &post_block, var, IOPARM_common_iomsg,
1038 p->iomsg);
1040 if (p->iostat)
1041 mask |= set_parameter_ref (&block, &post_block, var, IOPARM_common_iostat,
1042 p->iostat);
1044 if (p->err)
1045 mask |= IOPARM_common_err;
1047 if (p->file)
1048 mask |= set_string (&block, &post_block, var, IOPARM_open_file, p->file);
1050 if (p->status)
1051 mask |= set_string (&block, &post_block, var, IOPARM_open_status,
1052 p->status);
1054 if (p->access)
1055 mask |= set_string (&block, &post_block, var, IOPARM_open_access,
1056 p->access);
1058 if (p->form)
1059 mask |= set_string (&block, &post_block, var, IOPARM_open_form, p->form);
1061 if (p->recl)
1062 mask |= set_parameter_value (&block, var, IOPARM_open_recl_in,
1063 p->recl);
1065 if (p->blank)
1066 mask |= set_string (&block, &post_block, var, IOPARM_open_blank,
1067 p->blank);
1069 if (p->position)
1070 mask |= set_string (&block, &post_block, var, IOPARM_open_position,
1071 p->position);
1073 if (p->action)
1074 mask |= set_string (&block, &post_block, var, IOPARM_open_action,
1075 p->action);
1077 if (p->delim)
1078 mask |= set_string (&block, &post_block, var, IOPARM_open_delim,
1079 p->delim);
1081 if (p->pad)
1082 mask |= set_string (&block, &post_block, var, IOPARM_open_pad, p->pad);
1084 if (p->decimal)
1085 mask |= set_string (&block, &post_block, var, IOPARM_open_decimal,
1086 p->decimal);
1088 if (p->encoding)
1089 mask |= set_string (&block, &post_block, var, IOPARM_open_encoding,
1090 p->encoding);
1092 if (p->round)
1093 mask |= set_string (&block, &post_block, var, IOPARM_open_round, p->round);
1095 if (p->sign)
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,
1100 p->asynchronous);
1102 if (p->convert)
1103 mask |= set_string (&block, &post_block, var, IOPARM_open_convert,
1104 p->convert);
1106 if (p->newunit)
1107 mask |= set_parameter_ref (&block, &post_block, var, IOPARM_open_newunit,
1108 p->newunit);
1110 set_parameter_const (&block, var, IOPARM_common_flags, mask);
1112 if (p->unit)
1113 set_parameter_value_chk (&block, p->iostat, var, IOPARM_common_unit, p->unit);
1114 else
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. */
1132 tree
1133 gfc_trans_close (gfc_code * code)
1135 stmtblock_t block, post_block;
1136 gfc_close *p;
1137 tree tmp, var;
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;
1148 if (p->iomsg)
1149 mask |= set_string (&block, &post_block, var, IOPARM_common_iomsg,
1150 p->iomsg);
1152 if (p->iostat)
1153 mask |= set_parameter_ref (&block, &post_block, var, IOPARM_common_iostat,
1154 p->iostat);
1156 if (p->err)
1157 mask |= IOPARM_common_err;
1159 if (p->status)
1160 mask |= set_string (&block, &post_block, var, IOPARM_close_status,
1161 p->status);
1163 set_parameter_const (&block, var, IOPARM_common_flags, mask);
1165 if (p->unit)
1166 set_parameter_value_chk (&block, p->iostat, var, IOPARM_common_unit, p->unit);
1167 else
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. */
1185 static tree
1186 build_filepos (tree function, gfc_code * code)
1188 stmtblock_t block, post_block;
1189 gfc_filepos *p;
1190 tree tmp, var;
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,
1199 "filepos_parm");
1201 set_error_locus (&block, var, &code->loc);
1203 if (p->iomsg)
1204 mask |= set_string (&block, &post_block, var, IOPARM_common_iomsg,
1205 p->iomsg);
1207 if (p->iostat)
1208 mask |= set_parameter_ref (&block, &post_block, var,
1209 IOPARM_common_iostat, p->iostat);
1211 if (p->err)
1212 mask |= IOPARM_common_err;
1214 set_parameter_const (&block, var, IOPARM_common_flags, mask);
1216 if (p->unit)
1217 set_parameter_value_chk (&block, p->iostat, var, IOPARM_common_unit,
1218 p->unit);
1219 else
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,
1224 function, 1, tmp);
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. */
1237 tree
1238 gfc_trans_backspace (gfc_code * code)
1240 return build_filepos (iocall[IOCALL_BACKSPACE], code);
1244 /* Translate an ENDFILE statement. */
1246 tree
1247 gfc_trans_endfile (gfc_code * code)
1249 return build_filepos (iocall[IOCALL_ENDFILE], code);
1253 /* Translate a REWIND statement. */
1255 tree
1256 gfc_trans_rewind (gfc_code * code)
1258 return build_filepos (iocall[IOCALL_REWIND], code);
1262 /* Translate a FLUSH statement. */
1264 tree
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. */
1273 tree
1274 gfc_trans_inquire (gfc_code * code)
1276 stmtblock_t block, post_block;
1277 gfc_inquire *p;
1278 tree tmp, var;
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,
1285 "inquire_parm");
1287 set_error_locus (&block, var, &code->loc);
1288 p = code->ext.inquire;
1290 if (p->iomsg)
1291 mask |= set_string (&block, &post_block, var, IOPARM_common_iomsg,
1292 p->iomsg);
1294 if (p->iostat)
1295 mask |= set_parameter_ref (&block, &post_block, var, IOPARM_common_iostat,
1296 p->iostat);
1298 if (p->err)
1299 mask |= IOPARM_common_err;
1301 /* Sanity check. */
1302 if (p->unit && p->file)
1303 gfc_error ("INQUIRE statement at %L cannot contain both FILE and UNIT specifiers", &code->loc);
1305 if (p->file)
1306 mask |= set_string (&block, &post_block, var, IOPARM_inquire_file,
1307 p->file);
1309 if (p->exist)
1310 mask |= set_parameter_ref (&block, &post_block, var, IOPARM_inquire_exist,
1311 p->exist);
1313 if (p->opened)
1314 mask |= set_parameter_ref (&block, &post_block, var, IOPARM_inquire_opened,
1315 p->opened);
1317 if (p->number)
1318 mask |= set_parameter_ref (&block, &post_block, var, IOPARM_inquire_number,
1319 p->number);
1321 if (p->named)
1322 mask |= set_parameter_ref (&block, &post_block, var, IOPARM_inquire_named,
1323 p->named);
1325 if (p->name)
1326 mask |= set_string (&block, &post_block, var, IOPARM_inquire_name,
1327 p->name);
1329 if (p->access)
1330 mask |= set_string (&block, &post_block, var, IOPARM_inquire_access,
1331 p->access);
1333 if (p->sequential)
1334 mask |= set_string (&block, &post_block, var, IOPARM_inquire_sequential,
1335 p->sequential);
1337 if (p->direct)
1338 mask |= set_string (&block, &post_block, var, IOPARM_inquire_direct,
1339 p->direct);
1341 if (p->form)
1342 mask |= set_string (&block, &post_block, var, IOPARM_inquire_form,
1343 p->form);
1345 if (p->formatted)
1346 mask |= set_string (&block, &post_block, var, IOPARM_inquire_formatted,
1347 p->formatted);
1349 if (p->unformatted)
1350 mask |= set_string (&block, &post_block, var, IOPARM_inquire_unformatted,
1351 p->unformatted);
1353 if (p->recl)
1354 mask |= set_parameter_ref (&block, &post_block, var,
1355 IOPARM_inquire_recl_out, p->recl);
1357 if (p->nextrec)
1358 mask |= set_parameter_ref (&block, &post_block, var,
1359 IOPARM_inquire_nextrec, p->nextrec);
1361 if (p->blank)
1362 mask |= set_string (&block, &post_block, var, IOPARM_inquire_blank,
1363 p->blank);
1365 if (p->delim)
1366 mask |= set_string (&block, &post_block, var, IOPARM_inquire_delim,
1367 p->delim);
1369 if (p->position)
1370 mask |= set_string (&block, &post_block, var, IOPARM_inquire_position,
1371 p->position);
1373 if (p->action)
1374 mask |= set_string (&block, &post_block, var, IOPARM_inquire_action,
1375 p->action);
1377 if (p->read)
1378 mask |= set_string (&block, &post_block, var, IOPARM_inquire_read,
1379 p->read);
1381 if (p->write)
1382 mask |= set_string (&block, &post_block, var, IOPARM_inquire_write,
1383 p->write);
1385 if (p->readwrite)
1386 mask |= set_string (&block, &post_block, var, IOPARM_inquire_readwrite,
1387 p->readwrite);
1389 if (p->pad)
1390 mask |= set_string (&block, &post_block, var, IOPARM_inquire_pad,
1391 p->pad);
1393 if (p->convert)
1394 mask |= set_string (&block, &post_block, var, IOPARM_inquire_convert,
1395 p->convert);
1397 if (p->strm_pos)
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,
1404 p->asynchronous);
1406 if (p->decimal)
1407 mask2 |= set_string (&block, &post_block, var, IOPARM_inquire_decimal,
1408 p->decimal);
1410 if (p->encoding)
1411 mask2 |= set_string (&block, &post_block, var, IOPARM_inquire_encoding,
1412 p->encoding);
1414 if (p->round)
1415 mask2 |= set_string (&block, &post_block, var, IOPARM_inquire_round,
1416 p->round);
1418 if (p->sign)
1419 mask2 |= set_string (&block, &post_block, var, IOPARM_inquire_sign,
1420 p->sign);
1422 if (p->pending)
1423 mask2 |= set_parameter_ref (&block, &post_block, var,
1424 IOPARM_inquire_pending, p->pending);
1426 if (p->size)
1427 mask2 |= set_parameter_ref (&block, &post_block, var, IOPARM_inquire_size,
1428 p->size);
1430 if (p->id)
1431 mask2 |= set_parameter_ref (&block, &post_block,var, IOPARM_inquire_id,
1432 p->id);
1433 if (p->iqstream)
1434 mask2 |= set_string (&block, &post_block, var, IOPARM_inquire_iqstream,
1435 p->iqstream);
1437 if (mask2)
1438 mask |= set_parameter_const (&block, var, IOPARM_inquire_flags2, mask2);
1440 set_parameter_const (&block, var, IOPARM_common_flags, mask);
1442 if (p->unit)
1444 set_parameter_value (&block, var, IOPARM_common_unit, p->unit);
1445 set_parameter_value_inquire (&block, var, IOPARM_common_unit, p->unit);
1447 else
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);
1463 tree
1464 gfc_trans_wait (gfc_code * code)
1466 stmtblock_t block, post_block;
1467 gfc_wait *p;
1468 tree tmp, var;
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,
1475 "wait_parm");
1477 set_error_locus (&block, var, &code->loc);
1478 p = code->ext.wait;
1480 /* Set parameters here. */
1481 if (p->iomsg)
1482 mask |= set_string (&block, &post_block, var, IOPARM_common_iomsg,
1483 p->iomsg);
1485 if (p->iostat)
1486 mask |= set_parameter_ref (&block, &post_block, var, IOPARM_common_iostat,
1487 p->iostat);
1489 if (p->err)
1490 mask |= IOPARM_common_err;
1492 if (p->id)
1493 mask |= set_parameter_value (&block, var, IOPARM_wait_id, p->id);
1495 set_parameter_const (&block, var, IOPARM_common_flags, mask);
1497 if (p->unit)
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. */
1517 static char*
1518 nml_full_name (const char* var_name, const char* cmp_name, bool parent)
1520 int full_name_length;
1521 char * full_name;
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);
1528 return full_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. */
1538 static tree
1539 nml_get_addr_expr (gfc_symbol * sym, gfc_component * c,
1540 tree base_addr)
1542 tree decl = NULL_TREE;
1543 tree tmp;
1545 if (sym)
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);
1557 else
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));
1565 tmp = decl;
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);
1581 else
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,
1591 tmp);
1594 gcc_assert (tmp && POINTER_TYPE_P (TREE_TYPE (tmp)));
1596 return 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)
1606 static void
1607 transfer_namelist_element (stmtblock_t * block, const char * var_name,
1608 gfc_symbol * sym, gfc_component * c,
1609 tree base_addr)
1611 gfc_typespec * ts = NULL;
1612 gfc_array_spec * as = NULL;
1613 tree addr_expr = NULL;
1614 tree dt = NULL;
1615 tree string;
1616 tree tmp;
1617 tree dtype;
1618 tree dt_parm_addr;
1619 tree decl = NULL_TREE;
1620 tree gfc_int4_type_node = gfc_get_int_type (4);
1621 int n_dim;
1622 int itype;
1623 int rank = 0;
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);
1639 if (as)
1640 rank = as->rank;
1642 if (rank)
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);
1650 else
1652 itype = ts->type;
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;
1664 else
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),
1670 tmp, dtype);
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,
1680 dt_parm_addr,
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)
1690 gfc_component *cmp;
1692 /* Provide the RECORD_TYPE to build component references. */
1694 tree expr = build_fold_indirect_ref_loc (input_location,
1695 addr_expr);
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,
1702 full_name,
1703 NULL, cmp, expr);
1704 free (full_name);
1709 #undef IARG
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
1713 out by now. */
1715 static tree
1716 build_dt (tree function, gfc_code * code)
1718 stmtblock_t block, post_block, post_end_block, post_iu_block;
1719 gfc_dt *dt;
1720 tree tmp, var;
1721 gfc_expr *nmlname;
1722 gfc_namelist *nml;
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)
1736 gfc_inquire *inq;
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);
1747 dt = NULL;
1749 else
1751 dt = code->ext.dt;
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,
1760 var, dt->io_unit);
1761 set_parameter_const (&block, var, IOPARM_common_unit,
1762 dt->io_unit->ts.kind == 1 ? 0 : -1);
1765 else
1766 set_parameter_const (&block, var, IOPARM_common_unit, 0);
1768 if (dt)
1770 if (dt->iomsg)
1771 mask |= set_string (&block, &post_block, var, IOPARM_common_iomsg,
1772 dt->iomsg);
1774 if (dt->iostat)
1775 mask |= set_parameter_ref (&block, &post_end_block, var,
1776 IOPARM_common_iostat, dt->iostat);
1778 if (dt->err)
1779 mask |= IOPARM_common_err;
1781 if (dt->eor)
1782 mask |= IOPARM_common_eor;
1784 if (dt->end)
1785 mask |= IOPARM_common_end;
1787 if (dt->id)
1788 mask |= set_parameter_ref (&block, &post_end_block, var,
1789 IOPARM_dt_id, dt->id);
1791 if (dt->pos)
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);
1798 if (dt->blank)
1799 mask |= set_string (&block, &post_block, var, IOPARM_dt_blank,
1800 dt->blank);
1802 if (dt->decimal)
1803 mask |= set_string (&block, &post_block, var, IOPARM_dt_decimal,
1804 dt->decimal);
1806 if (dt->delim)
1807 mask |= set_string (&block, &post_block, var, IOPARM_dt_delim,
1808 dt->delim);
1810 if (dt->pad)
1811 mask |= set_string (&block, &post_block, var, IOPARM_dt_pad,
1812 dt->pad);
1814 if (dt->round)
1815 mask |= set_string (&block, &post_block, var, IOPARM_dt_round,
1816 dt->round);
1818 if (dt->sign)
1819 mask |= set_string (&block, &post_block, var, IOPARM_dt_sign,
1820 dt->sign);
1822 if (dt->rec)
1823 mask |= set_parameter_value (&block, var, IOPARM_dt_rec, dt->rec);
1825 if (dt->advance)
1826 mask |= set_string (&block, &post_block, var, IOPARM_dt_advance,
1827 dt->advance);
1829 if (dt->format_expr)
1830 mask |= set_string (&block, &post_end_block, var, IOPARM_dt_format,
1831 dt->format_expr);
1833 if (dt->format_label)
1835 if (dt->format_label == &format_asterisk)
1836 mask |= IOPARM_dt_list_format;
1837 else
1838 mask |= set_string (&block, &post_block, var, IOPARM_dt_format,
1839 dt->format_label->format);
1842 if (dt->size)
1843 mask |= set_parameter_ref (&block, &post_end_block, var,
1844 IOPARM_dt_size, dt->size);
1846 if (dt->namelist)
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,
1852 dt->namelist->name,
1853 strlen (dt->namelist->name));
1855 mask |= set_string (&block, &post_block, var, IOPARM_dt_namelist_name,
1856 nmlname);
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);
1865 dt_parm = var;
1867 for (nml = dt->namelist->namelist; nml; nml = nml->next)
1868 transfer_namelist_element (&block, nml->sym->name, nml->sym,
1869 NULL, NULL_TREE);
1871 else
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);
1878 else
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,
1883 function, 1, tmp);
1884 gfc_add_expr_to_block (&block, tmp);
1886 gfc_add_block_to_block (&block, &post_block);
1888 dt_parm = var;
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)),
1899 NULL_TREE);
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));
1906 else /* IOLENGTH */
1907 tmp = NULL_TREE;
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);
1913 dt_parm = NULL;
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. */
1924 tree
1925 gfc_trans_iolength (gfc_code * code)
1927 last_dt = IOLENGTH;
1928 return build_dt (iocall[IOCALL_IOLENGTH], code);
1932 /* Translate a READ statement. */
1934 tree
1935 gfc_trans_read (gfc_code * code)
1937 last_dt = READ;
1938 return build_dt (iocall[IOCALL_READ], code);
1942 /* Translate a WRITE statement */
1944 tree
1945 gfc_trans_write (gfc_code * code)
1947 last_dt = WRITE;
1948 return build_dt (iocall[IOCALL_WRITE], code);
1952 /* Finish a data transfer statement. */
1954 tree
1955 gfc_trans_dt_end (gfc_code * code)
1957 tree function, tmp;
1958 stmtblock_t block;
1960 gfc_init_block (&block);
1962 switch (last_dt)
1964 case READ:
1965 function = iocall[IOCALL_READ_DONE];
1966 break;
1968 case WRITE:
1969 function = iocall[IOCALL_WRITE_DONE];
1970 break;
1972 case IOLENGTH:
1973 function = iocall[IOCALL_IOLENGTH_DONE];
1974 break;
1976 default:
1977 gcc_unreachable ();
1980 tmp = gfc_build_addr_expr (NULL_TREE, dt_parm);
1981 tmp = build_call_expr_loc (input_location,
1982 function, 1, tmp);
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);
1997 static void
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
2005 recursive. */
2007 static tree
2008 transfer_array_component (tree expr, gfc_component * cm, locus * where)
2010 tree tmp;
2011 stmtblock_t body;
2012 stmtblock_t block;
2013 gfc_loopinfo loop;
2014 int n;
2015 gfc_ss *ss;
2016 gfc_se se;
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,
2028 GFC_SS_COMPONENT);
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);
2055 se.ss = ss;
2057 /* gfc_conv_tmp_array_ref assumes that se.expr contains the array. */
2058 se.expr = expr;
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
2067 return. */
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. */
2086 static void
2087 transfer_expr (gfc_se * se, gfc_typespec * ts, tree addr_expr, gfc_code * code)
2089 tree tmp, function, arg2, arg3, field, expr;
2090 gfc_component *c;
2091 int kind;
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;
2107 kind = ts->kind;
2108 function = NULL;
2109 arg2 = NULL;
2110 arg3 = NULL;
2112 switch (ts->type)
2114 case BT_INTEGER:
2115 arg2 = build_int_cst (integer_type_node, kind);
2116 if (last_dt == READ)
2117 function = iocall[IOCALL_X_INTEGER];
2118 else
2119 function = iocall[IOCALL_X_INTEGER_WRITE];
2121 break;
2123 case BT_REAL:
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];
2129 else
2130 function = iocall[IOCALL_X_REAL];
2132 else
2134 if (gfc_real16_is_float128 && ts->kind == 16)
2135 function = iocall[IOCALL_X_REAL128_WRITE];
2136 else
2137 function = iocall[IOCALL_X_REAL_WRITE];
2140 break;
2142 case BT_COMPLEX:
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];
2148 else
2149 function = iocall[IOCALL_X_COMPLEX];
2151 else
2153 if (gfc_real16_is_float128 && ts->kind == 16)
2154 function = iocall[IOCALL_X_COMPLEX128_WRITE];
2155 else
2156 function = iocall[IOCALL_X_COMPLEX_WRITE];
2159 break;
2161 case BT_LOGICAL:
2162 arg2 = build_int_cst (integer_type_node, kind);
2163 if (last_dt == READ)
2164 function = iocall[IOCALL_X_LOGICAL];
2165 else
2166 function = iocall[IOCALL_X_LOGICAL_WRITE];
2168 break;
2170 case BT_CHARACTER:
2171 if (kind == 4)
2173 if (se->string_length)
2174 arg2 = se->string_length;
2175 else
2177 tmp = build_fold_indirect_ref_loc (input_location,
2178 addr_expr);
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];
2186 else
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);
2194 return;
2196 /* Fall through. */
2197 case BT_HOLLERITH:
2198 if (se->string_length)
2199 arg2 = se->string_length;
2200 else
2202 tmp = build_fold_indirect_ref_loc (input_location,
2203 addr_expr);
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];
2209 else
2210 function = iocall[IOCALL_X_CHARACTER_WRITE];
2212 break;
2214 case BT_DERIVED:
2215 if (ts->u.derived->components == NULL)
2216 return;
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,
2221 expr);
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);
2243 else
2245 if (!c->attr.pointer)
2246 tmp = gfc_build_addr_expr (NULL_TREE, tmp);
2247 transfer_expr (se, &c->ts, tmp, code);
2250 return;
2252 default:
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. */
2268 static void
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;
2275 else
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];
2283 else
2284 io_call = iocall[IOCALL_X_ARRAY_WRITE];
2286 tmp = build_call_expr_loc (UNKNOWN_LOCATION,
2287 io_call, 4,
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 */
2296 tree
2297 gfc_trans_transfer (gfc_code * code)
2299 stmtblock_t block, body;
2300 gfc_loopinfo loop;
2301 gfc_expr *expr;
2302 gfc_ref *ref;
2303 gfc_ss *ss;
2304 gfc_se se;
2305 tree tmp;
2306 int n;
2308 gfc_start_block (&block);
2309 gfc_init_block (&body);
2311 expr = code->expr1;
2312 ref = NULL;
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);
2321 else
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;
2329 ref = ref->next);
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)
2344 seen_vector = true;
2345 break;
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);
2353 tmp = se.expr;
2355 else
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);
2380 se.ss = ss;
2382 gfc_conv_expr_reference (&se, expr);
2383 transfer_expr (&se, &expr->ts, se.expr, code);
2386 finish_block_label:
2388 gfc_add_block_to_block (&body, &se.pre);
2389 gfc_add_block_to_block (&body, &se.post);
2391 if (se.ss == NULL)
2392 tmp = gfc_finish_block (&body);
2393 else
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"