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