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