]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/fortran/trans-io.c
2018-08-21 Nicolas Koenig <koenigni@gcc.gnu.org>
[thirdparty/gcc.git] / gcc / fortran / trans-io.c
CommitLineData
4ee9c684 1/* IO Code translation/library interface
8e8f6434 2 Copyright (C) 2002-2018 Free Software Foundation, Inc.
4ee9c684 3 Contributed by Paul Brook
4
c84b470d 5This file is part of GCC.
4ee9c684 6
c84b470d 7GCC is free software; you can redistribute it and/or modify it under
8the terms of the GNU General Public License as published by the Free
bdabe786 9Software Foundation; either version 3, or (at your option) any later
c84b470d 10version.
4ee9c684 11
c84b470d 12GCC is distributed in the hope that it will be useful, but WITHOUT ANY
13WARRANTY; without even the implied warranty of MERCHANTABILITY or
14FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15for more details.
4ee9c684 16
17You should have received a copy of the GNU General Public License
bdabe786 18along with GCC; see the file COPYING3. If not see
19<http://www.gnu.org/licenses/>. */
4ee9c684 20
21
22#include "config.h"
23#include "system.h"
24#include "coretypes.h"
4cba6f60 25#include "tree.h"
4ee9c684 26#include "gfortran.h"
27#include "trans.h"
4cba6f60 28#include "stringpool.h"
4cba6f60 29#include "fold-const.h"
30#include "stor-layout.h"
4ee9c684 31#include "trans-stmt.h"
32#include "trans-array.h"
33#include "trans-types.h"
34#include "trans-const.h"
4ea02d8b 35#include "options.h"
4ee9c684 36
4ee9c684 37/* Members of the ioparm structure. */
38
60c514ba 39enum ioparam_type
40{
41 IOPARM_ptype_common,
42 IOPARM_ptype_open,
43 IOPARM_ptype_close,
44 IOPARM_ptype_filepos,
45 IOPARM_ptype_inquire,
46 IOPARM_ptype_dt,
ff6af856 47 IOPARM_ptype_wait,
60c514ba 48 IOPARM_ptype_num
49};
50
51enum iofield_type
52{
53 IOPARM_type_int4,
e83964b2 54 IOPARM_type_intio,
60c514ba 55 IOPARM_type_pint4,
e83964b2 56 IOPARM_type_pintio,
60c514ba 57 IOPARM_type_pchar,
58 IOPARM_type_parray,
59 IOPARM_type_pad,
60 IOPARM_type_char1,
61 IOPARM_type_char2,
62 IOPARM_type_common,
63 IOPARM_type_num
64};
65
fb1e4f4a 66typedef struct GTY(()) gfc_st_parameter_field {
60c514ba 67 const char *name;
68 unsigned int mask;
69 enum ioparam_type param_type;
70 enum iofield_type type;
71 tree field;
72 tree field_len;
73}
74gfc_st_parameter_field;
4ee9c684 75
fb1e4f4a 76typedef struct GTY(()) gfc_st_parameter {
60c514ba 77 const char *name;
78 tree type;
79}
80gfc_st_parameter;
81
82enum iofield
83{
84#define IOPARM(param_type, name, mask, type) IOPARM_##param_type##_##name,
85#include "ioparm.def"
86#undef IOPARM
87 IOPARM_field_num
88};
89
90static GTY(()) gfc_st_parameter st_parameter[] =
91{
92 { "common", NULL },
93 { "open", NULL },
94 { "close", NULL },
95 { "filepos", NULL },
96 { "inquire", NULL },
ff6af856 97 { "dt", NULL },
98 { "wait", NULL }
60c514ba 99};
100
101static GTY(()) gfc_st_parameter_field st_parameter_field[] =
102{
103#define IOPARM(param_type, name, mask, type) \
104 { #name, mask, IOPARM_ptype_##param_type, IOPARM_type_##type, NULL, NULL },
105#include "ioparm.def"
106#undef IOPARM
bc620c5c 107 { NULL, 0, (enum ioparam_type) 0, (enum iofield_type) 0, NULL, NULL }
60c514ba 108};
4ee9c684 109
110/* Library I/O subroutines */
111
60c514ba 112enum iocall
113{
114 IOCALL_READ,
115 IOCALL_READ_DONE,
116 IOCALL_WRITE,
117 IOCALL_WRITE_DONE,
118 IOCALL_X_INTEGER,
8545af25 119 IOCALL_X_INTEGER_WRITE,
60c514ba 120 IOCALL_X_LOGICAL,
8545af25 121 IOCALL_X_LOGICAL_WRITE,
60c514ba 122 IOCALL_X_CHARACTER,
8545af25 123 IOCALL_X_CHARACTER_WRITE,
dc01006d 124 IOCALL_X_CHARACTER_WIDE,
8545af25 125 IOCALL_X_CHARACTER_WIDE_WRITE,
60c514ba 126 IOCALL_X_REAL,
8545af25 127 IOCALL_X_REAL_WRITE,
60c514ba 128 IOCALL_X_COMPLEX,
8545af25 129 IOCALL_X_COMPLEX_WRITE,
87969c8c 130 IOCALL_X_REAL128,
131 IOCALL_X_REAL128_WRITE,
132 IOCALL_X_COMPLEX128,
133 IOCALL_X_COMPLEX128_WRITE,
60c514ba 134 IOCALL_X_ARRAY,
8545af25 135 IOCALL_X_ARRAY_WRITE,
9f732c4e 136 IOCALL_X_DERIVED,
60c514ba 137 IOCALL_OPEN,
138 IOCALL_CLOSE,
139 IOCALL_INQUIRE,
140 IOCALL_IOLENGTH,
141 IOCALL_IOLENGTH_DONE,
142 IOCALL_REWIND,
143 IOCALL_BACKSPACE,
144 IOCALL_ENDFILE,
145 IOCALL_FLUSH,
146 IOCALL_SET_NML_VAL,
9f732c4e 147 IOCALL_SET_NML_DTIO_VAL,
60c514ba 148 IOCALL_SET_NML_VAL_DIM,
ff6af856 149 IOCALL_WAIT,
60c514ba 150 IOCALL_NUM
151};
152
153static GTY(()) tree iocall[IOCALL_NUM];
4ee9c684 154
155/* Variable for keeping track of what the last data transfer statement
156 was. Used for deciding which subroutine to call when the data
b14e2757 157 transfer is complete. */
6799e2f8 158static enum { READ, WRITE, IOLENGTH } last_dt;
4ee9c684 159
60c514ba 160/* The data transfer parameter block that should be shared by all
161 data transfer calls belonging to the same read/write/iolength. */
162static GTY(()) tree dt_parm;
163static stmtblock_t *dt_post_end_block;
4ee9c684 164
60c514ba 165static void
166gfc_build_st_parameter (enum ioparam_type ptype, tree *types)
167{
8458f4ca 168 unsigned int type;
60c514ba 169 gfc_st_parameter_field *p;
170 char name[64];
171 size_t len;
172 tree t = make_node (RECORD_TYPE);
02e2a14b 173 tree *chain = NULL;
60c514ba 174
175 len = strlen (st_parameter[ptype].name);
176 gcc_assert (len <= sizeof (name) - sizeof ("__st_parameter_"));
177 memcpy (name, "__st_parameter_", sizeof ("__st_parameter_"));
178 memcpy (name + sizeof ("__st_parameter_") - 1, st_parameter[ptype].name,
6b7a7d7d 179 len + 1);
60c514ba 180 TYPE_NAME (t) = get_identifier (name);
181
182 for (type = 0, p = st_parameter_field; type < IOPARM_field_num; type++, p++)
183 if (p->param_type == ptype)
184 switch (p->type)
185 {
186 case IOPARM_type_int4:
e83964b2 187 case IOPARM_type_intio:
60c514ba 188 case IOPARM_type_pint4:
e83964b2 189 case IOPARM_type_pintio:
60c514ba 190 case IOPARM_type_parray:
191 case IOPARM_type_pchar:
192 case IOPARM_type_pad:
4ce1f210 193 p->field = gfc_add_field_to_struct (t, get_identifier (p->name),
02e2a14b 194 types[p->type], &chain);
60c514ba 195 break;
196 case IOPARM_type_char1:
4ce1f210 197 p->field = gfc_add_field_to_struct (t, get_identifier (p->name),
02e2a14b 198 pchar_type_node, &chain);
60c514ba 199 /* FALLTHROUGH */
200 case IOPARM_type_char2:
201 len = strlen (p->name);
202 gcc_assert (len <= sizeof (name) - sizeof ("_len"));
203 memcpy (name, p->name, len);
204 memcpy (name + len, "_len", sizeof ("_len"));
4ce1f210 205 p->field_len = gfc_add_field_to_struct (t, get_identifier (name),
02e2a14b 206 gfc_charlen_type_node,
207 &chain);
60c514ba 208 if (p->type == IOPARM_type_char2)
4ce1f210 209 p->field = gfc_add_field_to_struct (t, get_identifier (p->name),
02e2a14b 210 pchar_type_node, &chain);
60c514ba 211 break;
212 case IOPARM_type_common:
213 p->field
4ce1f210 214 = gfc_add_field_to_struct (t,
60c514ba 215 get_identifier (p->name),
02e2a14b 216 st_parameter[IOPARM_ptype_common].type,
217 &chain);
60c514ba 218 break;
219 case IOPARM_type_num:
220 gcc_unreachable ();
221 }
4ee9c684 222
4ea02d8b 223 /* -Wpadded warnings on these artificially created structures are not
224 helpful; suppress them. */
225 int save_warn_padded = warn_padded;
226 warn_padded = 0;
60c514ba 227 gfc_finish_type (t);
4ea02d8b 228 warn_padded = save_warn_padded;
60c514ba 229 st_parameter[ptype].type = t;
230}
4ee9c684 231
50ad5fa2 232
233/* Build code to test an error condition and call generate_error if needed.
234 Note: This builds calls to generate_error in the runtime library function.
235 The function generate_error is dependent on certain parameters in the
236 st_parameter_common flags to be set. (See libgfortran/runtime/error.c)
237 Therefore, the code to set these flags must be generated before
238 this function is used. */
239
c83059be 240static void
241gfc_trans_io_runtime_check (bool has_iostat, tree cond, tree var,
242 int error_code, const char * msgid,
243 stmtblock_t * pblock)
50ad5fa2 244{
245 stmtblock_t block;
246 tree body;
247 tree tmp;
248 tree arg1, arg2, arg3;
249 char *message;
250
251 if (integer_zerop (cond))
252 return;
253
254 /* The code to generate the error. */
255 gfc_start_block (&block);
4442e7ec 256
c83059be 257 if (has_iostat)
258 gfc_add_expr_to_block (&block, build_predict_expr (PRED_FORTRAN_FAIL_IO,
259 NOT_TAKEN));
260 else
261 gfc_add_expr_to_block (&block, build_predict_expr (PRED_NORETURN,
262 NOT_TAKEN));
263
86f2ad37 264 arg1 = gfc_build_addr_expr (NULL_TREE, var);
4442e7ec 265
50ad5fa2 266 arg2 = build_int_cst (integer_type_node, error_code),
4442e7ec 267
87fda26c 268 message = xasprintf ("%s", _(msgid));
8fb9e3cd 269 arg3 = gfc_build_addr_expr (pchar_type_node,
270 gfc_build_localized_cstring_const (message));
434f0922 271 free (message);
4442e7ec 272
389dd41b 273 tmp = build_call_expr_loc (input_location,
274 gfor_fndecl_generate_error, 3, arg1, arg2, arg3);
50ad5fa2 275
276 gfc_add_expr_to_block (&block, tmp);
277
278 body = gfc_finish_block (&block);
279
280 if (integer_onep (cond))
281 {
282 gfc_add_expr_to_block (pblock, body);
283 }
284 else
285 {
e60a6f7b 286 tmp = build3_v (COND_EXPR, cond, body, build_empty_stmt (input_location));
50ad5fa2 287 gfc_add_expr_to_block (pblock, tmp);
288 }
289}
290
291
4ee9c684 292/* Create function decls for IO library functions. */
293
294void
295gfc_build_io_library_fndecls (void)
296{
60c514ba 297 tree types[IOPARM_type_num], pad_idx, gfc_int4_type_node;
e83964b2 298 tree gfc_intio_type_node;
60c514ba 299 tree parm_type, dt_parm_type;
60c514ba 300 HOST_WIDE_INT pad_size;
9f1b7d17 301 unsigned int ptype;
60c514ba 302
303 types[IOPARM_type_int4] = gfc_int4_type_node = gfc_get_int_type (4);
e83964b2 304 types[IOPARM_type_intio] = gfc_intio_type_node
305 = gfc_get_int_type (gfc_intio_kind);
60c514ba 306 types[IOPARM_type_pint4] = build_pointer_type (gfc_int4_type_node);
e83964b2 307 types[IOPARM_type_pintio]
308 = build_pointer_type (gfc_intio_type_node);
60c514ba 309 types[IOPARM_type_parray] = pchar_type_node;
310 types[IOPARM_type_pchar] = pchar_type_node;
b5d015e3 311 pad_size = 16 * TREE_INT_CST_LOW (TYPE_SIZE_UNIT (pchar_type_node));
60c514ba 312 pad_size += 32 * TREE_INT_CST_LOW (TYPE_SIZE_UNIT (integer_type_node));
35bf1214 313 pad_idx = build_index_type (size_int (pad_size - 1));
60c514ba 314 types[IOPARM_type_pad] = build_array_type (char_type_node, pad_idx);
23434847 315
316 /* pad actually contains pointers and integers so it needs to have an
317 alignment that is at least as large as the needed alignment for those
318 types. See the st_parameter_dt structure in libgfortran/io/io.h for
319 what really goes into this space. */
5d4b30ea 320 SET_TYPE_ALIGN (types[IOPARM_type_pad], MAX (TYPE_ALIGN (pchar_type_node),
321 TYPE_ALIGN (gfc_get_int_type (gfc_intio_kind))));
23434847 322
60c514ba 323 for (ptype = IOPARM_ptype_common; ptype < IOPARM_ptype_num; ptype++)
9f1b7d17 324 gfc_build_st_parameter ((enum ioparam_type) ptype, types);
4ee9c684 325
8545af25 326 /* Define the transfer functions. */
4ee9c684 327
60c514ba 328 dt_parm_type = build_pointer_type (st_parameter[IOPARM_ptype_dt].type);
329
4bf69bc3 330 iocall[IOCALL_X_INTEGER] = gfc_build_library_function_decl_with_spec (
331 get_identifier (PREFIX("transfer_integer")), ".wW",
332 void_type_node, 3, dt_parm_type, pvoid_type_node, gfc_int4_type_node);
333
8545af25 334 iocall[IOCALL_X_INTEGER_WRITE] = gfc_build_library_function_decl_with_spec (
335 get_identifier (PREFIX("transfer_integer_write")), ".wR",
336 void_type_node, 3, dt_parm_type, pvoid_type_node, gfc_int4_type_node);
337
4bf69bc3 338 iocall[IOCALL_X_LOGICAL] = gfc_build_library_function_decl_with_spec (
339 get_identifier (PREFIX("transfer_logical")), ".wW",
340 void_type_node, 3, dt_parm_type, pvoid_type_node, gfc_int4_type_node);
341
8545af25 342 iocall[IOCALL_X_LOGICAL_WRITE] = gfc_build_library_function_decl_with_spec (
343 get_identifier (PREFIX("transfer_logical_write")), ".wR",
344 void_type_node, 3, dt_parm_type, pvoid_type_node, gfc_int4_type_node);
345
4bf69bc3 346 iocall[IOCALL_X_CHARACTER] = gfc_build_library_function_decl_with_spec (
347 get_identifier (PREFIX("transfer_character")), ".wW",
9f4d9f83 348 void_type_node, 3, dt_parm_type, pvoid_type_node, gfc_charlen_type_node);
4bf69bc3 349
8545af25 350 iocall[IOCALL_X_CHARACTER_WRITE] = gfc_build_library_function_decl_with_spec (
351 get_identifier (PREFIX("transfer_character_write")), ".wR",
9f4d9f83 352 void_type_node, 3, dt_parm_type, pvoid_type_node, gfc_charlen_type_node);
8545af25 353
4bf69bc3 354 iocall[IOCALL_X_CHARACTER_WIDE] = gfc_build_library_function_decl_with_spec (
355 get_identifier (PREFIX("transfer_character_wide")), ".wW",
356 void_type_node, 4, dt_parm_type, pvoid_type_node,
357 gfc_charlen_type_node, gfc_int4_type_node);
358
8545af25 359 iocall[IOCALL_X_CHARACTER_WIDE_WRITE] =
360 gfc_build_library_function_decl_with_spec (
361 get_identifier (PREFIX("transfer_character_wide_write")), ".wR",
362 void_type_node, 4, dt_parm_type, pvoid_type_node,
363 gfc_charlen_type_node, gfc_int4_type_node);
364
4bf69bc3 365 iocall[IOCALL_X_REAL] = gfc_build_library_function_decl_with_spec (
366 get_identifier (PREFIX("transfer_real")), ".wW",
367 void_type_node, 3, dt_parm_type, pvoid_type_node, gfc_int4_type_node);
368
8545af25 369 iocall[IOCALL_X_REAL_WRITE] = gfc_build_library_function_decl_with_spec (
370 get_identifier (PREFIX("transfer_real_write")), ".wR",
371 void_type_node, 3, dt_parm_type, pvoid_type_node, gfc_int4_type_node);
372
4bf69bc3 373 iocall[IOCALL_X_COMPLEX] = gfc_build_library_function_decl_with_spec (
374 get_identifier (PREFIX("transfer_complex")), ".wW",
375 void_type_node, 3, dt_parm_type, pvoid_type_node, gfc_int4_type_node);
376
8545af25 377 iocall[IOCALL_X_COMPLEX_WRITE] = gfc_build_library_function_decl_with_spec (
378 get_identifier (PREFIX("transfer_complex_write")), ".wR",
379 void_type_node, 3, dt_parm_type, pvoid_type_node, gfc_int4_type_node);
380
87969c8c 381 /* Version for __float128. */
382 iocall[IOCALL_X_REAL128] = gfc_build_library_function_decl_with_spec (
383 get_identifier (PREFIX("transfer_real128")), ".wW",
384 void_type_node, 3, dt_parm_type, pvoid_type_node, gfc_int4_type_node);
385
386 iocall[IOCALL_X_REAL128_WRITE] = gfc_build_library_function_decl_with_spec (
387 get_identifier (PREFIX("transfer_real128_write")), ".wR",
388 void_type_node, 3, dt_parm_type, pvoid_type_node, gfc_int4_type_node);
389
390 iocall[IOCALL_X_COMPLEX128] = gfc_build_library_function_decl_with_spec (
391 get_identifier (PREFIX("transfer_complex128")), ".wW",
392 void_type_node, 3, dt_parm_type, pvoid_type_node, gfc_int4_type_node);
393
394 iocall[IOCALL_X_COMPLEX128_WRITE] = gfc_build_library_function_decl_with_spec (
395 get_identifier (PREFIX("transfer_complex128_write")), ".wR",
396 void_type_node, 3, dt_parm_type, pvoid_type_node, gfc_int4_type_node);
397
4bf69bc3 398 iocall[IOCALL_X_ARRAY] = gfc_build_library_function_decl_with_spec (
12997918 399 get_identifier (PREFIX("transfer_array")), ".ww",
4bf69bc3 400 void_type_node, 4, dt_parm_type, pvoid_type_node,
401 integer_type_node, gfc_charlen_type_node);
fd5a2518 402
8545af25 403 iocall[IOCALL_X_ARRAY_WRITE] = gfc_build_library_function_decl_with_spec (
404 get_identifier (PREFIX("transfer_array_write")), ".wr",
405 void_type_node, 4, dt_parm_type, pvoid_type_node,
406 integer_type_node, gfc_charlen_type_node);
407
9f732c4e 408 iocall[IOCALL_X_DERIVED] = gfc_build_library_function_decl_with_spec (
409 get_identifier (PREFIX("transfer_derived")), ".wrR",
410 void_type_node, 2, dt_parm_type, pvoid_type_node, pchar_type_node);
411
4ee9c684 412 /* Library entry points */
413
4bf69bc3 414 iocall[IOCALL_READ] = gfc_build_library_function_decl_with_spec (
415 get_identifier (PREFIX("st_read")), ".w",
416 void_type_node, 1, dt_parm_type);
4ee9c684 417
4bf69bc3 418 iocall[IOCALL_WRITE] = gfc_build_library_function_decl_with_spec (
419 get_identifier (PREFIX("st_write")), ".w",
420 void_type_node, 1, dt_parm_type);
60c514ba 421
422 parm_type = build_pointer_type (st_parameter[IOPARM_ptype_open].type);
4bf69bc3 423 iocall[IOCALL_OPEN] = gfc_build_library_function_decl_with_spec (
424 get_identifier (PREFIX("st_open")), ".w",
425 void_type_node, 1, parm_type);
60c514ba 426
427 parm_type = build_pointer_type (st_parameter[IOPARM_ptype_close].type);
4bf69bc3 428 iocall[IOCALL_CLOSE] = gfc_build_library_function_decl_with_spec (
429 get_identifier (PREFIX("st_close")), ".w",
430 void_type_node, 1, parm_type);
4ee9c684 431
60c514ba 432 parm_type = build_pointer_type (st_parameter[IOPARM_ptype_inquire].type);
4bf69bc3 433 iocall[IOCALL_INQUIRE] = gfc_build_library_function_decl_with_spec (
434 get_identifier (PREFIX("st_inquire")), ".w",
f5e3bc0e 435 void_type_node, 1, parm_type);
4ee9c684 436
4bf69bc3 437 iocall[IOCALL_IOLENGTH] = gfc_build_library_function_decl_with_spec(
438 get_identifier (PREFIX("st_iolength")), ".w",
439 void_type_node, 1, dt_parm_type);
6799e2f8 440
ff6af856 441 parm_type = build_pointer_type (st_parameter[IOPARM_ptype_wait].type);
4bf69bc3 442 iocall[IOCALL_WAIT] = gfc_build_library_function_decl_with_spec (
629c30bb 443 get_identifier (PREFIX("st_wait_async")), ".w",
f5e3bc0e 444 void_type_node, 1, parm_type);
ff6af856 445
60c514ba 446 parm_type = build_pointer_type (st_parameter[IOPARM_ptype_filepos].type);
4bf69bc3 447 iocall[IOCALL_REWIND] = gfc_build_library_function_decl_with_spec (
448 get_identifier (PREFIX("st_rewind")), ".w",
f5e3bc0e 449 void_type_node, 1, parm_type);
4ee9c684 450
4bf69bc3 451 iocall[IOCALL_BACKSPACE] = gfc_build_library_function_decl_with_spec (
452 get_identifier (PREFIX("st_backspace")), ".w",
f5e3bc0e 453 void_type_node, 1, parm_type);
4ee9c684 454
4bf69bc3 455 iocall[IOCALL_ENDFILE] = gfc_build_library_function_decl_with_spec (
456 get_identifier (PREFIX("st_endfile")), ".w",
f5e3bc0e 457 void_type_node, 1, parm_type);
6c306f90 458
4bf69bc3 459 iocall[IOCALL_FLUSH] = gfc_build_library_function_decl_with_spec (
460 get_identifier (PREFIX("st_flush")), ".w",
f5e3bc0e 461 void_type_node, 1, parm_type);
6c306f90 462
4ee9c684 463 /* Library helpers */
464
4bf69bc3 465 iocall[IOCALL_READ_DONE] = gfc_build_library_function_decl_with_spec (
466 get_identifier (PREFIX("st_read_done")), ".w",
f5e3bc0e 467 void_type_node, 1, dt_parm_type);
6799e2f8 468
4bf69bc3 469 iocall[IOCALL_WRITE_DONE] = gfc_build_library_function_decl_with_spec (
470 get_identifier (PREFIX("st_write_done")), ".w",
f5e3bc0e 471 void_type_node, 1, dt_parm_type);
6799e2f8 472
4bf69bc3 473 iocall[IOCALL_IOLENGTH_DONE] = gfc_build_library_function_decl_with_spec (
474 get_identifier (PREFIX("st_iolength_done")), ".w",
f5e3bc0e 475 void_type_node, 1, dt_parm_type);
4ee9c684 476
4bf69bc3 477 iocall[IOCALL_SET_NML_VAL] = gfc_build_library_function_decl_with_spec (
478 get_identifier (PREFIX("st_set_nml_var")), ".w.R",
479 void_type_node, 6, dt_parm_type, pvoid_type_node, pvoid_type_node,
d9c7c3e3 480 gfc_int4_type_node, gfc_charlen_type_node, get_dtype_type_node());
4ee9c684 481
9f732c4e 482 iocall[IOCALL_SET_NML_DTIO_VAL] = gfc_build_library_function_decl_with_spec (
483 get_identifier (PREFIX("st_set_nml_dtio_var")), ".w.R",
484 void_type_node, 8, dt_parm_type, pvoid_type_node, pvoid_type_node,
d9c7c3e3 485 gfc_int4_type_node, gfc_charlen_type_node, get_dtype_type_node(),
9f732c4e 486 pvoid_type_node, pvoid_type_node);
487
4bf69bc3 488 iocall[IOCALL_SET_NML_VAL_DIM] = gfc_build_library_function_decl_with_spec (
489 get_identifier (PREFIX("st_set_nml_var_dim")), ".w",
490 void_type_node, 5, dt_parm_type, gfc_int4_type_node,
491 gfc_array_index_type, gfc_array_index_type, gfc_array_index_type);
4ee9c684 492}
493
494
9f732c4e 495static void
496set_parameter_tree (stmtblock_t *block, tree var, enum iofield type, tree value)
60c514ba 497{
498 tree tmp;
499 gfc_st_parameter_field *p = &st_parameter_field[type];
500
501 if (p->param_type == IOPARM_ptype_common)
1516b2fb 502 var = fold_build3_loc (input_location, COMPONENT_REF,
503 st_parameter[IOPARM_ptype_common].type,
504 var, TYPE_FIELDS (TREE_TYPE (var)), NULL_TREE);
505 tmp = fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (p->field),
506 var, p->field, NULL_TREE);
9f732c4e 507 gfc_add_modify (block, tmp, value);
508}
509
510
511/* Generate code to store an integer constant into the
512 st_parameter_XXX structure. */
513
514static unsigned int
515set_parameter_const (stmtblock_t *block, tree var, enum iofield type,
516 unsigned int val)
517{
518 gfc_st_parameter_field *p = &st_parameter_field[type];
519
520 set_parameter_tree (block, var, type,
521 build_int_cst (TREE_TYPE (p->field), val));
60c514ba 522 return p->mask;
523}
524
525
89d91d02 526/* Generate code to store a non-string I/O parameter into the
60c514ba 527 st_parameter_XXX structure. This is a pass by value. */
4ee9c684 528
60c514ba 529static unsigned int
f26dc717 530set_parameter_value (stmtblock_t *block, tree var, enum iofield type,
531 gfc_expr *e)
532{
533 gfc_se se;
534 tree tmp;
535 gfc_st_parameter_field *p = &st_parameter_field[type];
536 tree dest_type = TREE_TYPE (p->field);
537
538 gfc_init_se (&se, NULL);
539 gfc_conv_expr_val (&se, e);
540
541 se.expr = convert (dest_type, se.expr);
542 gfc_add_block_to_block (block, &se.pre);
543
544 if (p->param_type == IOPARM_ptype_common)
545 var = fold_build3_loc (input_location, COMPONENT_REF,
546 st_parameter[IOPARM_ptype_common].type,
547 var, TYPE_FIELDS (TREE_TYPE (var)), NULL_TREE);
548
549 tmp = fold_build3_loc (input_location, COMPONENT_REF, dest_type, var,
550 p->field, NULL_TREE);
551 gfc_add_modify (block, tmp, se.expr);
552 return p->mask;
553}
554
555
556/* Similar to set_parameter_value except generate runtime
557 error checks. */
558
559static unsigned int
560set_parameter_value_chk (stmtblock_t *block, bool has_iostat, tree var,
c83059be 561 enum iofield type, gfc_expr *e)
4ee9c684 562{
563 gfc_se se;
564 tree tmp;
60c514ba 565 gfc_st_parameter_field *p = &st_parameter_field[type];
50ad5fa2 566 tree dest_type = TREE_TYPE (p->field);
4ee9c684 567
568 gfc_init_se (&se, NULL);
50ad5fa2 569 gfc_conv_expr_val (&se, e);
570
571 /* If we're storing a UNIT number, we need to check it first. */
82b12af7 572 if (type == IOPARM_common_unit && e->ts.kind > 4)
50ad5fa2 573 {
82b12af7 574 tree cond, val;
50ad5fa2 575 int i;
576
50ad5fa2 577 /* Don't evaluate the UNIT number multiple times. */
578 se.expr = gfc_evaluate_now (se.expr, &se.pre);
579
82b12af7 580 /* UNIT numbers should be greater than the min. */
581 i = gfc_validate_kind (BT_INTEGER, 4, false);
582 val = gfc_conv_mpz_to_tree (gfc_integer_kinds[i].pedantic_min_int, 4);
4c796f54 583 cond = fold_build2_loc (input_location, LT_EXPR, logical_type_node,
1516b2fb 584 se.expr,
585 fold_convert (TREE_TYPE (se.expr), val));
c83059be 586 gfc_trans_io_runtime_check (has_iostat, cond, var, LIBERROR_BAD_UNIT,
587 "Unit number in I/O statement too small",
588 &se.pre);
4442e7ec 589
50ad5fa2 590 /* UNIT numbers should be less than the max. */
82b12af7 591 val = gfc_conv_mpz_to_tree (gfc_integer_kinds[i].huge, 4);
4c796f54 592 cond = fold_build2_loc (input_location, GT_EXPR, logical_type_node,
1516b2fb 593 se.expr,
594 fold_convert (TREE_TYPE (se.expr), val));
c83059be 595 gfc_trans_io_runtime_check (has_iostat, cond, var, LIBERROR_BAD_UNIT,
596 "Unit number in I/O statement too large",
597 &se.pre);
50ad5fa2 598 }
599
600 se.expr = convert (dest_type, se.expr);
4ee9c684 601 gfc_add_block_to_block (block, &se.pre);
602
60c514ba 603 if (p->param_type == IOPARM_ptype_common)
1516b2fb 604 var = fold_build3_loc (input_location, COMPONENT_REF,
605 st_parameter[IOPARM_ptype_common].type,
606 var, TYPE_FIELDS (TREE_TYPE (var)), NULL_TREE);
50ad5fa2 607
1516b2fb 608 tmp = fold_build3_loc (input_location, COMPONENT_REF, dest_type, var,
609 p->field, NULL_TREE);
75a70cf9 610 gfc_add_modify (block, tmp, se.expr);
60c514ba 611 return p->mask;
4ee9c684 612}
613
614
f26dc717 615/* Build code to check the unit range if KIND=8 is used. Similar to
616 set_parameter_value_chk but we do not generate error calls for
617 inquire statements. */
618
619static unsigned int
620set_parameter_value_inquire (stmtblock_t *block, tree var,
621 enum iofield type, gfc_expr *e)
622{
623 gfc_se se;
624 gfc_st_parameter_field *p = &st_parameter_field[type];
625 tree dest_type = TREE_TYPE (p->field);
626
627 gfc_init_se (&se, NULL);
628 gfc_conv_expr_val (&se, e);
629
630 /* If we're inquiring on a UNIT number, we need to check to make
631 sure it exists for larger than kind = 4. */
632 if (type == IOPARM_common_unit && e->ts.kind > 4)
633 {
634 stmtblock_t newblock;
635 tree cond1, cond2, cond3, val, body;
636 int i;
637
638 /* Don't evaluate the UNIT number multiple times. */
639 se.expr = gfc_evaluate_now (se.expr, &se.pre);
640
cdde49df 641 /* UNIT numbers should be greater than the min. */
f26dc717 642 i = gfc_validate_kind (BT_INTEGER, 4, false);
cdde49df 643 val = gfc_conv_mpz_to_tree (gfc_integer_kinds[i].pedantic_min_int, 4);
4c796f54 644 cond1 = build2_loc (input_location, LT_EXPR, logical_type_node,
f26dc717 645 se.expr,
cdde49df 646 fold_convert (TREE_TYPE (se.expr), val));
f26dc717 647 /* UNIT numbers should be less than the max. */
648 val = gfc_conv_mpz_to_tree (gfc_integer_kinds[i].huge, 4);
4c796f54 649 cond2 = build2_loc (input_location, GT_EXPR, logical_type_node,
f26dc717 650 se.expr,
651 fold_convert (TREE_TYPE (se.expr), val));
652 cond3 = build2_loc (input_location, TRUTH_OR_EXPR,
4c796f54 653 logical_type_node, cond1, cond2);
f26dc717 654
655 gfc_start_block (&newblock);
656
657 /* The unit number GFC_INVALID_UNIT is reserved. No units can
658 ever have this value. It is used here to signal to the
659 runtime library that the inquire unit number is outside the
660 allowable range and so cannot exist. It is needed when
661 -fdefault-integer-8 is used. */
662 set_parameter_const (&newblock, var, IOPARM_common_unit,
663 GFC_INVALID_UNIT);
664
665 body = gfc_finish_block (&newblock);
666
9f732c4e 667 cond3 = gfc_unlikely (cond3, PRED_FORTRAN_FAIL_IO);
f26dc717 668 var = build3_v (COND_EXPR, cond3, body, build_empty_stmt (input_location));
669 gfc_add_expr_to_block (&se.pre, var);
670 }
671
672 se.expr = convert (dest_type, se.expr);
673 gfc_add_block_to_block (block, &se.pre);
674
675 return p->mask;
676}
677
678
89d91d02 679/* Generate code to store a non-string I/O parameter into the
60c514ba 680 st_parameter_XXX structure. This is pass by reference. */
4ee9c684 681
60c514ba 682static unsigned int
683set_parameter_ref (stmtblock_t *block, stmtblock_t *postblock,
684 tree var, enum iofield type, gfc_expr *e)
4ee9c684 685{
686 gfc_se se;
60c514ba 687 tree tmp, addr;
688 gfc_st_parameter_field *p = &st_parameter_field[type];
4ee9c684 689
60c514ba 690 gcc_assert (e->ts.type == BT_INTEGER || e->ts.type == BT_LOGICAL);
4ee9c684 691 gfc_init_se (&se, NULL);
60c514ba 692 gfc_conv_expr_lhs (&se, e);
4ee9c684 693
4ee9c684 694 gfc_add_block_to_block (block, &se.pre);
695
60c514ba 696 if (TYPE_MODE (TREE_TYPE (se.expr))
697 == TYPE_MODE (TREE_TYPE (TREE_TYPE (p->field))))
50ad5fa2 698 {
86f2ad37 699 addr = convert (TREE_TYPE (p->field), gfc_build_addr_expr (NULL_TREE, se.expr));
50ad5fa2 700
701 /* If this is for the iostat variable initialize the
18f0b7df 702 user variable to LIBERROR_OK which is zero. */
50ad5fa2 703 if (type == IOPARM_common_iostat)
75a70cf9 704 gfc_add_modify (block, se.expr,
18f0b7df 705 build_int_cst (TREE_TYPE (se.expr), LIBERROR_OK));
50ad5fa2 706 }
60c514ba 707 else
708 {
709 /* The type used by the library has different size
50ad5fa2 710 from the type of the variable supplied by the user.
711 Need to use a temporary. */
712 tree tmpvar = gfc_create_var (TREE_TYPE (TREE_TYPE (p->field)),
713 st_parameter_field[type].name);
714
715 /* If this is for the iostat variable, initialize the
18f0b7df 716 user variable to LIBERROR_OK which is zero. */
50ad5fa2 717 if (type == IOPARM_common_iostat)
75a70cf9 718 gfc_add_modify (block, tmpvar,
18f0b7df 719 build_int_cst (TREE_TYPE (tmpvar), LIBERROR_OK));
50ad5fa2 720
86f2ad37 721 addr = gfc_build_addr_expr (NULL_TREE, tmpvar);
50ad5fa2 722 /* After the I/O operation, we set the variable from the temporary. */
60c514ba 723 tmp = convert (TREE_TYPE (se.expr), tmpvar);
75a70cf9 724 gfc_add_modify (postblock, se.expr, tmp);
50ad5fa2 725 }
60c514ba 726
9f732c4e 727 set_parameter_tree (block, var, type, addr);
60c514ba 728 return p->mask;
4ee9c684 729}
730
169f9d09 731/* Given an array expr, find its address and length to get a string. If the
732 array is full, the string's address is the address of array's first element
bc56d052 733 and the length is the size of the whole array. If it is an element, the
169f9d09 734 string's address is the element's address and the length is the rest size of
bc56d052 735 the array. */
169f9d09 736
737static void
738gfc_convert_array_to_string (gfc_se * se, gfc_expr * e)
739{
169f9d09 740 tree size;
169f9d09 741
bc56d052 742 if (e->rank == 0)
169f9d09 743 {
bc56d052 744 tree type, array, tmp;
745 gfc_symbol *sym;
746 int rank;
747
748 /* If it is an element, we need its address and size of the rest. */
749 gcc_assert (e->expr_type == EXPR_VARIABLE);
750 gcc_assert (e->ref->u.ar.type == AR_ELEMENT);
751 sym = e->symtree->n.sym;
752 rank = sym->as->rank - 1;
169f9d09 753 gfc_conv_expr (se, e);
169f9d09 754
bc56d052 755 array = sym->backend_decl;
756 type = TREE_TYPE (array);
169f9d09 757
bc56d052 758 if (GFC_ARRAY_TYPE_P (type))
759 size = GFC_TYPE_ARRAY_SIZE (type);
760 else
761 {
762 gcc_assert (GFC_DESCRIPTOR_TYPE_P (type));
763 size = gfc_conv_array_stride (array, rank);
1516b2fb 764 tmp = fold_build2_loc (input_location, MINUS_EXPR,
765 gfc_array_index_type,
766 gfc_conv_array_ubound (array, rank),
767 gfc_conv_array_lbound (array, rank));
768 tmp = fold_build2_loc (input_location, PLUS_EXPR,
769 gfc_array_index_type, tmp,
770 gfc_index_one_node);
771 size = fold_build2_loc (input_location, MULT_EXPR,
772 gfc_array_index_type, tmp, size);
bc56d052 773 }
774 gcc_assert (size);
169f9d09 775
1516b2fb 776 size = fold_build2_loc (input_location, MINUS_EXPR,
777 gfc_array_index_type, size,
778 TREE_OPERAND (se->expr, 1));
86f2ad37 779 se->expr = gfc_build_addr_expr (NULL_TREE, se->expr);
bc56d052 780 tmp = TYPE_SIZE_UNIT (gfc_get_element_type (type));
1516b2fb 781 size = fold_build2_loc (input_location, MULT_EXPR,
782 gfc_array_index_type, size,
783 fold_convert (gfc_array_index_type, tmp));
bc56d052 784 se->string_length = fold_convert (gfc_charlen_type_node, size);
785 return;
169f9d09 786 }
787
5d34a30f 788 gfc_conv_array_parameter (se, e, true, NULL, NULL, &size);
169f9d09 789 se->string_length = fold_convert (gfc_charlen_type_node, size);
790}
4ee9c684 791
709f8308 792
4ee9c684 793/* Generate code to store a string and its length into the
60c514ba 794 st_parameter_XXX structure. */
4ee9c684 795
60c514ba 796static unsigned int
4ee9c684 797set_string (stmtblock_t * block, stmtblock_t * postblock, tree var,
60c514ba 798 enum iofield type, gfc_expr * e)
4ee9c684 799{
800 gfc_se se;
801 tree tmp;
4ee9c684 802 tree io;
803 tree len;
60c514ba 804 gfc_st_parameter_field *p = &st_parameter_field[type];
4ee9c684 805
806 gfc_init_se (&se, NULL);
4ee9c684 807
60c514ba 808 if (p->param_type == IOPARM_ptype_common)
1516b2fb 809 var = fold_build3_loc (input_location, COMPONENT_REF,
810 st_parameter[IOPARM_ptype_common].type,
811 var, TYPE_FIELDS (TREE_TYPE (var)), NULL_TREE);
812 io = fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (p->field),
f75d6b8a 813 var, p->field, NULL_TREE);
1516b2fb 814 len = fold_build3_loc (input_location, COMPONENT_REF,
815 TREE_TYPE (p->field_len),
816 var, p->field_len, NULL_TREE);
4ee9c684 817
260abd71 818 /* Integer variable assigned a format label. */
bc56d052 819 if (e->ts.type == BT_INTEGER
820 && e->rank == 0
821 && e->symtree->n.sym->attr.assign == 1)
4ee9c684 822 {
97c2a00c 823 char * msg;
399aecc1 824 tree cond;
97c2a00c 825
836fa030 826 gfc_conv_label_variable (&se, e);
4ee9c684 827 tmp = GFC_DECL_STRING_LEN (se.expr);
4c796f54 828 cond = fold_build2_loc (input_location, LT_EXPR, logical_type_node,
1516b2fb 829 tmp, build_int_cst (TREE_TYPE (tmp), 0));
97c2a00c 830
87fda26c 831 msg = xasprintf ("Label assigned to variable '%s' (%%ld) is not a format "
832 "label", e->symtree->name);
da6ffc6d 833 gfc_trans_runtime_check (true, false, cond, &se.pre, &e->where, msg,
399aecc1 834 fold_convert (long_integer_type_node, tmp));
434f0922 835 free (msg);
97c2a00c 836
75a70cf9 837 gfc_add_modify (&se.pre, io,
6957b927 838 fold_convert (TREE_TYPE (io), GFC_DECL_ASSIGN_ADDR (se.expr)));
75a70cf9 839 gfc_add_modify (&se.pre, len, GFC_DECL_STRING_LEN (se.expr));
4ee9c684 840 }
841 else
842 {
169f9d09 843 /* General character. */
844 if (e->ts.type == BT_CHARACTER && e->rank == 0)
845 gfc_conv_expr (&se, e);
846 /* Array assigned Hollerith constant or character array. */
bc56d052 847 else if (e->rank > 0 || (e->symtree && e->symtree->n.sym->as->rank > 0))
169f9d09 848 gfc_convert_array_to_string (&se, e);
849 else
850 gcc_unreachable ();
851
4ee9c684 852 gfc_conv_string_parameter (&se);
75a70cf9 853 gfc_add_modify (&se.pre, io, fold_convert (TREE_TYPE (io), se.expr));
9f4d9f83 854 gfc_add_modify (&se.pre, len, fold_convert (TREE_TYPE (len),
855 se.string_length));
4ee9c684 856 }
857
858 gfc_add_block_to_block (block, &se.pre);
859 gfc_add_block_to_block (postblock, &se.post);
60c514ba 860 return p->mask;
4ee9c684 861}
862
863
709f8308 864/* Generate code to store the character (array) and the character length
865 for an internal unit. */
866
60c514ba 867static unsigned int
2ecf364f 868set_internal_unit (stmtblock_t * block, stmtblock_t * post_block,
869 tree var, gfc_expr * e)
709f8308 870{
871 gfc_se se;
872 tree io;
873 tree len;
874 tree desc;
875 tree tmp;
60c514ba 876 gfc_st_parameter_field *p;
877 unsigned int mask;
709f8308 878
879 gfc_init_se (&se, NULL);
880
60c514ba 881 p = &st_parameter_field[IOPARM_dt_internal_unit];
882 mask = p->mask;
1516b2fb 883 io = fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (p->field),
884 var, p->field, NULL_TREE);
885 len = fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (p->field_len),
886 var, p->field_len, NULL_TREE);
60c514ba 887 p = &st_parameter_field[IOPARM_dt_internal_unit_desc];
1516b2fb 888 desc = fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (p->field),
889 var, p->field, NULL_TREE);
709f8308 890
891 gcc_assert (e->ts.type == BT_CHARACTER);
892
893 /* Character scalars. */
894 if (e->rank == 0)
895 {
896 gfc_conv_expr (&se, e);
897 gfc_conv_string_parameter (&se);
898 tmp = se.expr;
7d3075f6 899 se.expr = build_int_cst (pchar_type_node, 0);
709f8308 900 }
901
902 /* Character array. */
6d7e860f 903 else if (e->rank > 0)
709f8308 904 {
1033248c 905 if (is_subref_array (e))
2ecf364f 906 {
907 /* Use a temporary for components of arrays of derived types
908 or substring array references. */
1033248c 909 gfc_conv_subref_array_arg (&se, e, 0,
3446c28b 910 last_dt == READ ? INTENT_IN : INTENT_OUT, false);
389dd41b 911 tmp = build_fold_indirect_ref_loc (input_location,
912 se.expr);
2ecf364f 913 se.expr = gfc_build_addr_expr (pchar_type_node, tmp);
914 tmp = gfc_conv_descriptor_data_get (tmp);
915 }
916 else
917 {
918 /* Return the data pointer and rank from the descriptor. */
5d34a30f 919 gfc_conv_expr_descriptor (&se, e);
2ecf364f 920 tmp = gfc_conv_descriptor_data_get (se.expr);
921 se.expr = gfc_build_addr_expr (pchar_type_node, se.expr);
922 }
709f8308 923 }
924 else
925 gcc_unreachable ();
926
927 /* The cast is needed for character substrings and the descriptor
928 data. */
75a70cf9 929 gfc_add_modify (&se.pre, io, fold_convert (TREE_TYPE (io), tmp));
930 gfc_add_modify (&se.pre, len,
2ecf364f 931 fold_convert (TREE_TYPE (len), se.string_length));
75a70cf9 932 gfc_add_modify (&se.pre, desc, se.expr);
709f8308 933
934 gfc_add_block_to_block (block, &se.pre);
2ecf364f 935 gfc_add_block_to_block (post_block, &se.post);
60c514ba 936 return mask;
709f8308 937}
938
4ee9c684 939/* Add a case to a IO-result switch. */
940
941static void
942add_case (int label_value, gfc_st_label * label, stmtblock_t * body)
943{
944 tree tmp, value;
945
946 if (label == NULL)
947 return; /* No label, no case */
948
35bf1214 949 value = build_int_cst (integer_type_node, label_value);
4ee9c684 950
951 /* Make a backend label for this case. */
b797d6d3 952 tmp = gfc_build_label_decl (NULL_TREE);
4ee9c684 953
954 /* And the case itself. */
b6e3dd65 955 tmp = build_case_label (value, NULL_TREE, tmp);
4ee9c684 956 gfc_add_expr_to_block (body, tmp);
957
958 /* Jump to the label. */
959 tmp = build1_v (GOTO_EXPR, gfc_get_label_decl (label));
960 gfc_add_expr_to_block (body, tmp);
961}
962
963
964/* Generate a switch statement that branches to the correct I/O
965 result label. The last statement of an I/O call stores the
966 result into a variable because there is often cleanup that
967 must be done before the switch, so a temporary would have to
968 be created anyway. */
969
970static void
60c514ba 971io_result (stmtblock_t * block, tree var, gfc_st_label * err_label,
4ee9c684 972 gfc_st_label * end_label, gfc_st_label * eor_label)
973{
974 stmtblock_t body;
975 tree tmp, rc;
60c514ba 976 gfc_st_parameter_field *p = &st_parameter_field[IOPARM_common_flags];
4ee9c684 977
978 /* If no labels are specified, ignore the result instead
979 of building an empty switch. */
980 if (err_label == NULL
981 && end_label == NULL
982 && eor_label == NULL)
983 return;
984
985 /* Build a switch statement. */
986 gfc_start_block (&body);
987
988 /* The label values here must be the same as the values
989 in the library_return enum in the runtime library */
990 add_case (1, err_label, &body);
991 add_case (2, end_label, &body);
992 add_case (3, eor_label, &body);
993
994 tmp = gfc_finish_block (&body);
995
1516b2fb 996 var = fold_build3_loc (input_location, COMPONENT_REF,
997 st_parameter[IOPARM_ptype_common].type,
998 var, TYPE_FIELDS (TREE_TYPE (var)), NULL_TREE);
999 rc = fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (p->field),
1000 var, p->field, NULL_TREE);
1001 rc = fold_build2_loc (input_location, BIT_AND_EXPR, TREE_TYPE (rc),
1002 rc, build_int_cst (TREE_TYPE (rc),
1003 IOPARM_common_libreturn_mask));
4ee9c684 1004
bd37ce3e 1005 tmp = fold_build2_loc (input_location, SWITCH_EXPR, NULL_TREE, rc, tmp);
4ee9c684 1006
1007 gfc_add_expr_to_block (block, tmp);
1008}
1009
1010
1011/* Store the current file and line number to variables so that if a
1012 library call goes awry, we can tell the user where the problem is. */
1013
1014static void
60c514ba 1015set_error_locus (stmtblock_t * block, tree var, locus * where)
4ee9c684 1016{
1017 gfc_file *f;
60c514ba 1018 tree str, locus_file;
4ee9c684 1019 int line;
60c514ba 1020 gfc_st_parameter_field *p = &st_parameter_field[IOPARM_common_filename];
4ee9c684 1021
1516b2fb 1022 locus_file = fold_build3_loc (input_location, COMPONENT_REF,
1023 st_parameter[IOPARM_ptype_common].type,
1024 var, TYPE_FIELDS (TREE_TYPE (var)), NULL_TREE);
1025 locus_file = fold_build3_loc (input_location, COMPONENT_REF,
1026 TREE_TYPE (p->field), locus_file,
1027 p->field, NULL_TREE);
b0057e95 1028 f = where->lb->file;
60c514ba 1029 str = gfc_build_cstring_const (f->filename);
4ee9c684 1030
60c514ba 1031 str = gfc_build_addr_expr (pchar_type_node, str);
75a70cf9 1032 gfc_add_modify (block, locus_file, str);
4ee9c684 1033
b31f705b 1034 line = LOCATION_LINE (where->lb->location);
60c514ba 1035 set_parameter_const (block, var, IOPARM_common_line, line);
4ee9c684 1036}
1037
1038
1039/* Translate an OPEN statement. */
1040
1041tree
1042gfc_trans_open (gfc_code * code)
1043{
1044 stmtblock_t block, post_block;
1045 gfc_open *p;
60c514ba 1046 tree tmp, var;
1047 unsigned int mask = 0;
4ee9c684 1048
60c514ba 1049 gfc_start_block (&block);
4ee9c684 1050 gfc_init_block (&post_block);
1051
60c514ba 1052 var = gfc_create_var (st_parameter[IOPARM_ptype_open].type, "open_parm");
1053
1054 set_error_locus (&block, var, &code->loc);
4ee9c684 1055 p = code->ext.open;
1056
50ad5fa2 1057 if (p->iomsg)
1058 mask |= set_string (&block, &post_block, var, IOPARM_common_iomsg,
1059 p->iomsg);
1060
1061 if (p->iostat)
1062 mask |= set_parameter_ref (&block, &post_block, var, IOPARM_common_iostat,
1063 p->iostat);
1064
1065 if (p->err)
1066 mask |= IOPARM_common_err;
4ee9c684 1067
1068 if (p->file)
60c514ba 1069 mask |= set_string (&block, &post_block, var, IOPARM_open_file, p->file);
4ee9c684 1070
1071 if (p->status)
60c514ba 1072 mask |= set_string (&block, &post_block, var, IOPARM_open_status,
1073 p->status);
4ee9c684 1074
1075 if (p->access)
60c514ba 1076 mask |= set_string (&block, &post_block, var, IOPARM_open_access,
1077 p->access);
4ee9c684 1078
1079 if (p->form)
60c514ba 1080 mask |= set_string (&block, &post_block, var, IOPARM_open_form, p->form);
4ee9c684 1081
1082 if (p->recl)
f26dc717 1083 mask |= set_parameter_value (&block, var, IOPARM_open_recl_in,
c83059be 1084 p->recl);
4ee9c684 1085
1086 if (p->blank)
60c514ba 1087 mask |= set_string (&block, &post_block, var, IOPARM_open_blank,
1088 p->blank);
4ee9c684 1089
1090 if (p->position)
60c514ba 1091 mask |= set_string (&block, &post_block, var, IOPARM_open_position,
1092 p->position);
4ee9c684 1093
1094 if (p->action)
60c514ba 1095 mask |= set_string (&block, &post_block, var, IOPARM_open_action,
1096 p->action);
4ee9c684 1097
1098 if (p->delim)
60c514ba 1099 mask |= set_string (&block, &post_block, var, IOPARM_open_delim,
1100 p->delim);
4ee9c684 1101
1102 if (p->pad)
60c514ba 1103 mask |= set_string (&block, &post_block, var, IOPARM_open_pad, p->pad);
4ee9c684 1104
ff6af856 1105 if (p->decimal)
1106 mask |= set_string (&block, &post_block, var, IOPARM_open_decimal,
1107 p->decimal);
1108
1109 if (p->encoding)
1110 mask |= set_string (&block, &post_block, var, IOPARM_open_encoding,
1111 p->encoding);
1112
1113 if (p->round)
1114 mask |= set_string (&block, &post_block, var, IOPARM_open_round, p->round);
1115
1116 if (p->sign)
1117 mask |= set_string (&block, &post_block, var, IOPARM_open_sign, p->sign);
1118
1119 if (p->asynchronous)
1120 mask |= set_string (&block, &post_block, var, IOPARM_open_asynchronous,
1121 p->asynchronous);
1122
9e94d29f 1123 if (p->convert)
1124 mask |= set_string (&block, &post_block, var, IOPARM_open_convert,
1125 p->convert);
4442e7ec 1126
82b12af7 1127 if (p->newunit)
1128 mask |= set_parameter_ref (&block, &post_block, var, IOPARM_open_newunit,
1129 p->newunit);
9e94d29f 1130
b3db57e8 1131 if (p->cc)
1132 mask |= set_string (&block, &post_block, var, IOPARM_open_cc, p->cc);
1133
1134 if (p->share)
1135 mask |= set_string (&block, &post_block, var, IOPARM_open_share, p->share);
1136
1137 mask |= set_parameter_const (&block, var, IOPARM_open_readonly, p->readonly);
1138
60c514ba 1139 set_parameter_const (&block, var, IOPARM_common_flags, mask);
1140
50ad5fa2 1141 if (p->unit)
f26dc717 1142 set_parameter_value_chk (&block, p->iostat, var, IOPARM_common_unit, p->unit);
50ad5fa2 1143 else
1144 set_parameter_const (&block, var, IOPARM_common_unit, 0);
1145
86f2ad37 1146 tmp = gfc_build_addr_expr (NULL_TREE, var);
389dd41b 1147 tmp = build_call_expr_loc (input_location,
1148 iocall[IOCALL_OPEN], 1, tmp);
4ee9c684 1149 gfc_add_expr_to_block (&block, tmp);
1150
1151 gfc_add_block_to_block (&block, &post_block);
1152
60c514ba 1153 io_result (&block, var, p->err, NULL, NULL);
4ee9c684 1154
1155 return gfc_finish_block (&block);
1156}
1157
1158
1159/* Translate a CLOSE statement. */
1160
1161tree
1162gfc_trans_close (gfc_code * code)
1163{
1164 stmtblock_t block, post_block;
1165 gfc_close *p;
60c514ba 1166 tree tmp, var;
1167 unsigned int mask = 0;
4ee9c684 1168
60c514ba 1169 gfc_start_block (&block);
4ee9c684 1170 gfc_init_block (&post_block);
1171
60c514ba 1172 var = gfc_create_var (st_parameter[IOPARM_ptype_close].type, "close_parm");
1173
1174 set_error_locus (&block, var, &code->loc);
4ee9c684 1175 p = code->ext.close;
1176
65f9e5fc 1177 if (p->iomsg)
60c514ba 1178 mask |= set_string (&block, &post_block, var, IOPARM_common_iomsg,
1179 p->iomsg);
65f9e5fc 1180
4ee9c684 1181 if (p->iostat)
60c514ba 1182 mask |= set_parameter_ref (&block, &post_block, var, IOPARM_common_iostat,
1183 p->iostat);
4ee9c684 1184
1185 if (p->err)
60c514ba 1186 mask |= IOPARM_common_err;
1187
50ad5fa2 1188 if (p->status)
1189 mask |= set_string (&block, &post_block, var, IOPARM_close_status,
1190 p->status);
1191
60c514ba 1192 set_parameter_const (&block, var, IOPARM_common_flags, mask);
4ee9c684 1193
50ad5fa2 1194 if (p->unit)
f26dc717 1195 set_parameter_value_chk (&block, p->iostat, var, IOPARM_common_unit, p->unit);
50ad5fa2 1196 else
1197 set_parameter_const (&block, var, IOPARM_common_unit, 0);
1198
86f2ad37 1199 tmp = gfc_build_addr_expr (NULL_TREE, var);
389dd41b 1200 tmp = build_call_expr_loc (input_location,
1201 iocall[IOCALL_CLOSE], 1, tmp);
4ee9c684 1202 gfc_add_expr_to_block (&block, tmp);
1203
1204 gfc_add_block_to_block (&block, &post_block);
1205
60c514ba 1206 io_result (&block, var, p->err, NULL, NULL);
4ee9c684 1207
1208 return gfc_finish_block (&block);
1209}
1210
1211
1212/* Common subroutine for building a file positioning statement. */
1213
1214static tree
1215build_filepos (tree function, gfc_code * code)
1216{
65f9e5fc 1217 stmtblock_t block, post_block;
4ee9c684 1218 gfc_filepos *p;
60c514ba 1219 tree tmp, var;
1220 unsigned int mask = 0;
4ee9c684 1221
1222 p = code->ext.filepos;
1223
60c514ba 1224 gfc_start_block (&block);
65f9e5fc 1225 gfc_init_block (&post_block);
4ee9c684 1226
60c514ba 1227 var = gfc_create_var (st_parameter[IOPARM_ptype_filepos].type,
1228 "filepos_parm");
1229
1230 set_error_locus (&block, var, &code->loc);
4ee9c684 1231
65f9e5fc 1232 if (p->iomsg)
60c514ba 1233 mask |= set_string (&block, &post_block, var, IOPARM_common_iomsg,
1234 p->iomsg);
65f9e5fc 1235
4ee9c684 1236 if (p->iostat)
f26dc717 1237 mask |= set_parameter_ref (&block, &post_block, var,
1238 IOPARM_common_iostat, p->iostat);
4ee9c684 1239
1240 if (p->err)
60c514ba 1241 mask |= IOPARM_common_err;
1242
1243 set_parameter_const (&block, var, IOPARM_common_flags, mask);
4ee9c684 1244
50ad5fa2 1245 if (p->unit)
f26dc717 1246 set_parameter_value_chk (&block, p->iostat, var, IOPARM_common_unit,
1247 p->unit);
50ad5fa2 1248 else
1249 set_parameter_const (&block, var, IOPARM_common_unit, 0);
1250
86f2ad37 1251 tmp = gfc_build_addr_expr (NULL_TREE, var);
389dd41b 1252 tmp = build_call_expr_loc (input_location,
1253 function, 1, tmp);
4ee9c684 1254 gfc_add_expr_to_block (&block, tmp);
1255
65f9e5fc 1256 gfc_add_block_to_block (&block, &post_block);
1257
60c514ba 1258 io_result (&block, var, p->err, NULL, NULL);
4ee9c684 1259
1260 return gfc_finish_block (&block);
1261}
1262
1263
1264/* Translate a BACKSPACE statement. */
1265
1266tree
1267gfc_trans_backspace (gfc_code * code)
1268{
60c514ba 1269 return build_filepos (iocall[IOCALL_BACKSPACE], code);
4ee9c684 1270}
1271
1272
1273/* Translate an ENDFILE statement. */
1274
1275tree
1276gfc_trans_endfile (gfc_code * code)
1277{
60c514ba 1278 return build_filepos (iocall[IOCALL_ENDFILE], code);
4ee9c684 1279}
1280
1281
1282/* Translate a REWIND statement. */
1283
1284tree
1285gfc_trans_rewind (gfc_code * code)
1286{
60c514ba 1287 return build_filepos (iocall[IOCALL_REWIND], code);
4ee9c684 1288}
1289
1290
6c306f90 1291/* Translate a FLUSH statement. */
1292
1293tree
1294gfc_trans_flush (gfc_code * code)
1295{
60c514ba 1296 return build_filepos (iocall[IOCALL_FLUSH], code);
6c306f90 1297}
1298
1299
4ee9c684 1300/* Translate the non-IOLENGTH form of an INQUIRE statement. */
1301
1302tree
1303gfc_trans_inquire (gfc_code * code)
1304{
1305 stmtblock_t block, post_block;
1306 gfc_inquire *p;
60c514ba 1307 tree tmp, var;
ff6af856 1308 unsigned int mask = 0, mask2 = 0;
4ee9c684 1309
60c514ba 1310 gfc_start_block (&block);
4ee9c684 1311 gfc_init_block (&post_block);
1312
60c514ba 1313 var = gfc_create_var (st_parameter[IOPARM_ptype_inquire].type,
1314 "inquire_parm");
1315
1316 set_error_locus (&block, var, &code->loc);
4ee9c684 1317 p = code->ext.inquire;
1318
65f9e5fc 1319 if (p->iomsg)
60c514ba 1320 mask |= set_string (&block, &post_block, var, IOPARM_common_iomsg,
1321 p->iomsg);
65f9e5fc 1322
4ee9c684 1323 if (p->iostat)
60c514ba 1324 mask |= set_parameter_ref (&block, &post_block, var, IOPARM_common_iostat,
1325 p->iostat);
4ee9c684 1326
50ad5fa2 1327 if (p->err)
1328 mask |= IOPARM_common_err;
1329
1330 /* Sanity check. */
1331 if (p->unit && p->file)
1332 gfc_error ("INQUIRE statement at %L cannot contain both FILE and UNIT specifiers", &code->loc);
1333
1334 if (p->file)
1335 mask |= set_string (&block, &post_block, var, IOPARM_inquire_file,
1336 p->file);
1337
4ee9c684 1338 if (p->exist)
f26dc717 1339 mask |= set_parameter_ref (&block, &post_block, var, IOPARM_inquire_exist,
07671b0c 1340 p->exist);
4ee9c684 1341
1342 if (p->opened)
60c514ba 1343 mask |= set_parameter_ref (&block, &post_block, var, IOPARM_inquire_opened,
1344 p->opened);
4ee9c684 1345
1346 if (p->number)
60c514ba 1347 mask |= set_parameter_ref (&block, &post_block, var, IOPARM_inquire_number,
1348 p->number);
4ee9c684 1349
1350 if (p->named)
60c514ba 1351 mask |= set_parameter_ref (&block, &post_block, var, IOPARM_inquire_named,
1352 p->named);
4ee9c684 1353
1354 if (p->name)
60c514ba 1355 mask |= set_string (&block, &post_block, var, IOPARM_inquire_name,
1356 p->name);
4ee9c684 1357
1358 if (p->access)
60c514ba 1359 mask |= set_string (&block, &post_block, var, IOPARM_inquire_access,
1360 p->access);
4ee9c684 1361
1362 if (p->sequential)
60c514ba 1363 mask |= set_string (&block, &post_block, var, IOPARM_inquire_sequential,
1364 p->sequential);
4ee9c684 1365
1366 if (p->direct)
60c514ba 1367 mask |= set_string (&block, &post_block, var, IOPARM_inquire_direct,
1368 p->direct);
4ee9c684 1369
1370 if (p->form)
60c514ba 1371 mask |= set_string (&block, &post_block, var, IOPARM_inquire_form,
1372 p->form);
4ee9c684 1373
1374 if (p->formatted)
60c514ba 1375 mask |= set_string (&block, &post_block, var, IOPARM_inquire_formatted,
1376 p->formatted);
4ee9c684 1377
1378 if (p->unformatted)
60c514ba 1379 mask |= set_string (&block, &post_block, var, IOPARM_inquire_unformatted,
1380 p->unformatted);
4ee9c684 1381
1382 if (p->recl)
60c514ba 1383 mask |= set_parameter_ref (&block, &post_block, var,
1384 IOPARM_inquire_recl_out, p->recl);
4ee9c684 1385
1386 if (p->nextrec)
60c514ba 1387 mask |= set_parameter_ref (&block, &post_block, var,
1388 IOPARM_inquire_nextrec, p->nextrec);
4ee9c684 1389
1390 if (p->blank)
60c514ba 1391 mask |= set_string (&block, &post_block, var, IOPARM_inquire_blank,
1392 p->blank);
4ee9c684 1393
15618afa 1394 if (p->delim)
1395 mask |= set_string (&block, &post_block, var, IOPARM_inquire_delim,
1396 p->delim);
1397
4ee9c684 1398 if (p->position)
60c514ba 1399 mask |= set_string (&block, &post_block, var, IOPARM_inquire_position,
1400 p->position);
4ee9c684 1401
1402 if (p->action)
60c514ba 1403 mask |= set_string (&block, &post_block, var, IOPARM_inquire_action,
1404 p->action);
4ee9c684 1405
1406 if (p->read)
60c514ba 1407 mask |= set_string (&block, &post_block, var, IOPARM_inquire_read,
1408 p->read);
4ee9c684 1409
1410 if (p->write)
60c514ba 1411 mask |= set_string (&block, &post_block, var, IOPARM_inquire_write,
1412 p->write);
4ee9c684 1413
1414 if (p->readwrite)
60c514ba 1415 mask |= set_string (&block, &post_block, var, IOPARM_inquire_readwrite,
1416 p->readwrite);
4ee9c684 1417
60065042 1418 if (p->pad)
60c514ba 1419 mask |= set_string (&block, &post_block, var, IOPARM_inquire_pad,
1420 p->pad);
4442e7ec 1421
9e94d29f 1422 if (p->convert)
1423 mask |= set_string (&block, &post_block, var, IOPARM_inquire_convert,
1424 p->convert);
1425
e83964b2 1426 if (p->strm_pos)
1427 mask |= set_parameter_ref (&block, &post_block, var,
1428 IOPARM_inquire_strm_pos_out, p->strm_pos);
1429
ff6af856 1430 /* The second series of flags. */
1431 if (p->asynchronous)
1432 mask2 |= set_string (&block, &post_block, var, IOPARM_inquire_asynchronous,
1433 p->asynchronous);
1434
1435 if (p->decimal)
1436 mask2 |= set_string (&block, &post_block, var, IOPARM_inquire_decimal,
1437 p->decimal);
1438
1439 if (p->encoding)
1440 mask2 |= set_string (&block, &post_block, var, IOPARM_inquire_encoding,
1441 p->encoding);
1442
1443 if (p->round)
1444 mask2 |= set_string (&block, &post_block, var, IOPARM_inquire_round,
1445 p->round);
1446
1447 if (p->sign)
1448 mask2 |= set_string (&block, &post_block, var, IOPARM_inquire_sign,
1449 p->sign);
1450
1451 if (p->pending)
1452 mask2 |= set_parameter_ref (&block, &post_block, var,
1453 IOPARM_inquire_pending, p->pending);
1454
1455 if (p->size)
1456 mask2 |= set_parameter_ref (&block, &post_block, var, IOPARM_inquire_size,
1457 p->size);
1458
1459 if (p->id)
15618afa 1460 mask2 |= set_parameter_ref (&block, &post_block,var, IOPARM_inquire_id,
1461 p->id);
3f693491 1462 if (p->iqstream)
1463 mask2 |= set_string (&block, &post_block, var, IOPARM_inquire_iqstream,
1464 p->iqstream);
ff6af856 1465
b3db57e8 1466 if (p->share)
1467 mask2 |= set_string (&block, &post_block, var, IOPARM_inquire_share,
1468 p->share);
1469
1470 if (p->cc)
1471 mask2 |= set_string (&block, &post_block, var, IOPARM_inquire_cc, p->cc);
1472
ff6af856 1473 if (mask2)
b5d015e3 1474 mask |= set_parameter_const (&block, var, IOPARM_inquire_flags2, mask2);
ff6af856 1475
60c514ba 1476 set_parameter_const (&block, var, IOPARM_common_flags, mask);
4ee9c684 1477
50ad5fa2 1478 if (p->unit)
f26dc717 1479 {
1480 set_parameter_value (&block, var, IOPARM_common_unit, p->unit);
1481 set_parameter_value_inquire (&block, var, IOPARM_common_unit, p->unit);
1482 }
50ad5fa2 1483 else
1484 set_parameter_const (&block, var, IOPARM_common_unit, 0);
1485
86f2ad37 1486 tmp = gfc_build_addr_expr (NULL_TREE, var);
389dd41b 1487 tmp = build_call_expr_loc (input_location,
1488 iocall[IOCALL_INQUIRE], 1, tmp);
4ee9c684 1489 gfc_add_expr_to_block (&block, tmp);
1490
1491 gfc_add_block_to_block (&block, &post_block);
1492
60c514ba 1493 io_result (&block, var, p->err, NULL, NULL);
4ee9c684 1494
1495 return gfc_finish_block (&block);
1496}
1497
ff6af856 1498
1499tree
1500gfc_trans_wait (gfc_code * code)
1501{
1502 stmtblock_t block, post_block;
1503 gfc_wait *p;
1504 tree tmp, var;
1505 unsigned int mask = 0;
1506
1507 gfc_start_block (&block);
1508 gfc_init_block (&post_block);
1509
1510 var = gfc_create_var (st_parameter[IOPARM_ptype_wait].type,
1511 "wait_parm");
1512
1513 set_error_locus (&block, var, &code->loc);
1514 p = code->ext.wait;
1515
1516 /* Set parameters here. */
1517 if (p->iomsg)
1518 mask |= set_string (&block, &post_block, var, IOPARM_common_iomsg,
1519 p->iomsg);
1520
1521 if (p->iostat)
1522 mask |= set_parameter_ref (&block, &post_block, var, IOPARM_common_iostat,
1523 p->iostat);
1524
1525 if (p->err)
1526 mask |= IOPARM_common_err;
1527
1528 if (p->id)
629c30bb 1529 mask |= set_parameter_ref (&block, &post_block, var, IOPARM_wait_id, p->id);
ff6af856 1530
1531 set_parameter_const (&block, var, IOPARM_common_flags, mask);
1532
1533 if (p->unit)
f26dc717 1534 set_parameter_value_chk (&block, p->iostat, var, IOPARM_common_unit, p->unit);
ff6af856 1535
86f2ad37 1536 tmp = gfc_build_addr_expr (NULL_TREE, var);
389dd41b 1537 tmp = build_call_expr_loc (input_location,
1538 iocall[IOCALL_WAIT], 1, tmp);
ff6af856 1539 gfc_add_expr_to_block (&block, tmp);
1540
1541 gfc_add_block_to_block (&block, &post_block);
1542
1543 io_result (&block, var, p->err, NULL, NULL);
1544
1545 return gfc_finish_block (&block);
1546
1547}
1548
4ee9c684 1549
fc2a7c27 1550/* nml_full_name builds up the fully qualified name of a
74f5b093 1551 derived type component. '+' is used to denote a type extension. */
fc2a7c27 1552
1553static char*
74f5b093 1554nml_full_name (const char* var_name, const char* cmp_name, bool parent)
4ee9c684 1555{
fc2a7c27 1556 int full_name_length;
1557 char * full_name;
1558
1559 full_name_length = strlen (var_name) + strlen (cmp_name) + 1;
dfa3fb6a 1560 full_name = XCNEWVEC (char, full_name_length + 1);
fc2a7c27 1561 strcpy (full_name, var_name);
74f5b093 1562 full_name = strcat (full_name, parent ? "+" : "%");
fc2a7c27 1563 full_name = strcat (full_name, cmp_name);
1564 return full_name;
4ee9c684 1565}
1566
95fad61e 1567
fc2a7c27 1568/* nml_get_addr_expr builds an address expression from the
1569 gfc_symbol or gfc_component backend_decl's. An offset is
1570 provided so that the address of an element of an array of
1571 derived types is returned. This is used in the runtime to
f6d0e37a 1572 determine that span of the derived type. */
fc2a7c27 1573
1574static tree
1575nml_get_addr_expr (gfc_symbol * sym, gfc_component * c,
1576 tree base_addr)
1577{
1578 tree decl = NULL_TREE;
1579 tree tmp;
fc2a7c27 1580
1581 if (sym)
1582 {
1583 sym->attr.referenced = 1;
1584 decl = gfc_get_symbol_decl (sym);
bc055333 1585
1586 /* If this is the enclosing function declaration, use
1587 the fake result instead. */
1588 if (decl == current_function_decl)
1589 decl = gfc_get_fake_result_decl (sym, 0);
1590 else if (decl == DECL_CONTEXT (current_function_decl))
1591 decl = gfc_get_fake_result_decl (sym, 1);
fc2a7c27 1592 }
1593 else
1594 decl = c->backend_decl;
1595
fe732a9b 1596 gcc_assert (decl && (TREE_CODE (decl) == FIELD_DECL
1597 || VAR_P (decl)
1598 || TREE_CODE (decl) == PARM_DECL
1599 || TREE_CODE (decl) == COMPONENT_REF));
fc2a7c27 1600
1601 tmp = decl;
1602
1603 /* Build indirect reference, if dummy argument. */
1604
95fad61e 1605 if (POINTER_TYPE_P (TREE_TYPE(tmp)))
1606 tmp = build_fold_indirect_ref_loc (input_location, tmp);
fc2a7c27 1607
1608 /* Treat the component of a derived type, using base_addr for
1609 the derived type. */
1610
1611 if (TREE_CODE (decl) == FIELD_DECL)
1516b2fb 1612 tmp = fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (tmp),
1613 base_addr, tmp, NULL_TREE);
fc2a7c27 1614
0a0ee506 1615 if (GFC_CLASS_TYPE_P (TREE_TYPE (tmp))
1616 && GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (gfc_class_data_get (tmp))))
1617 tmp = gfc_class_data_get (tmp);
1618
95fad61e 1619 if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (tmp)))
1620 tmp = gfc_conv_array_data (tmp);
1621 else
1622 {
1623 if (!POINTER_TYPE_P (TREE_TYPE (tmp)))
1624 tmp = gfc_build_addr_expr (NULL_TREE, tmp);
fc2a7c27 1625
95fad61e 1626 if (TREE_CODE (TREE_TYPE (tmp)) == ARRAY_TYPE)
1627 tmp = gfc_build_array_ref (tmp, gfc_index_zero_node, NULL);
fc2a7c27 1628
95fad61e 1629 if (!POINTER_TYPE_P (TREE_TYPE (tmp)))
1630 tmp = build_fold_indirect_ref_loc (input_location,
389dd41b 1631 tmp);
95fad61e 1632 }
fc2a7c27 1633
1634 gcc_assert (tmp && POINTER_TYPE_P (TREE_TYPE (tmp)));
1635
1636 return tmp;
1637}
2cd58ad7 1638
95fad61e 1639
fc2a7c27 1640/* For an object VAR_NAME whose base address is BASE_ADDR, generate a
60c514ba 1641 call to iocall[IOCALL_SET_NML_VAL]. For derived type variable, recursively
1642 generate calls to iocall[IOCALL_SET_NML_VAL] for each component. */
2cd58ad7 1643
fc2a7c27 1644#define IARG(i) build_int_cst (gfc_array_index_type, i)
2cd58ad7 1645
1646static void
fc2a7c27 1647transfer_namelist_element (stmtblock_t * block, const char * var_name,
1648 gfc_symbol * sym, gfc_component * c,
1649 tree base_addr)
2cd58ad7 1650{
fc2a7c27 1651 gfc_typespec * ts = NULL;
1652 gfc_array_spec * as = NULL;
1653 tree addr_expr = NULL;
1654 tree dt = NULL;
1655 tree string;
1656 tree tmp;
fc2a7c27 1657 tree dtype;
60c514ba 1658 tree dt_parm_addr;
95fad61e 1659 tree decl = NULL_TREE;
9803f9eb 1660 tree gfc_int4_type_node = gfc_get_int_type (4);
9f732c4e 1661 tree dtio_proc = null_pointer_node;
1662 tree vtable = null_pointer_node;
4442e7ec 1663 int n_dim;
fc2a7c27 1664 int rank = 0;
2cd58ad7 1665
fc2a7c27 1666 gcc_assert (sym || c);
2cd58ad7 1667
fc2a7c27 1668 /* Build the namelist object name. */
1669
1670 string = gfc_build_cstring_const (var_name);
1671 string = gfc_build_addr_expr (pchar_type_node, string);
1672
1673 /* Build ts, as and data address using symbol or component. */
1674
0a0ee506 1675 ts = sym ? &sym->ts : &c->ts;
1676
1677 if (ts->type != BT_CLASS)
1678 as = sym ? sym->as : c->as;
1679 else
1680 as = sym ? CLASS_DATA (sym)->as : CLASS_DATA (c)->as;
fc2a7c27 1681
1682 addr_expr = nml_get_addr_expr (sym, c, base_addr);
1683
1684 if (as)
1685 rank = as->rank;
1686
1687 if (rank)
2cd58ad7 1688 {
0a0ee506 1689 decl = sym ? sym->backend_decl : c->backend_decl;
95fad61e 1690 if (sym && sym->attr.dummy)
1691 decl = build_fold_indirect_ref_loc (input_location, decl);
0a0ee506 1692
1693 if (ts->type == BT_CLASS)
1694 decl = gfc_class_data_get (decl);
95fad61e 1695 dt = TREE_TYPE (decl);
fc2a7c27 1696 dtype = gfc_get_dtype (dt);
2cd58ad7 1697 }
fc2a7c27 1698 else
1699 {
d9c7c3e3 1700 dt = gfc_typenode_for_spec (ts);
1701 dtype = gfc_get_dtype_rank_type (0, dt);
2cd58ad7 1702 }
1703
fc2a7c27 1704 /* Build up the arguments for the transfer call.
1705 The call for the scalar part transfers:
1706 (address, name, type, kind or string_length, dtype) */
1707
86f2ad37 1708 dt_parm_addr = gfc_build_addr_expr (NULL_TREE, dt_parm);
fc2a7c27 1709
9f732c4e 1710 /* Check if the derived type has a specific DTIO for the mode.
1711 Note that although namelist io is forbidden to have a format
1712 list, the specific subroutine is of the formatted kind. */
259bcf21 1713 if (ts->type == BT_DERIVED || ts->type == BT_CLASS)
9f732c4e 1714 {
259bcf21 1715 gfc_symbol *derived;
1716 if (ts->type==BT_CLASS)
1717 derived = ts->u.derived->components->ts.u.derived;
1718 else
1719 derived = ts->u.derived;
1720
1721 gfc_symtree *tb_io_st = gfc_find_typebound_dtio_proc (derived,
1722 last_dt == WRITE, true);
1723
1724 if (ts->type == BT_CLASS && tb_io_st)
1725 {
1726 // polymorphic DTIO call (based on the dynamic type)
1727 gfc_se se;
1728 gfc_symtree *st = gfc_find_symtree (sym->ns->sym_root, sym->name);
1729 // build vtable expr
1730 gfc_expr *expr = gfc_get_variable_expr (st);
1731 gfc_add_vptr_component (expr);
1732 gfc_init_se (&se, NULL);
1733 se.want_pointer = 1;
1734 gfc_conv_expr (&se, expr);
1735 vtable = se.expr;
1736 // build dtio expr
1737 gfc_add_component_ref (expr,
1738 tb_io_st->n.tb->u.generic->specific_st->name);
1739 gfc_init_se (&se, NULL);
1740 se.want_pointer = 1;
1741 gfc_conv_expr (&se, expr);
1742 gfc_free_expr (expr);
1743 dtio_proc = se.expr;
1744 }
1745 else
9f732c4e 1746 {
259bcf21 1747 // non-polymorphic DTIO call (based on the declared type)
1748 gfc_symbol *dtio_sub = gfc_find_specific_dtio_proc (derived,
1749 last_dt == WRITE, true);
1750 if (dtio_sub != NULL)
1751 {
1752 dtio_proc = gfc_get_symbol_decl (dtio_sub);
1753 dtio_proc = gfc_build_addr_expr (NULL, dtio_proc);
1754 gfc_symbol *vtab = gfc_find_derived_vtab (derived);
1755 vtable = vtab->backend_decl;
1756 if (vtable == NULL_TREE)
1757 vtable = gfc_get_symbol_decl (vtab);
1758 vtable = gfc_build_addr_expr (pvoid_type_node, vtable);
1759 }
9f732c4e 1760 }
1761 }
1762
fc2a7c27 1763 if (ts->type == BT_CHARACTER)
eeebe20b 1764 tmp = ts->u.cl->backend_decl;
fc2a7c27 1765 else
c2f47e15 1766 tmp = build_int_cst (gfc_charlen_type_node, 0);
9f732c4e 1767
2b09e331 1768 if (dtio_proc == null_pointer_node)
9f732c4e 1769 tmp = build_call_expr_loc (input_location,
1770 iocall[IOCALL_SET_NML_VAL], 6,
1771 dt_parm_addr, addr_expr, string,
1772 build_int_cst (gfc_int4_type_node, ts->kind),
1773 tmp, dtype);
1774 else
1775 tmp = build_call_expr_loc (input_location,
1776 iocall[IOCALL_SET_NML_DTIO_VAL], 8,
1777 dt_parm_addr, addr_expr, string,
1778 build_int_cst (gfc_int4_type_node, ts->kind),
1779 tmp, dtype, dtio_proc, vtable);
2cd58ad7 1780 gfc_add_expr_to_block (block, tmp);
fc2a7c27 1781
1782 /* If the object is an array, transfer rank times:
1783 (null pointer, name, stride, lbound, ubound) */
1784
1785 for ( n_dim = 0 ; n_dim < rank ; n_dim++ )
1786 {
389dd41b 1787 tmp = build_call_expr_loc (input_location,
1788 iocall[IOCALL_SET_NML_VAL_DIM], 5,
c2f47e15 1789 dt_parm_addr,
9803f9eb 1790 build_int_cst (gfc_int4_type_node, n_dim),
95fad61e 1791 gfc_conv_array_stride (decl, n_dim),
1792 gfc_conv_array_lbound (decl, n_dim),
1793 gfc_conv_array_ubound (decl, n_dim));
fc2a7c27 1794 gfc_add_expr_to_block (block, tmp);
1795 }
1796
9f732c4e 1797 if (gfc_bt_struct (ts->type) && ts->u.derived->components
1798 && dtio_proc == null_pointer_node)
fc2a7c27 1799 {
1800 gfc_component *cmp;
1801
1802 /* Provide the RECORD_TYPE to build component references. */
1803
389dd41b 1804 tree expr = build_fold_indirect_ref_loc (input_location,
1805 addr_expr);
fc2a7c27 1806
eeebe20b 1807 for (cmp = ts->u.derived->components; cmp; cmp = cmp->next)
fc2a7c27 1808 {
74f5b093 1809 char *full_name = nml_full_name (var_name, cmp->name,
1810 ts->u.derived->attr.extension);
fc2a7c27 1811 transfer_namelist_element (block,
1812 full_name,
1813 NULL, cmp, expr);
434f0922 1814 free (full_name);
fc2a7c27 1815 }
1816 }
2cd58ad7 1817}
4ee9c684 1818
fc2a7c27 1819#undef IARG
fc2a7c27 1820
4ee9c684 1821/* Create a data transfer statement. Not all of the fields are valid
1822 for both reading and writing, but improper use has been filtered
1823 out by now. */
1824
1825static tree
60c514ba 1826build_dt (tree function, gfc_code * code)
4ee9c684 1827{
2ecf364f 1828 stmtblock_t block, post_block, post_end_block, post_iu_block;
4ee9c684 1829 gfc_dt *dt;
60c514ba 1830 tree tmp, var;
fc2a7c27 1831 gfc_expr *nmlname;
2cd58ad7 1832 gfc_namelist *nml;
0db1fafd 1833 unsigned int mask = 0;
4ee9c684 1834
60c514ba 1835 gfc_start_block (&block);
4ee9c684 1836 gfc_init_block (&post_block);
60c514ba 1837 gfc_init_block (&post_end_block);
2ecf364f 1838 gfc_init_block (&post_iu_block);
60c514ba 1839
1840 var = gfc_create_var (st_parameter[IOPARM_ptype_dt].type, "dt_parm");
1841
1842 set_error_locus (&block, var, &code->loc);
4ee9c684 1843
60c514ba 1844 if (last_dt == IOLENGTH)
1845 {
1846 gfc_inquire *inq;
1847
1848 inq = code->ext.inquire;
4ee9c684 1849
60c514ba 1850 /* First check that preconditions are met. */
1851 gcc_assert (inq != NULL);
1852 gcc_assert (inq->iolength != NULL);
1853
1854 /* Connect to the iolength variable. */
1855 mask |= set_parameter_ref (&block, &post_end_block, var,
1856 IOPARM_dt_iolength, inq->iolength);
1857 dt = NULL;
1858 }
1859 else
1860 {
1861 dt = code->ext.dt;
1862 gcc_assert (dt != NULL);
1863 }
6799e2f8 1864
60c514ba 1865 if (dt && dt->io_unit)
4ee9c684 1866 {
1867 if (dt->io_unit->ts.type == BT_CHARACTER)
1868 {
2ecf364f 1869 mask |= set_internal_unit (&block, &post_iu_block,
1870 var, dt->io_unit);
487c959a 1871 set_parameter_const (&block, var, IOPARM_common_unit,
e7c4560c 1872 dt->io_unit->ts.kind == 1 ?
1873 GFC_INTERNAL_UNIT : GFC_INTERNAL_UNIT4);
4ee9c684 1874 }
4ee9c684 1875 }
60c514ba 1876 else
1877 set_parameter_const (&block, var, IOPARM_common_unit, 0);
4ee9c684 1878
60c514ba 1879 if (dt)
1880 {
50ad5fa2 1881 if (dt->iomsg)
1882 mask |= set_string (&block, &post_block, var, IOPARM_common_iomsg,
1883 dt->iomsg);
1884
1885 if (dt->iostat)
1886 mask |= set_parameter_ref (&block, &post_end_block, var,
1887 IOPARM_common_iostat, dt->iostat);
1888
1889 if (dt->err)
1890 mask |= IOPARM_common_err;
1891
1892 if (dt->eor)
1893 mask |= IOPARM_common_eor;
1894
1895 if (dt->end)
1896 mask |= IOPARM_common_end;
1897
ff6af856 1898 if (dt->id)
1899 mask |= set_parameter_ref (&block, &post_end_block, var,
1900 IOPARM_dt_id, dt->id);
1901
1902 if (dt->pos)
f26dc717 1903 mask |= set_parameter_value (&block, var, IOPARM_dt_pos, dt->pos);
ff6af856 1904
1905 if (dt->asynchronous)
f26dc717 1906 mask |= set_string (&block, &post_block, var,
1907 IOPARM_dt_asynchronous, dt->asynchronous);
ff6af856 1908
1909 if (dt->blank)
1910 mask |= set_string (&block, &post_block, var, IOPARM_dt_blank,
1911 dt->blank);
1912
1913 if (dt->decimal)
1914 mask |= set_string (&block, &post_block, var, IOPARM_dt_decimal,
1915 dt->decimal);
1916
1917 if (dt->delim)
1918 mask |= set_string (&block, &post_block, var, IOPARM_dt_delim,
1919 dt->delim);
1920
1921 if (dt->pad)
1922 mask |= set_string (&block, &post_block, var, IOPARM_dt_pad,
1923 dt->pad);
1924
1925 if (dt->round)
1926 mask |= set_string (&block, &post_block, var, IOPARM_dt_round,
1927 dt->round);
1928
1929 if (dt->sign)
1930 mask |= set_string (&block, &post_block, var, IOPARM_dt_sign,
1931 dt->sign);
1932
60c514ba 1933 if (dt->rec)
f26dc717 1934 mask |= set_parameter_value (&block, var, IOPARM_dt_rec, dt->rec);
4ee9c684 1935
60c514ba 1936 if (dt->advance)
1937 mask |= set_string (&block, &post_block, var, IOPARM_dt_advance,
1938 dt->advance);
4ee9c684 1939
60c514ba 1940 if (dt->format_expr)
c1f61f13 1941 mask |= set_string (&block, &post_end_block, var, IOPARM_dt_format,
60c514ba 1942 dt->format_expr);
4ee9c684 1943
60c514ba 1944 if (dt->format_label)
1945 {
1946 if (dt->format_label == &format_asterisk)
1947 mask |= IOPARM_dt_list_format;
1948 else
1949 mask |= set_string (&block, &post_block, var, IOPARM_dt_format,
1950 dt->format_label->format);
1951 }
4ee9c684 1952
60c514ba 1953 if (dt->size)
1954 mask |= set_parameter_ref (&block, &post_end_block, var,
1955 IOPARM_dt_size, dt->size);
4ee9c684 1956
e7c4560c 1957 if (dt->udtio)
1958 mask |= IOPARM_dt_dtio;
1959
366dbfaa 1960 if (dt->dec_ext)
1961 mask |= IOPARM_dt_dec_ext;
3e0607a2 1962
60c514ba 1963 if (dt->namelist)
1964 {
1965 if (dt->format_expr || dt->format_label)
1966 gfc_internal_error ("build_dt: format with namelist");
1967
126387b5 1968 nmlname = gfc_get_character_expr (gfc_default_character_kind, NULL,
1969 dt->namelist->name,
1970 strlen (dt->namelist->name));
fc2a7c27 1971
60c514ba 1972 mask |= set_string (&block, &post_block, var, IOPARM_dt_namelist_name,
1973 nmlname);
fc2a7c27 1974
c23adf93 1975 gfc_free_expr (nmlname);
1976
60c514ba 1977 if (last_dt == READ)
1978 mask |= IOPARM_dt_namelist_read_mode;
fc2a7c27 1979
60c514ba 1980 set_parameter_const (&block, var, IOPARM_common_flags, mask);
fc2a7c27 1981
60c514ba 1982 dt_parm = var;
1983
1984 for (nml = dt->namelist->namelist; nml; nml = nml->next)
1985 transfer_namelist_element (&block, nml->sym->name, nml->sym,
7623e879 1986 NULL, NULL_TREE);
60c514ba 1987 }
1988 else
1989 set_parameter_const (&block, var, IOPARM_common_flags, mask);
50ad5fa2 1990
1991 if (dt->io_unit && dt->io_unit->ts.type == BT_INTEGER)
f26dc717 1992 set_parameter_value_chk (&block, dt->iostat, var,
1993 IOPARM_common_unit, dt->io_unit);
4ee9c684 1994 }
60c514ba 1995 else
1996 set_parameter_const (&block, var, IOPARM_common_flags, mask);
4ee9c684 1997
86f2ad37 1998 tmp = gfc_build_addr_expr (NULL_TREE, var);
1108483a 1999 tmp = build_call_expr_loc (UNKNOWN_LOCATION,
389dd41b 2000 function, 1, tmp);
4ee9c684 2001 gfc_add_expr_to_block (&block, tmp);
2002
2003 gfc_add_block_to_block (&block, &post_block);
2004
60c514ba 2005 dt_parm = var;
2006 dt_post_end_block = &post_end_block;
2007
1e8c7f7a 2008 /* Set implied do loop exit condition. */
2009 if (last_dt == READ || last_dt == WRITE)
2010 {
2011 gfc_st_parameter_field *p = &st_parameter_field[IOPARM_common_flags];
2012
1516b2fb 2013 tmp = fold_build3_loc (input_location, COMPONENT_REF,
2014 st_parameter[IOPARM_ptype_common].type,
2015 dt_parm, TYPE_FIELDS (TREE_TYPE (dt_parm)),
2016 NULL_TREE);
2017 tmp = fold_build3_loc (input_location, COMPONENT_REF,
2018 TREE_TYPE (p->field), tmp, p->field, NULL_TREE);
2019 tmp = fold_build2_loc (input_location, BIT_AND_EXPR, TREE_TYPE (tmp),
2020 tmp, build_int_cst (TREE_TYPE (tmp),
2021 IOPARM_common_libreturn_mask));
1e8c7f7a 2022 }
2023 else /* IOLENGTH */
2024 tmp = NULL_TREE;
2025
2026 gfc_add_expr_to_block (&block, gfc_trans_code_cond (code->block->next, tmp));
60c514ba 2027
2ecf364f 2028 gfc_add_block_to_block (&block, &post_iu_block);
2029
60c514ba 2030 dt_parm = NULL;
2031 dt_post_end_block = NULL;
2032
4ee9c684 2033 return gfc_finish_block (&block);
2034}
2035
2036
6799e2f8 2037/* Translate the IOLENGTH form of an INQUIRE statement. We treat
2038 this as a third sort of data transfer statement, except that
7b3423b9 2039 lengths are summed instead of actually transferring any data. */
6799e2f8 2040
2041tree
2042gfc_trans_iolength (gfc_code * code)
2043{
6799e2f8 2044 last_dt = IOLENGTH;
60c514ba 2045 return build_dt (iocall[IOCALL_IOLENGTH], code);
6799e2f8 2046}
2047
2048
4ee9c684 2049/* Translate a READ statement. */
2050
2051tree
2052gfc_trans_read (gfc_code * code)
2053{
4ee9c684 2054 last_dt = READ;
60c514ba 2055 return build_dt (iocall[IOCALL_READ], code);
4ee9c684 2056}
2057
2058
2059/* Translate a WRITE statement */
2060
2061tree
2062gfc_trans_write (gfc_code * code)
2063{
4ee9c684 2064 last_dt = WRITE;
60c514ba 2065 return build_dt (iocall[IOCALL_WRITE], code);
4ee9c684 2066}
2067
2068
2069/* Finish a data transfer statement. */
2070
2071tree
2072gfc_trans_dt_end (gfc_code * code)
2073{
2074 tree function, tmp;
2075 stmtblock_t block;
2076
2077 gfc_init_block (&block);
2078
6799e2f8 2079 switch (last_dt)
2080 {
2081 case READ:
60c514ba 2082 function = iocall[IOCALL_READ_DONE];
6799e2f8 2083 break;
2084
2085 case WRITE:
60c514ba 2086 function = iocall[IOCALL_WRITE_DONE];
6799e2f8 2087 break;
2088
2089 case IOLENGTH:
60c514ba 2090 function = iocall[IOCALL_IOLENGTH_DONE];
6799e2f8 2091 break;
2092
2093 default:
22d678e8 2094 gcc_unreachable ();
6799e2f8 2095 }
4ee9c684 2096
86f2ad37 2097 tmp = gfc_build_addr_expr (NULL_TREE, dt_parm);
389dd41b 2098 tmp = build_call_expr_loc (input_location,
2099 function, 1, tmp);
4ee9c684 2100 gfc_add_expr_to_block (&block, tmp);
60c514ba 2101 gfc_add_block_to_block (&block, dt_post_end_block);
2102 gfc_init_block (dt_post_end_block);
4ee9c684 2103
6799e2f8 2104 if (last_dt != IOLENGTH)
2105 {
22d678e8 2106 gcc_assert (code->ext.dt != NULL);
60c514ba 2107 io_result (&block, dt_parm, code->ext.dt->err,
6799e2f8 2108 code->ext.dt->end, code->ext.dt->eor);
2109 }
4ee9c684 2110
2111 return gfc_finish_block (&block);
2112}
2113
3273c361 2114static void
9f732c4e 2115transfer_expr (gfc_se * se, gfc_typespec * ts, tree addr_expr,
2116 gfc_code * code, tree vptr);
3273c361 2117
2118/* Given an array field in a derived type variable, generate the code
2119 for the loop that iterates over array elements, and the code that
2120 accesses those array elements. Use transfer_expr to generate code
2121 for transferring that element. Because elements may also be
2122 derived types, transfer_expr and transfer_array_component are mutually
2123 recursive. */
2124
2125static tree
92f4d1c4 2126transfer_array_component (tree expr, gfc_component * cm, locus * where)
3273c361 2127{
2128 tree tmp;
2129 stmtblock_t body;
2130 stmtblock_t block;
2131 gfc_loopinfo loop;
2132 int n;
2133 gfc_ss *ss;
2134 gfc_se se;
f6b46ebc 2135 gfc_array_info *ss_array;
3273c361 2136
2137 gfc_start_block (&block);
2138 gfc_init_se (&se, NULL);
2139
2140 /* Create and initialize Scalarization Status. Unlike in
2141 gfc_trans_transfer, we can't simply use gfc_walk_expr to take
2142 care of this task, because we don't have a gfc_expr at hand.
2143 Build one manually, as in gfc_trans_subarray_assign. */
2144
f912e858 2145 ss = gfc_get_array_ss (gfc_ss_terminator, NULL, cm->as->rank,
2146 GFC_SS_COMPONENT);
b8f38347 2147 ss_array = &ss->info->data.array;
f0efd2e8 2148
2149 if (cm->attr.pdt_array)
2150 ss_array->shape = NULL;
2151 else
2152 ss_array->shape = gfc_get_shape (cm->as->rank);
2153
f6b46ebc 2154 ss_array->descriptor = expr;
2155 ss_array->data = gfc_conv_array_data (expr);
2156 ss_array->offset = gfc_conv_array_offset (expr);
3273c361 2157 for (n = 0; n < cm->as->rank; n++)
2158 {
f6b46ebc 2159 ss_array->start[n] = gfc_conv_array_lbound (expr, n);
2160 ss_array->stride[n] = gfc_index_one_node;
3273c361 2161
f0efd2e8 2162 if (cm->attr.pdt_array)
2163 ss_array->end[n] = gfc_conv_array_ubound (expr, n);
2164 else
2165 {
2166 mpz_init (ss_array->shape[n]);
2167 mpz_sub (ss_array->shape[n], cm->as->upper[n]->value.integer,
2168 cm->as->lower[n]->value.integer);
2169 mpz_add_ui (ss_array->shape[n], ss_array->shape[n], 1);
2170 }
3273c361 2171 }
2172
b14e2757 2173 /* Once we got ss, we use scalarizer to create the loop. */
3273c361 2174
2175 gfc_init_loopinfo (&loop);
2176 gfc_add_ss_to_loop (&loop, ss);
2177 gfc_conv_ss_startstride (&loop);
92f4d1c4 2178 gfc_conv_loop_setup (&loop, where);
3273c361 2179 gfc_mark_ss_chain_used (ss, 1);
2180 gfc_start_scalarized_body (&loop, &body);
2181
2182 gfc_copy_loopinfo_to_se (&se, &loop);
2183 se.ss = ss;
2184
2185 /* gfc_conv_tmp_array_ref assumes that se.expr contains the array. */
2186 se.expr = expr;
2187 gfc_conv_tmp_array_ref (&se);
2188
2189 /* Now se.expr contains an element of the array. Take the address and pass
2190 it to the IO routines. */
86f2ad37 2191 tmp = gfc_build_addr_expr (NULL_TREE, se.expr);
9f732c4e 2192 transfer_expr (&se, &cm->ts, tmp, NULL, NULL_TREE);
3273c361 2193
2194 /* We are done now with the loop body. Wrap up the scalarizer and
b14e2757 2195 return. */
3273c361 2196
2197 gfc_add_block_to_block (&body, &se.pre);
2198 gfc_add_block_to_block (&body, &se.post);
2199
2200 gfc_trans_scalarizing_loops (&loop, &body);
2201
2202 gfc_add_block_to_block (&block, &loop.pre);
2203 gfc_add_block_to_block (&block, &loop.post);
2204
f0efd2e8 2205 if (!cm->attr.pdt_array)
2206 {
2207 gcc_assert (ss_array->shape != NULL);
2208 gfc_free_shape (&ss_array->shape, cm->as->rank);
2209 }
6cf06ccd 2210 gfc_cleanup_loop (&loop);
2211
3273c361 2212 return gfc_finish_block (&block);
2213}
4ee9c684 2214
9f732c4e 2215
2216/* Helper function for transfer_expr that looks for the DTIO procedure
2217 either as a typebound binding or in a generic interface. If present,
2218 the address expression of the procedure is returned. It is assumed
2219 that the procedure interface has been checked during resolution. */
2220
2221static tree
2222get_dtio_proc (gfc_typespec * ts, gfc_code * code, gfc_symbol **dtio_sub)
2223{
2224 gfc_symbol *derived;
2225 bool formatted = false;
2226 gfc_dt *dt = code->ext.dt;
2227
cbb040a1 2228 /* Determine when to use the formatted DTIO procedure. */
2229 if (dt && (dt->format_expr || dt->format_label))
2230 formatted = true;
9f732c4e 2231
da230ae1 2232 if (ts->type == BT_CLASS)
2233 derived = ts->u.derived->components->ts.u.derived;
2234 else
2235 derived = ts->u.derived;
2236
2237 gfc_symtree *tb_io_st = gfc_find_typebound_dtio_proc (derived,
2238 last_dt == WRITE, formatted);
2239 if (ts->type == BT_CLASS && tb_io_st)
8bf96899 2240 {
da230ae1 2241 // polymorphic DTIO call (based on the dynamic type)
2242 gfc_se se;
2243 gfc_expr *expr = gfc_find_and_cut_at_last_class_ref (code->expr1);
2244 gfc_add_vptr_component (expr);
2245 gfc_add_component_ref (expr,
2246 tb_io_st->n.tb->u.generic->specific_st->name);
2247 *dtio_sub = tb_io_st->n.tb->u.generic->specific->u.specific->n.sym;
2248 gfc_init_se (&se, NULL);
2249 se.want_pointer = 1;
2250 gfc_conv_expr (&se, expr);
2251 gfc_free_expr (expr);
2252 return se.expr;
2253 }
2254 else
2255 {
2256 // non-polymorphic DTIO call (based on the declared type)
8bf96899 2257 *dtio_sub = gfc_find_specific_dtio_proc (derived, last_dt == WRITE,
2258 formatted);
2259
2260 if (*dtio_sub)
2261 return gfc_build_addr_expr (NULL, gfc_get_symbol_decl (*dtio_sub));
2262 }
9f732c4e 2263
2264 return NULL_TREE;
9f732c4e 2265}
2266
4ee9c684 2267/* Generate the call for a scalar transfer node. */
2268
2269static void
9f732c4e 2270transfer_expr (gfc_se * se, gfc_typespec * ts, tree addr_expr,
2271 gfc_code * code, tree vptr)
4ee9c684 2272{
dc01006d 2273 tree tmp, function, arg2, arg3, field, expr;
4ee9c684 2274 gfc_component *c;
2275 int kind;
2276
c5d33754 2277 /* It is possible to get a C_NULL_PTR or C_NULL_FUNPTR expression here if
2278 the user says something like: print *, 'c_null_ptr: ', c_null_ptr
2279 We need to translate the expression to a constant if it's either
e4eda3ec 2280 C_NULL_PTR or C_NULL_FUNPTR. We could also get a user variable of
2281 type C_PTR or C_FUNPTR, in which case the ts->type may no longer be
2282 BT_DERIVED (could have been changed by gfc_conv_expr). */
eeebe20b 2283 if ((ts->type == BT_DERIVED || ts->type == BT_INTEGER)
2284 && ts->u.derived != NULL
2285 && (ts->is_iso_c == 1 || ts->u.derived->ts.is_iso_c == 1))
c5d33754 2286 {
07f0c434 2287 ts->type = BT_INTEGER;
35bb864b 2288 ts->kind = gfc_index_integer_kind;
2289 }
2290
2291 /* gfortran reaches here for "print *, c_loc(xxx)". */
2292 if (ts->type == BT_VOID
2293 && code->expr1 && code->expr1->ts.type == BT_VOID
2294 && code->expr1->symtree
2295 && strcmp (code->expr1->symtree->name, "c_loc") == 0)
2296 {
2297 ts->type = BT_INTEGER;
07f0c434 2298 ts->kind = gfc_index_integer_kind;
c5d33754 2299 }
4442e7ec 2300
4ee9c684 2301 kind = ts->kind;
2302 function = NULL;
2303 arg2 = NULL;
dc01006d 2304 arg3 = NULL;
4ee9c684 2305
2306 switch (ts->type)
2307 {
2308 case BT_INTEGER:
35bf1214 2309 arg2 = build_int_cst (integer_type_node, kind);
8545af25 2310 if (last_dt == READ)
2311 function = iocall[IOCALL_X_INTEGER];
2312 else
2313 function = iocall[IOCALL_X_INTEGER_WRITE];
2314
4ee9c684 2315 break;
2316
2317 case BT_REAL:
35bf1214 2318 arg2 = build_int_cst (integer_type_node, kind);
8545af25 2319 if (last_dt == READ)
87969c8c 2320 {
2321 if (gfc_real16_is_float128 && ts->kind == 16)
2322 function = iocall[IOCALL_X_REAL128];
2323 else
2324 function = iocall[IOCALL_X_REAL];
2325 }
8545af25 2326 else
87969c8c 2327 {
2328 if (gfc_real16_is_float128 && ts->kind == 16)
2329 function = iocall[IOCALL_X_REAL128_WRITE];
2330 else
2331 function = iocall[IOCALL_X_REAL_WRITE];
2332 }
8545af25 2333
4ee9c684 2334 break;
2335
2336 case BT_COMPLEX:
35bf1214 2337 arg2 = build_int_cst (integer_type_node, kind);
8545af25 2338 if (last_dt == READ)
87969c8c 2339 {
2340 if (gfc_real16_is_float128 && ts->kind == 16)
2341 function = iocall[IOCALL_X_COMPLEX128];
2342 else
2343 function = iocall[IOCALL_X_COMPLEX];
2344 }
8545af25 2345 else
87969c8c 2346 {
2347 if (gfc_real16_is_float128 && ts->kind == 16)
2348 function = iocall[IOCALL_X_COMPLEX128_WRITE];
2349 else
2350 function = iocall[IOCALL_X_COMPLEX_WRITE];
2351 }
8545af25 2352
4ee9c684 2353 break;
2354
2355 case BT_LOGICAL:
35bf1214 2356 arg2 = build_int_cst (integer_type_node, kind);
8545af25 2357 if (last_dt == READ)
2358 function = iocall[IOCALL_X_LOGICAL];
2359 else
2360 function = iocall[IOCALL_X_LOGICAL_WRITE];
2361
4ee9c684 2362 break;
2363
2364 case BT_CHARACTER:
dc01006d 2365 if (kind == 4)
2366 {
2367 if (se->string_length)
2368 arg2 = se->string_length;
2369 else
2370 {
389dd41b 2371 tmp = build_fold_indirect_ref_loc (input_location,
2372 addr_expr);
dc01006d 2373 gcc_assert (TREE_CODE (TREE_TYPE (tmp)) == ARRAY_TYPE);
2374 arg2 = TYPE_MAX_VALUE (TYPE_DOMAIN (TREE_TYPE (tmp)));
2375 arg2 = fold_convert (gfc_charlen_type_node, arg2);
2376 }
35bf1214 2377 arg3 = build_int_cst (integer_type_node, kind);
8545af25 2378 if (last_dt == READ)
2379 function = iocall[IOCALL_X_CHARACTER_WIDE];
2380 else
2381 function = iocall[IOCALL_X_CHARACTER_WIDE_WRITE];
4442e7ec 2382
86f2ad37 2383 tmp = gfc_build_addr_expr (NULL_TREE, dt_parm);
389dd41b 2384 tmp = build_call_expr_loc (input_location,
2385 function, 4, tmp, addr_expr, arg2, arg3);
dc01006d 2386 gfc_add_expr_to_block (&se->pre, tmp);
2387 gfc_add_block_to_block (&se->pre, &se->post);
2388 return;
2389 }
293d72e0 2390 /* Fall through. */
61807373 2391 case BT_HOLLERITH:
3273c361 2392 if (se->string_length)
2393 arg2 = se->string_length;
2394 else
2395 {
389dd41b 2396 tmp = build_fold_indirect_ref_loc (input_location,
2397 addr_expr);
3273c361 2398 gcc_assert (TREE_CODE (TREE_TYPE (tmp)) == ARRAY_TYPE);
2399 arg2 = TYPE_MAX_VALUE (TYPE_DOMAIN (TREE_TYPE (tmp)));
2400 }
8545af25 2401 if (last_dt == READ)
2402 function = iocall[IOCALL_X_CHARACTER];
2403 else
2404 function = iocall[IOCALL_X_CHARACTER_WRITE];
2405
4ee9c684 2406 break;
2407
d7cd448a 2408 case_bt_struct:
9f732c4e 2409 case BT_CLASS:
d526ff88 2410 if (ts->u.derived->components == NULL)
2411 return;
edaf95de 2412 if (gfc_bt_struct (ts->type) || ts->type == BT_CLASS)
9f732c4e 2413 {
2414 gfc_symbol *derived;
2415 gfc_symbol *dtio_sub = NULL;
2416 /* Test for a specific DTIO subroutine. */
2417 if (ts->type == BT_DERIVED)
2418 derived = ts->u.derived;
2419 else
2420 derived = ts->u.derived->components->ts.u.derived;
d526ff88 2421
9f732c4e 2422 if (derived->attr.has_dtio_procs)
2423 arg2 = get_dtio_proc (ts, code, &dtio_sub);
4ee9c684 2424
4c3a9c43 2425 if ((dtio_sub != NULL) && (last_dt != IOLENGTH))
9f732c4e 2426 {
2427 tree decl;
2428 decl = build_fold_indirect_ref_loc (input_location,
2429 se->expr);
2430 /* Remember that the first dummy of the DTIO subroutines
2431 is CLASS(derived) for extensible derived types, so the
2432 conversion must be done here for derived type and for
2433 scalarized CLASS array element io-list objects. */
2434 if ((ts->type == BT_DERIVED
2435 && !(ts->u.derived->attr.sequence
2436 || ts->u.derived->attr.is_bind_c))
2437 || (ts->type == BT_CLASS
2438 && !GFC_CLASS_TYPE_P (TREE_TYPE (decl))))
2439 gfc_conv_derived_to_class (se, code->expr1,
2440 dtio_sub->formal->sym->ts,
2441 vptr, false, false);
2442 addr_expr = se->expr;
2443 function = iocall[IOCALL_X_DERIVED];
2444 break;
2445 }
edaf95de 2446 else if (gfc_bt_struct (ts->type))
9f732c4e 2447 {
2448 /* Recurse into the elements of the derived type. */
2449 expr = gfc_evaluate_now (addr_expr, &se->pre);
cbb040a1 2450 expr = build_fold_indirect_ref_loc (input_location, expr);
4442e7ec 2451
9f732c4e 2452 /* Make sure that the derived type has been built. An external
2453 function, if only referenced in an io statement, requires this
2454 check (see PR58771). */
2455 if (ts->u.derived->backend_decl == NULL_TREE)
2456 (void) gfc_typenode_for_spec (ts);
2457
2458 for (c = ts->u.derived->components; c; c = c->next)
2459 {
f0efd2e8 2460 /* Ignore hidden string lengths. */
2461 if (c->name[0] == '_')
2462 continue;
2463
9f732c4e 2464 field = c->backend_decl;
2465 gcc_assert (field && TREE_CODE (field) == FIELD_DECL);
2466
2467 tmp = fold_build3_loc (UNKNOWN_LOCATION,
2468 COMPONENT_REF, TREE_TYPE (field),
2469 expr, field, NULL_TREE);
2470
2471 if (c->attr.dimension)
2472 {
2473 tmp = transfer_array_component (tmp, c, & code->loc);
2474 gfc_add_expr_to_block (&se->pre, tmp);
2475 }
2476 else
2477 {
f0efd2e8 2478 tree strlen = NULL_TREE;
2479
2480 if (!c->attr.pointer && !c->attr.pdt_string)
9f732c4e 2481 tmp = gfc_build_addr_expr (NULL_TREE, tmp);
f0efd2e8 2482
2483 /* Use the hidden string length for pdt strings. */
2484 if (c->attr.pdt_string
2485 && gfc_deferred_strlen (c, &strlen)
2486 && strlen != NULL_TREE)
2487 {
2488 strlen = fold_build3_loc (UNKNOWN_LOCATION,
2489 COMPONENT_REF,
2490 TREE_TYPE (strlen),
2491 expr, strlen, NULL_TREE);
2492 se->string_length = strlen;
2493 }
2494
9f732c4e 2495 transfer_expr (se, &c->ts, tmp, code, NULL_TREE);
f0efd2e8 2496
2497 /* Reset so that the pdt string length does not propagate
2498 through to other strings. */
2499 if (c->attr.pdt_string && strlen)
2500 se->string_length = NULL_TREE;
9f732c4e 2501 }
2502 }
2503 return;
2504 }
2505 /* If a CLASS object gets through to here, fall through and ICE. */
4ee9c684 2506 }
3c77f69c 2507 gcc_fallthrough ();
4ee9c684 2508 default:
382ad5c3 2509 gfc_internal_error ("Bad IO basetype (%d)", ts->type);
4ee9c684 2510 }
2511
86f2ad37 2512 tmp = gfc_build_addr_expr (NULL_TREE, dt_parm);
389dd41b 2513 tmp = build_call_expr_loc (input_location,
2514 function, 3, tmp, addr_expr, arg2);
4ee9c684 2515 gfc_add_expr_to_block (&se->pre, tmp);
2516 gfc_add_block_to_block (&se->pre, &se->post);
6799e2f8 2517
4ee9c684 2518}
2519
2520
fd5a2518 2521/* Generate a call to pass an array descriptor to the IO library. The
2522 array should be of one of the intrinsic types. */
2523
2524static void
2525transfer_array_desc (gfc_se * se, gfc_typespec * ts, tree addr_expr)
2526{
8545af25 2527 tree tmp, charlen_arg, kind_arg, io_call;
fd5a2518 2528
2529 if (ts->type == BT_CHARACTER)
2530 charlen_arg = se->string_length;
2531 else
35bf1214 2532 charlen_arg = build_int_cst (gfc_charlen_type_node, 0);
fd5a2518 2533
35bf1214 2534 kind_arg = build_int_cst (integer_type_node, ts->kind);
4ea6d60e 2535
86f2ad37 2536 tmp = gfc_build_addr_expr (NULL_TREE, dt_parm);
8545af25 2537 if (last_dt == READ)
2538 io_call = iocall[IOCALL_X_ARRAY];
2539 else
2540 io_call = iocall[IOCALL_X_ARRAY_WRITE];
2541
1108483a 2542 tmp = build_call_expr_loc (UNKNOWN_LOCATION,
8545af25 2543 io_call, 4,
c2f47e15 2544 tmp, addr_expr, kind_arg, charlen_arg);
fd5a2518 2545 gfc_add_expr_to_block (&se->pre, tmp);
2546 gfc_add_block_to_block (&se->pre, &se->post);
2547}
2548
2549
4ee9c684 2550/* gfc_trans_transfer()-- Translate a TRANSFER code node */
2551
2552tree
2553gfc_trans_transfer (gfc_code * code)
2554{
2555 stmtblock_t block, body;
2556 gfc_loopinfo loop;
2557 gfc_expr *expr;
0b044e59 2558 gfc_ref *ref;
4ee9c684 2559 gfc_ss *ss;
2560 gfc_se se;
2561 tree tmp;
9f732c4e 2562 tree vptr;
25d7376a 2563 int n;
4ee9c684 2564
2565 gfc_start_block (&block);
fd5a2518 2566 gfc_init_block (&body);
4ee9c684 2567
578d3f19 2568 expr = code->expr1;
0b044e59 2569 ref = NULL;
4ee9c684 2570 gfc_init_se (&se, NULL);
2571
5d34a30f 2572 if (expr->rank == 0)
fd5a2518 2573 {
868213c7 2574 /* Transfer a scalar value. */
9f732c4e 2575 if (expr->ts.type == BT_CLASS)
2576 {
2577 se.want_pointer = 1;
2578 gfc_conv_expr (&se, expr);
2579 vptr = gfc_get_vptr_from_expr (se.expr);
2580 }
2581 else
2582 {
2583 vptr = NULL_TREE;
2584 gfc_conv_expr_reference (&se, expr);
2585 }
2586 transfer_expr (&se, &expr->ts, se.expr, code, vptr);
fd5a2518 2587 }
868213c7 2588 else
4ee9c684 2589 {
0b044e59 2590 /* Transfer an array. If it is an array of an intrinsic
2591 type, pass the descriptor to the library. Otherwise
2592 scalarize the transfer. */
b3961d7b 2593 if (expr->ref && !gfc_is_proc_ptr_comp (expr))
0b044e59 2594 {
2595 for (ref = expr->ref; ref && ref->type != REF_ARRAY;
d526ff88 2596 ref = ref->next);
2597 gcc_assert (ref && ref->type == REF_ARRAY);
0b044e59 2598 }
2599
47e6a59a 2600 if (expr->ts.type != BT_CLASS
2601 && expr->expr_type == EXPR_VARIABLE
2602 && gfc_expr_attr (expr).pointer)
2603 goto scalarize;
2604
2605
9f732c4e 2606 if (!(gfc_bt_struct (expr->ts.type)
2607 || expr->ts.type == BT_CLASS)
1033248c 2608 && ref && ref->next == NULL
2609 && !is_subref_array (expr))
868213c7 2610 {
25d7376a 2611 bool seen_vector = false;
2612
2613 if (ref && ref->u.ar.type == AR_SECTION)
2614 {
2615 for (n = 0; n < ref->u.ar.dimen; n++)
2616 if (ref->u.ar.dimen_type[n] == DIMEN_VECTOR)
16e3c896 2617 {
2618 seen_vector = true;
2619 break;
2620 }
25d7376a 2621 }
2622
2623 if (seen_vector && last_dt == READ)
2624 {
2625 /* Create a temp, read to that and copy it back. */
3446c28b 2626 gfc_conv_subref_array_arg (&se, expr, 0, INTENT_OUT, false);
25d7376a 2627 tmp = se.expr;
2628 }
2629 else
2630 {
2631 /* Get the descriptor. */
5d34a30f 2632 gfc_conv_expr_descriptor (&se, expr);
86f2ad37 2633 tmp = gfc_build_addr_expr (NULL_TREE, se.expr);
25d7376a 2634 }
2635
0b044e59 2636 transfer_array_desc (&se, &expr->ts, tmp);
2637 goto finish_block_label;
868213c7 2638 }
5d34a30f 2639
47e6a59a 2640scalarize:
4ee9c684 2641 /* Initialize the scalarizer. */
5d34a30f 2642 ss = gfc_walk_expr (expr);
4ee9c684 2643 gfc_init_loopinfo (&loop);
2644 gfc_add_ss_to_loop (&loop, ss);
2645
2646 /* Initialize the loop. */
2647 gfc_conv_ss_startstride (&loop);
578d3f19 2648 gfc_conv_loop_setup (&loop, &code->expr1->where);
4ee9c684 2649
2650 /* The main loop body. */
2651 gfc_mark_ss_chain_used (ss, 1);
2652 gfc_start_scalarized_body (&loop, &body);
2653
2654 gfc_copy_loopinfo_to_se (&se, &loop);
2655 se.ss = ss;
47e6a59a 2656
fd5a2518 2657 gfc_conv_expr_reference (&se, expr);
47e6a59a 2658
9f732c4e 2659 if (expr->ts.type == BT_CLASS)
2660 vptr = gfc_get_vptr_from_expr (ss->info->data.array.descriptor);
2661 else
2662 vptr = NULL_TREE;
2663 transfer_expr (&se, &expr->ts, se.expr, code, vptr);
fd5a2518 2664 }
868213c7 2665
2666 finish_block_label:
4ee9c684 2667
2668 gfc_add_block_to_block (&body, &se.pre);
2669 gfc_add_block_to_block (&body, &se.post);
2670
2671 if (se.ss == NULL)
2672 tmp = gfc_finish_block (&body);
2673 else
2674 {
a4e45797 2675 gcc_assert (expr->rank != 0);
22d678e8 2676 gcc_assert (se.ss == gfc_ss_terminator);
4ee9c684 2677 gfc_trans_scalarizing_loops (&loop, &body);
2678
2679 gfc_add_block_to_block (&loop.pre, &loop.post);
2680 tmp = gfc_finish_block (&loop.pre);
2681 gfc_cleanup_loop (&loop);
2682 }
2683
2684 gfc_add_expr_to_block (&block, tmp);
2685
3273c361 2686 return gfc_finish_block (&block);
4ee9c684 2687}
2688
2689#include "gt-fortran-trans-io.h"