]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/fortran/trans-io.c
atomic (compare_exchange_weak, [...]): Add call to __cmpexch_failure_order.
[thirdparty/gcc.git] / gcc / fortran / trans-io.c
CommitLineData
6de9cd9a 1/* IO Code translation/library interface
d1e082c2 2 Copyright (C) 2002-2013 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"
25#include "tree.h"
6de9cd9a 26#include "ggc.h"
c829d016 27#include "diagnostic-core.h" /* For internal_error. */
6de9cd9a
DN
28#include "gfortran.h"
29#include "trans.h"
30#include "trans-stmt.h"
31#include "trans-array.h"
32#include "trans-types.h"
33#include "trans-const.h"
34
6de9cd9a
DN
35/* Members of the ioparm structure. */
36
5e805e44
JJ
37enum ioparam_type
38{
39 IOPARM_ptype_common,
40 IOPARM_ptype_open,
41 IOPARM_ptype_close,
42 IOPARM_ptype_filepos,
43 IOPARM_ptype_inquire,
44 IOPARM_ptype_dt,
6f0f0b2e 45 IOPARM_ptype_wait,
5e805e44
JJ
46 IOPARM_ptype_num
47};
48
49enum iofield_type
50{
51 IOPARM_type_int4,
014ec6ee 52 IOPARM_type_intio,
5e805e44 53 IOPARM_type_pint4,
014ec6ee 54 IOPARM_type_pintio,
5e805e44
JJ
55 IOPARM_type_pchar,
56 IOPARM_type_parray,
57 IOPARM_type_pad,
58 IOPARM_type_char1,
59 IOPARM_type_char2,
60 IOPARM_type_common,
61 IOPARM_type_num
62};
63
d1b38208 64typedef struct GTY(()) gfc_st_parameter_field {
5e805e44
JJ
65 const char *name;
66 unsigned int mask;
67 enum ioparam_type param_type;
68 enum iofield_type type;
69 tree field;
70 tree field_len;
71}
72gfc_st_parameter_field;
6de9cd9a 73
d1b38208 74typedef struct GTY(()) gfc_st_parameter {
5e805e44
JJ
75 const char *name;
76 tree type;
77}
78gfc_st_parameter;
79
80enum iofield
81{
82#define IOPARM(param_type, name, mask, type) IOPARM_##param_type##_##name,
83#include "ioparm.def"
84#undef IOPARM
85 IOPARM_field_num
86};
87
88static GTY(()) gfc_st_parameter st_parameter[] =
89{
90 { "common", NULL },
91 { "open", NULL },
92 { "close", NULL },
93 { "filepos", NULL },
94 { "inquire", NULL },
6f0f0b2e
JD
95 { "dt", NULL },
96 { "wait", NULL }
5e805e44
JJ
97};
98
99static GTY(()) gfc_st_parameter_field st_parameter_field[] =
100{
101#define IOPARM(param_type, name, mask, type) \
102 { #name, mask, IOPARM_ptype_##param_type, IOPARM_type_##type, NULL, NULL },
103#include "ioparm.def"
104#undef IOPARM
81f40b79 105 { NULL, 0, (enum ioparam_type) 0, (enum iofield_type) 0, NULL, NULL }
5e805e44 106};
6de9cd9a
DN
107
108/* Library I/O subroutines */
109
5e805e44
JJ
110enum iocall
111{
112 IOCALL_READ,
113 IOCALL_READ_DONE,
114 IOCALL_WRITE,
115 IOCALL_WRITE_DONE,
116 IOCALL_X_INTEGER,
6eb6875d 117 IOCALL_X_INTEGER_WRITE,
5e805e44 118 IOCALL_X_LOGICAL,
6eb6875d 119 IOCALL_X_LOGICAL_WRITE,
5e805e44 120 IOCALL_X_CHARACTER,
6eb6875d 121 IOCALL_X_CHARACTER_WRITE,
8a221914 122 IOCALL_X_CHARACTER_WIDE,
6eb6875d 123 IOCALL_X_CHARACTER_WIDE_WRITE,
5e805e44 124 IOCALL_X_REAL,
6eb6875d 125 IOCALL_X_REAL_WRITE,
5e805e44 126 IOCALL_X_COMPLEX,
6eb6875d 127 IOCALL_X_COMPLEX_WRITE,
1ec601bf
FXC
128 IOCALL_X_REAL128,
129 IOCALL_X_REAL128_WRITE,
130 IOCALL_X_COMPLEX128,
131 IOCALL_X_COMPLEX128_WRITE,
5e805e44 132 IOCALL_X_ARRAY,
6eb6875d 133 IOCALL_X_ARRAY_WRITE,
5e805e44
JJ
134 IOCALL_OPEN,
135 IOCALL_CLOSE,
136 IOCALL_INQUIRE,
137 IOCALL_IOLENGTH,
138 IOCALL_IOLENGTH_DONE,
139 IOCALL_REWIND,
140 IOCALL_BACKSPACE,
141 IOCALL_ENDFILE,
142 IOCALL_FLUSH,
143 IOCALL_SET_NML_VAL,
144 IOCALL_SET_NML_VAL_DIM,
6f0f0b2e 145 IOCALL_WAIT,
5e805e44
JJ
146 IOCALL_NUM
147};
148
149static GTY(()) tree iocall[IOCALL_NUM];
6de9cd9a
DN
150
151/* Variable for keeping track of what the last data transfer statement
152 was. Used for deciding which subroutine to call when the data
f7b529fa 153 transfer is complete. */
8750f9cd 154static enum { READ, WRITE, IOLENGTH } last_dt;
6de9cd9a 155
5e805e44
JJ
156/* The data transfer parameter block that should be shared by all
157 data transfer calls belonging to the same read/write/iolength. */
158static GTY(()) tree dt_parm;
159static stmtblock_t *dt_post_end_block;
6de9cd9a 160
5e805e44
JJ
161static void
162gfc_build_st_parameter (enum ioparam_type ptype, tree *types)
163{
32e8bb8e 164 unsigned int type;
5e805e44
JJ
165 gfc_st_parameter_field *p;
166 char name[64];
167 size_t len;
168 tree t = make_node (RECORD_TYPE);
dfd6ece2 169 tree *chain = NULL;
5e805e44
JJ
170
171 len = strlen (st_parameter[ptype].name);
172 gcc_assert (len <= sizeof (name) - sizeof ("__st_parameter_"));
173 memcpy (name, "__st_parameter_", sizeof ("__st_parameter_"));
174 memcpy (name + sizeof ("__st_parameter_") - 1, st_parameter[ptype].name,
ff7417d4 175 len + 1);
5e805e44
JJ
176 TYPE_NAME (t) = get_identifier (name);
177
178 for (type = 0, p = st_parameter_field; type < IOPARM_field_num; type++, p++)
179 if (p->param_type == ptype)
180 switch (p->type)
181 {
182 case IOPARM_type_int4:
014ec6ee 183 case IOPARM_type_intio:
5e805e44 184 case IOPARM_type_pint4:
014ec6ee 185 case IOPARM_type_pintio:
5e805e44
JJ
186 case IOPARM_type_parray:
187 case IOPARM_type_pchar:
188 case IOPARM_type_pad:
35151cd5 189 p->field = gfc_add_field_to_struct (t, get_identifier (p->name),
dfd6ece2 190 types[p->type], &chain);
5e805e44
JJ
191 break;
192 case IOPARM_type_char1:
35151cd5 193 p->field = gfc_add_field_to_struct (t, get_identifier (p->name),
dfd6ece2 194 pchar_type_node, &chain);
5e805e44
JJ
195 /* FALLTHROUGH */
196 case IOPARM_type_char2:
197 len = strlen (p->name);
198 gcc_assert (len <= sizeof (name) - sizeof ("_len"));
199 memcpy (name, p->name, len);
200 memcpy (name + len, "_len", sizeof ("_len"));
35151cd5 201 p->field_len = gfc_add_field_to_struct (t, get_identifier (name),
dfd6ece2
NF
202 gfc_charlen_type_node,
203 &chain);
5e805e44 204 if (p->type == IOPARM_type_char2)
35151cd5 205 p->field = gfc_add_field_to_struct (t, get_identifier (p->name),
dfd6ece2 206 pchar_type_node, &chain);
5e805e44
JJ
207 break;
208 case IOPARM_type_common:
209 p->field
35151cd5 210 = gfc_add_field_to_struct (t,
5e805e44 211 get_identifier (p->name),
dfd6ece2
NF
212 st_parameter[IOPARM_ptype_common].type,
213 &chain);
5e805e44
JJ
214 break;
215 case IOPARM_type_num:
216 gcc_unreachable ();
217 }
6de9cd9a 218
5e805e44
JJ
219 gfc_finish_type (t);
220 st_parameter[ptype].type = t;
221}
6de9cd9a 222
f96d606f
JD
223
224/* Build code to test an error condition and call generate_error if needed.
225 Note: This builds calls to generate_error in the runtime library function.
226 The function generate_error is dependent on certain parameters in the
227 st_parameter_common flags to be set. (See libgfortran/runtime/error.c)
228 Therefore, the code to set these flags must be generated before
229 this function is used. */
230
231void
232gfc_trans_io_runtime_check (tree cond, tree var, int error_code,
233 const char * msgid, stmtblock_t * pblock)
234{
235 stmtblock_t block;
236 tree body;
237 tree tmp;
238 tree arg1, arg2, arg3;
239 char *message;
240
241 if (integer_zerop (cond))
242 return;
243
244 /* The code to generate the error. */
245 gfc_start_block (&block);
246
628c189e 247 arg1 = gfc_build_addr_expr (NULL_TREE, var);
f96d606f
JD
248
249 arg2 = build_int_cst (integer_type_node, error_code),
250
251 asprintf (&message, "%s", _(msgid));
ee37d2f5
FXC
252 arg3 = gfc_build_addr_expr (pchar_type_node,
253 gfc_build_localized_cstring_const (message));
cede9502 254 free (message);
f96d606f 255
db3927fb
AH
256 tmp = build_call_expr_loc (input_location,
257 gfor_fndecl_generate_error, 3, arg1, arg2, arg3);
f96d606f
JD
258
259 gfc_add_expr_to_block (&block, tmp);
260
261 body = gfc_finish_block (&block);
262
263 if (integer_onep (cond))
264 {
265 gfc_add_expr_to_block (pblock, body);
266 }
267 else
268 {
5af07930 269 cond = gfc_unlikely (cond);
c2255bc4 270 tmp = build3_v (COND_EXPR, cond, body, build_empty_stmt (input_location));
f96d606f
JD
271 gfc_add_expr_to_block (pblock, tmp);
272 }
273}
274
275
6de9cd9a
DN
276/* Create function decls for IO library functions. */
277
278void
279gfc_build_io_library_fndecls (void)
280{
5e805e44 281 tree types[IOPARM_type_num], pad_idx, gfc_int4_type_node;
014ec6ee 282 tree gfc_intio_type_node;
5e805e44 283 tree parm_type, dt_parm_type;
5e805e44 284 HOST_WIDE_INT pad_size;
09639a83 285 unsigned int ptype;
5e805e44
JJ
286
287 types[IOPARM_type_int4] = gfc_int4_type_node = gfc_get_int_type (4);
014ec6ee
JD
288 types[IOPARM_type_intio] = gfc_intio_type_node
289 = gfc_get_int_type (gfc_intio_kind);
5e805e44 290 types[IOPARM_type_pint4] = build_pointer_type (gfc_int4_type_node);
014ec6ee
JD
291 types[IOPARM_type_pintio]
292 = build_pointer_type (gfc_intio_type_node);
5e805e44
JJ
293 types[IOPARM_type_parray] = pchar_type_node;
294 types[IOPARM_type_pchar] = pchar_type_node;
e1456843 295 pad_size = 16 * TREE_INT_CST_LOW (TYPE_SIZE_UNIT (pchar_type_node));
5e805e44 296 pad_size += 32 * TREE_INT_CST_LOW (TYPE_SIZE_UNIT (integer_type_node));
df09d1d5 297 pad_idx = build_index_type (size_int (pad_size - 1));
5e805e44 298 types[IOPARM_type_pad] = build_array_type (char_type_node, pad_idx);
7ae99337
SE
299
300 /* pad actually contains pointers and integers so it needs to have an
301 alignment that is at least as large as the needed alignment for those
302 types. See the st_parameter_dt structure in libgfortran/io/io.h for
303 what really goes into this space. */
304 TYPE_ALIGN (types[IOPARM_type_pad]) = MAX (TYPE_ALIGN (pchar_type_node),
e1456843 305 TYPE_ALIGN (gfc_get_int_type (gfc_intio_kind)));
7ae99337 306
5e805e44 307 for (ptype = IOPARM_ptype_common; ptype < IOPARM_ptype_num; ptype++)
09639a83 308 gfc_build_st_parameter ((enum ioparam_type) ptype, types);
6de9cd9a 309
6eb6875d 310 /* Define the transfer functions. */
6de9cd9a 311
5e805e44
JJ
312 dt_parm_type = build_pointer_type (st_parameter[IOPARM_ptype_dt].type);
313
3f34855a
TB
314 iocall[IOCALL_X_INTEGER] = gfc_build_library_function_decl_with_spec (
315 get_identifier (PREFIX("transfer_integer")), ".wW",
316 void_type_node, 3, dt_parm_type, pvoid_type_node, gfc_int4_type_node);
317
6eb6875d
TK
318 iocall[IOCALL_X_INTEGER_WRITE] = gfc_build_library_function_decl_with_spec (
319 get_identifier (PREFIX("transfer_integer_write")), ".wR",
320 void_type_node, 3, dt_parm_type, pvoid_type_node, gfc_int4_type_node);
321
3f34855a
TB
322 iocall[IOCALL_X_LOGICAL] = gfc_build_library_function_decl_with_spec (
323 get_identifier (PREFIX("transfer_logical")), ".wW",
324 void_type_node, 3, dt_parm_type, pvoid_type_node, gfc_int4_type_node);
325
6eb6875d
TK
326 iocall[IOCALL_X_LOGICAL_WRITE] = gfc_build_library_function_decl_with_spec (
327 get_identifier (PREFIX("transfer_logical_write")), ".wR",
328 void_type_node, 3, dt_parm_type, pvoid_type_node, gfc_int4_type_node);
329
3f34855a
TB
330 iocall[IOCALL_X_CHARACTER] = gfc_build_library_function_decl_with_spec (
331 get_identifier (PREFIX("transfer_character")), ".wW",
332 void_type_node, 3, dt_parm_type, pvoid_type_node, gfc_int4_type_node);
333
6eb6875d
TK
334 iocall[IOCALL_X_CHARACTER_WRITE] = gfc_build_library_function_decl_with_spec (
335 get_identifier (PREFIX("transfer_character_write")), ".wR",
336 void_type_node, 3, dt_parm_type, pvoid_type_node, gfc_int4_type_node);
337
3f34855a
TB
338 iocall[IOCALL_X_CHARACTER_WIDE] = gfc_build_library_function_decl_with_spec (
339 get_identifier (PREFIX("transfer_character_wide")), ".wW",
340 void_type_node, 4, dt_parm_type, pvoid_type_node,
341 gfc_charlen_type_node, gfc_int4_type_node);
342
6eb6875d
TK
343 iocall[IOCALL_X_CHARACTER_WIDE_WRITE] =
344 gfc_build_library_function_decl_with_spec (
345 get_identifier (PREFIX("transfer_character_wide_write")), ".wR",
346 void_type_node, 4, dt_parm_type, pvoid_type_node,
347 gfc_charlen_type_node, gfc_int4_type_node);
348
3f34855a
TB
349 iocall[IOCALL_X_REAL] = gfc_build_library_function_decl_with_spec (
350 get_identifier (PREFIX("transfer_real")), ".wW",
351 void_type_node, 3, dt_parm_type, pvoid_type_node, gfc_int4_type_node);
352
6eb6875d
TK
353 iocall[IOCALL_X_REAL_WRITE] = gfc_build_library_function_decl_with_spec (
354 get_identifier (PREFIX("transfer_real_write")), ".wR",
355 void_type_node, 3, dt_parm_type, pvoid_type_node, gfc_int4_type_node);
356
3f34855a
TB
357 iocall[IOCALL_X_COMPLEX] = gfc_build_library_function_decl_with_spec (
358 get_identifier (PREFIX("transfer_complex")), ".wW",
359 void_type_node, 3, dt_parm_type, pvoid_type_node, gfc_int4_type_node);
360
6eb6875d
TK
361 iocall[IOCALL_X_COMPLEX_WRITE] = gfc_build_library_function_decl_with_spec (
362 get_identifier (PREFIX("transfer_complex_write")), ".wR",
363 void_type_node, 3, dt_parm_type, pvoid_type_node, gfc_int4_type_node);
364
1ec601bf
FXC
365 /* Version for __float128. */
366 iocall[IOCALL_X_REAL128] = gfc_build_library_function_decl_with_spec (
367 get_identifier (PREFIX("transfer_real128")), ".wW",
368 void_type_node, 3, dt_parm_type, pvoid_type_node, gfc_int4_type_node);
369
370 iocall[IOCALL_X_REAL128_WRITE] = gfc_build_library_function_decl_with_spec (
371 get_identifier (PREFIX("transfer_real128_write")), ".wR",
372 void_type_node, 3, dt_parm_type, pvoid_type_node, gfc_int4_type_node);
373
374 iocall[IOCALL_X_COMPLEX128] = gfc_build_library_function_decl_with_spec (
375 get_identifier (PREFIX("transfer_complex128")), ".wW",
376 void_type_node, 3, dt_parm_type, pvoid_type_node, gfc_int4_type_node);
377
378 iocall[IOCALL_X_COMPLEX128_WRITE] = gfc_build_library_function_decl_with_spec (
379 get_identifier (PREFIX("transfer_complex128_write")), ".wR",
380 void_type_node, 3, dt_parm_type, pvoid_type_node, gfc_int4_type_node);
381
3f34855a 382 iocall[IOCALL_X_ARRAY] = gfc_build_library_function_decl_with_spec (
d4d9b0a6 383 get_identifier (PREFIX("transfer_array")), ".ww",
3f34855a
TB
384 void_type_node, 4, dt_parm_type, pvoid_type_node,
385 integer_type_node, gfc_charlen_type_node);
18623fae 386
6eb6875d
TK
387 iocall[IOCALL_X_ARRAY_WRITE] = gfc_build_library_function_decl_with_spec (
388 get_identifier (PREFIX("transfer_array_write")), ".wr",
389 void_type_node, 4, dt_parm_type, pvoid_type_node,
390 integer_type_node, gfc_charlen_type_node);
391
6de9cd9a
DN
392 /* Library entry points */
393
3f34855a
TB
394 iocall[IOCALL_READ] = gfc_build_library_function_decl_with_spec (
395 get_identifier (PREFIX("st_read")), ".w",
396 void_type_node, 1, dt_parm_type);
6de9cd9a 397
3f34855a
TB
398 iocall[IOCALL_WRITE] = gfc_build_library_function_decl_with_spec (
399 get_identifier (PREFIX("st_write")), ".w",
400 void_type_node, 1, dt_parm_type);
5e805e44
JJ
401
402 parm_type = build_pointer_type (st_parameter[IOPARM_ptype_open].type);
3f34855a
TB
403 iocall[IOCALL_OPEN] = gfc_build_library_function_decl_with_spec (
404 get_identifier (PREFIX("st_open")), ".w",
405 void_type_node, 1, parm_type);
5e805e44
JJ
406
407 parm_type = build_pointer_type (st_parameter[IOPARM_ptype_close].type);
3f34855a
TB
408 iocall[IOCALL_CLOSE] = gfc_build_library_function_decl_with_spec (
409 get_identifier (PREFIX("st_close")), ".w",
410 void_type_node, 1, parm_type);
6de9cd9a 411
5e805e44 412 parm_type = build_pointer_type (st_parameter[IOPARM_ptype_inquire].type);
3f34855a
TB
413 iocall[IOCALL_INQUIRE] = gfc_build_library_function_decl_with_spec (
414 get_identifier (PREFIX("st_inquire")), ".w",
a19d2b95 415 void_type_node, 1, parm_type);
6de9cd9a 416
3f34855a
TB
417 iocall[IOCALL_IOLENGTH] = gfc_build_library_function_decl_with_spec(
418 get_identifier (PREFIX("st_iolength")), ".w",
419 void_type_node, 1, dt_parm_type);
8750f9cd 420
3f34855a 421 /* TODO: Change when asynchronous I/O is implemented. */
6f0f0b2e 422 parm_type = build_pointer_type (st_parameter[IOPARM_ptype_wait].type);
3f34855a
TB
423 iocall[IOCALL_WAIT] = gfc_build_library_function_decl_with_spec (
424 get_identifier (PREFIX("st_wait")), ".X",
a19d2b95 425 void_type_node, 1, parm_type);
6f0f0b2e 426
5e805e44 427 parm_type = build_pointer_type (st_parameter[IOPARM_ptype_filepos].type);
3f34855a
TB
428 iocall[IOCALL_REWIND] = gfc_build_library_function_decl_with_spec (
429 get_identifier (PREFIX("st_rewind")), ".w",
a19d2b95 430 void_type_node, 1, parm_type);
6de9cd9a 431
3f34855a
TB
432 iocall[IOCALL_BACKSPACE] = gfc_build_library_function_decl_with_spec (
433 get_identifier (PREFIX("st_backspace")), ".w",
a19d2b95 434 void_type_node, 1, parm_type);
6de9cd9a 435
3f34855a
TB
436 iocall[IOCALL_ENDFILE] = gfc_build_library_function_decl_with_spec (
437 get_identifier (PREFIX("st_endfile")), ".w",
a19d2b95 438 void_type_node, 1, parm_type);
6403ec5f 439
3f34855a
TB
440 iocall[IOCALL_FLUSH] = gfc_build_library_function_decl_with_spec (
441 get_identifier (PREFIX("st_flush")), ".w",
a19d2b95 442 void_type_node, 1, parm_type);
6403ec5f 443
6de9cd9a
DN
444 /* Library helpers */
445
3f34855a
TB
446 iocall[IOCALL_READ_DONE] = gfc_build_library_function_decl_with_spec (
447 get_identifier (PREFIX("st_read_done")), ".w",
a19d2b95 448 void_type_node, 1, dt_parm_type);
8750f9cd 449
3f34855a
TB
450 iocall[IOCALL_WRITE_DONE] = gfc_build_library_function_decl_with_spec (
451 get_identifier (PREFIX("st_write_done")), ".w",
a19d2b95 452 void_type_node, 1, dt_parm_type);
8750f9cd 453
3f34855a
TB
454 iocall[IOCALL_IOLENGTH_DONE] = gfc_build_library_function_decl_with_spec (
455 get_identifier (PREFIX("st_iolength_done")), ".w",
a19d2b95 456 void_type_node, 1, dt_parm_type);
6de9cd9a 457
3f34855a
TB
458 iocall[IOCALL_SET_NML_VAL] = gfc_build_library_function_decl_with_spec (
459 get_identifier (PREFIX("st_set_nml_var")), ".w.R",
460 void_type_node, 6, dt_parm_type, pvoid_type_node, pvoid_type_node,
a19d2b95 461 void_type_node, gfc_charlen_type_node, gfc_int4_type_node);
6de9cd9a 462
3f34855a
TB
463 iocall[IOCALL_SET_NML_VAL_DIM] = gfc_build_library_function_decl_with_spec (
464 get_identifier (PREFIX("st_set_nml_var_dim")), ".w",
465 void_type_node, 5, dt_parm_type, gfc_int4_type_node,
466 gfc_array_index_type, gfc_array_index_type, gfc_array_index_type);
6de9cd9a
DN
467}
468
469
5e805e44
JJ
470/* Generate code to store an integer constant into the
471 st_parameter_XXX structure. */
472
473static unsigned int
474set_parameter_const (stmtblock_t *block, tree var, enum iofield type,
475 unsigned int val)
476{
477 tree tmp;
478 gfc_st_parameter_field *p = &st_parameter_field[type];
479
480 if (p->param_type == IOPARM_ptype_common)
65a9ca82
TB
481 var = fold_build3_loc (input_location, COMPONENT_REF,
482 st_parameter[IOPARM_ptype_common].type,
483 var, TYPE_FIELDS (TREE_TYPE (var)), NULL_TREE);
484 tmp = fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (p->field),
485 var, p->field, NULL_TREE);
726a989a 486 gfc_add_modify (block, tmp, build_int_cst (TREE_TYPE (p->field), val));
5e805e44
JJ
487 return p->mask;
488}
489
490
49de9e73 491/* Generate code to store a non-string I/O parameter into the
5e805e44 492 st_parameter_XXX structure. This is a pass by value. */
6de9cd9a 493
5e805e44
JJ
494static unsigned int
495set_parameter_value (stmtblock_t *block, tree var, enum iofield type,
496 gfc_expr *e)
6de9cd9a
DN
497{
498 gfc_se se;
499 tree tmp;
5e805e44 500 gfc_st_parameter_field *p = &st_parameter_field[type];
f96d606f 501 tree dest_type = TREE_TYPE (p->field);
6de9cd9a
DN
502
503 gfc_init_se (&se, NULL);
f96d606f
JD
504 gfc_conv_expr_val (&se, e);
505
506 /* If we're storing a UNIT number, we need to check it first. */
9ad55c33 507 if (type == IOPARM_common_unit && e->ts.kind > 4)
f96d606f 508 {
9ad55c33 509 tree cond, val;
f96d606f
JD
510 int i;
511
f96d606f
JD
512 /* Don't evaluate the UNIT number multiple times. */
513 se.expr = gfc_evaluate_now (se.expr, &se.pre);
514
9ad55c33
JD
515 /* UNIT numbers should be greater than the min. */
516 i = gfc_validate_kind (BT_INTEGER, 4, false);
517 val = gfc_conv_mpz_to_tree (gfc_integer_kinds[i].pedantic_min_int, 4);
65a9ca82
TB
518 cond = fold_build2_loc (input_location, LT_EXPR, boolean_type_node,
519 se.expr,
520 fold_convert (TREE_TYPE (se.expr), val));
d74b97cc 521 gfc_trans_io_runtime_check (cond, var, LIBERROR_BAD_UNIT,
9ad55c33 522 "Unit number in I/O statement too small",
f96d606f
JD
523 &se.pre);
524
525 /* UNIT numbers should be less than the max. */
9ad55c33 526 val = gfc_conv_mpz_to_tree (gfc_integer_kinds[i].huge, 4);
65a9ca82
TB
527 cond = fold_build2_loc (input_location, GT_EXPR, boolean_type_node,
528 se.expr,
529 fold_convert (TREE_TYPE (se.expr), val));
d74b97cc 530 gfc_trans_io_runtime_check (cond, var, LIBERROR_BAD_UNIT,
f96d606f
JD
531 "Unit number in I/O statement too large",
532 &se.pre);
533
534 }
535
536 se.expr = convert (dest_type, se.expr);
6de9cd9a
DN
537 gfc_add_block_to_block (block, &se.pre);
538
5e805e44 539 if (p->param_type == IOPARM_ptype_common)
65a9ca82
TB
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);
f96d606f 543
65a9ca82
TB
544 tmp = fold_build3_loc (input_location, COMPONENT_REF, dest_type, var,
545 p->field, NULL_TREE);
726a989a 546 gfc_add_modify (block, tmp, se.expr);
5e805e44 547 return p->mask;
6de9cd9a
DN
548}
549
550
49de9e73 551/* Generate code to store a non-string I/O parameter into the
5e805e44 552 st_parameter_XXX structure. This is pass by reference. */
6de9cd9a 553
5e805e44
JJ
554static unsigned int
555set_parameter_ref (stmtblock_t *block, stmtblock_t *postblock,
556 tree var, enum iofield type, gfc_expr *e)
6de9cd9a
DN
557{
558 gfc_se se;
5e805e44
JJ
559 tree tmp, addr;
560 gfc_st_parameter_field *p = &st_parameter_field[type];
6de9cd9a 561
5e805e44 562 gcc_assert (e->ts.type == BT_INTEGER || e->ts.type == BT_LOGICAL);
6de9cd9a 563 gfc_init_se (&se, NULL);
5e805e44 564 gfc_conv_expr_lhs (&se, e);
6de9cd9a 565
6de9cd9a
DN
566 gfc_add_block_to_block (block, &se.pre);
567
5e805e44
JJ
568 if (TYPE_MODE (TREE_TYPE (se.expr))
569 == TYPE_MODE (TREE_TYPE (TREE_TYPE (p->field))))
f96d606f 570 {
628c189e 571 addr = convert (TREE_TYPE (p->field), gfc_build_addr_expr (NULL_TREE, se.expr));
f96d606f
JD
572
573 /* If this is for the iostat variable initialize the
d74b97cc 574 user variable to LIBERROR_OK which is zero. */
f96d606f 575 if (type == IOPARM_common_iostat)
726a989a 576 gfc_add_modify (block, se.expr,
d74b97cc 577 build_int_cst (TREE_TYPE (se.expr), LIBERROR_OK));
f96d606f 578 }
5e805e44
JJ
579 else
580 {
581 /* The type used by the library has different size
f96d606f
JD
582 from the type of the variable supplied by the user.
583 Need to use a temporary. */
584 tree tmpvar = gfc_create_var (TREE_TYPE (TREE_TYPE (p->field)),
585 st_parameter_field[type].name);
586
587 /* If this is for the iostat variable, initialize the
d74b97cc 588 user variable to LIBERROR_OK which is zero. */
f96d606f 589 if (type == IOPARM_common_iostat)
726a989a 590 gfc_add_modify (block, tmpvar,
d74b97cc 591 build_int_cst (TREE_TYPE (tmpvar), LIBERROR_OK));
f96d606f 592
628c189e 593 addr = gfc_build_addr_expr (NULL_TREE, tmpvar);
f96d606f 594 /* After the I/O operation, we set the variable from the temporary. */
5e805e44 595 tmp = convert (TREE_TYPE (se.expr), tmpvar);
726a989a 596 gfc_add_modify (postblock, se.expr, tmp);
f96d606f 597 }
5e805e44
JJ
598
599 if (p->param_type == IOPARM_ptype_common)
65a9ca82
TB
600 var = fold_build3_loc (input_location, COMPONENT_REF,
601 st_parameter[IOPARM_ptype_common].type,
602 var, TYPE_FIELDS (TREE_TYPE (var)), NULL_TREE);
603 tmp = fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (p->field),
604 var, p->field, NULL_TREE);
726a989a 605 gfc_add_modify (block, tmp, addr);
5e805e44 606 return p->mask;
6de9cd9a
DN
607}
608
d3642f89
FW
609/* Given an array expr, find its address and length to get a string. If the
610 array is full, the string's address is the address of array's first element
7e279142 611 and the length is the size of the whole array. If it is an element, the
d3642f89 612 string's address is the element's address and the length is the rest size of
7e279142 613 the array. */
d3642f89
FW
614
615static void
616gfc_convert_array_to_string (gfc_se * se, gfc_expr * e)
617{
d3642f89 618 tree size;
d3642f89 619
7e279142 620 if (e->rank == 0)
d3642f89 621 {
7e279142
JJ
622 tree type, array, tmp;
623 gfc_symbol *sym;
624 int rank;
625
626 /* If it is an element, we need its address and size of the rest. */
627 gcc_assert (e->expr_type == EXPR_VARIABLE);
628 gcc_assert (e->ref->u.ar.type == AR_ELEMENT);
629 sym = e->symtree->n.sym;
630 rank = sym->as->rank - 1;
d3642f89 631 gfc_conv_expr (se, e);
d3642f89 632
7e279142
JJ
633 array = sym->backend_decl;
634 type = TREE_TYPE (array);
d3642f89 635
7e279142
JJ
636 if (GFC_ARRAY_TYPE_P (type))
637 size = GFC_TYPE_ARRAY_SIZE (type);
638 else
639 {
640 gcc_assert (GFC_DESCRIPTOR_TYPE_P (type));
641 size = gfc_conv_array_stride (array, rank);
65a9ca82
TB
642 tmp = fold_build2_loc (input_location, MINUS_EXPR,
643 gfc_array_index_type,
644 gfc_conv_array_ubound (array, rank),
645 gfc_conv_array_lbound (array, rank));
646 tmp = fold_build2_loc (input_location, PLUS_EXPR,
647 gfc_array_index_type, tmp,
648 gfc_index_one_node);
649 size = fold_build2_loc (input_location, MULT_EXPR,
650 gfc_array_index_type, tmp, size);
7e279142
JJ
651 }
652 gcc_assert (size);
d3642f89 653
65a9ca82
TB
654 size = fold_build2_loc (input_location, MINUS_EXPR,
655 gfc_array_index_type, size,
656 TREE_OPERAND (se->expr, 1));
628c189e 657 se->expr = gfc_build_addr_expr (NULL_TREE, se->expr);
7e279142 658 tmp = TYPE_SIZE_UNIT (gfc_get_element_type (type));
65a9ca82
TB
659 size = fold_build2_loc (input_location, MULT_EXPR,
660 gfc_array_index_type, size,
661 fold_convert (gfc_array_index_type, tmp));
7e279142
JJ
662 se->string_length = fold_convert (gfc_charlen_type_node, size);
663 return;
d3642f89
FW
664 }
665
2960a368 666 gfc_conv_array_parameter (se, e, true, NULL, NULL, &size);
d3642f89
FW
667 se->string_length = fold_convert (gfc_charlen_type_node, size);
668}
6de9cd9a 669
109b0ac2 670
6de9cd9a 671/* Generate code to store a string and its length into the
5e805e44 672 st_parameter_XXX structure. */
6de9cd9a 673
5e805e44 674static unsigned int
6de9cd9a 675set_string (stmtblock_t * block, stmtblock_t * postblock, tree var,
5e805e44 676 enum iofield type, gfc_expr * e)
6de9cd9a
DN
677{
678 gfc_se se;
679 tree tmp;
6de9cd9a
DN
680 tree io;
681 tree len;
5e805e44 682 gfc_st_parameter_field *p = &st_parameter_field[type];
6de9cd9a
DN
683
684 gfc_init_se (&se, NULL);
6de9cd9a 685
5e805e44 686 if (p->param_type == IOPARM_ptype_common)
65a9ca82
TB
687 var = fold_build3_loc (input_location, COMPONENT_REF,
688 st_parameter[IOPARM_ptype_common].type,
689 var, TYPE_FIELDS (TREE_TYPE (var)), NULL_TREE);
690 io = fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (p->field),
44855d8c 691 var, p->field, NULL_TREE);
65a9ca82
TB
692 len = fold_build3_loc (input_location, COMPONENT_REF,
693 TREE_TYPE (p->field_len),
694 var, p->field_len, NULL_TREE);
6de9cd9a 695
7ab92584 696 /* Integer variable assigned a format label. */
7e279142
JJ
697 if (e->ts.type == BT_INTEGER
698 && e->rank == 0
699 && e->symtree->n.sym->attr.assign == 1)
6de9cd9a 700 {
dd18a33b 701 char * msg;
c8fe94c7 702 tree cond;
dd18a33b 703
ce2df7c6 704 gfc_conv_label_variable (&se, e);
6de9cd9a 705 tmp = GFC_DECL_STRING_LEN (se.expr);
65a9ca82
TB
706 cond = fold_build2_loc (input_location, LT_EXPR, boolean_type_node,
707 tmp, build_int_cst (TREE_TYPE (tmp), 0));
dd18a33b 708
c8fe94c7
FXC
709 asprintf(&msg, "Label assigned to variable '%s' (%%ld) is not a format "
710 "label", e->symtree->name);
0d52899f 711 gfc_trans_runtime_check (true, false, cond, &se.pre, &e->where, msg,
c8fe94c7 712 fold_convert (long_integer_type_node, tmp));
cede9502 713 free (msg);
dd18a33b 714
726a989a 715 gfc_add_modify (&se.pre, io,
b078dfbf 716 fold_convert (TREE_TYPE (io), GFC_DECL_ASSIGN_ADDR (se.expr)));
726a989a 717 gfc_add_modify (&se.pre, len, GFC_DECL_STRING_LEN (se.expr));
6de9cd9a
DN
718 }
719 else
720 {
d3642f89
FW
721 /* General character. */
722 if (e->ts.type == BT_CHARACTER && e->rank == 0)
723 gfc_conv_expr (&se, e);
724 /* Array assigned Hollerith constant or character array. */
7e279142 725 else if (e->rank > 0 || (e->symtree && e->symtree->n.sym->as->rank > 0))
d3642f89
FW
726 gfc_convert_array_to_string (&se, e);
727 else
728 gcc_unreachable ();
729
6de9cd9a 730 gfc_conv_string_parameter (&se);
726a989a
RB
731 gfc_add_modify (&se.pre, io, fold_convert (TREE_TYPE (io), se.expr));
732 gfc_add_modify (&se.pre, len, se.string_length);
6de9cd9a
DN
733 }
734
735 gfc_add_block_to_block (block, &se.pre);
736 gfc_add_block_to_block (postblock, &se.post);
5e805e44 737 return p->mask;
6de9cd9a
DN
738}
739
740
109b0ac2
PT
741/* Generate code to store the character (array) and the character length
742 for an internal unit. */
743
5e805e44 744static unsigned int
d4feb3d3
PT
745set_internal_unit (stmtblock_t * block, stmtblock_t * post_block,
746 tree var, gfc_expr * e)
109b0ac2
PT
747{
748 gfc_se se;
749 tree io;
750 tree len;
751 tree desc;
752 tree tmp;
5e805e44
JJ
753 gfc_st_parameter_field *p;
754 unsigned int mask;
109b0ac2
PT
755
756 gfc_init_se (&se, NULL);
757
5e805e44
JJ
758 p = &st_parameter_field[IOPARM_dt_internal_unit];
759 mask = p->mask;
65a9ca82
TB
760 io = fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (p->field),
761 var, p->field, NULL_TREE);
762 len = fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (p->field_len),
763 var, p->field_len, NULL_TREE);
5e805e44 764 p = &st_parameter_field[IOPARM_dt_internal_unit_desc];
65a9ca82
TB
765 desc = fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (p->field),
766 var, p->field, NULL_TREE);
109b0ac2
PT
767
768 gcc_assert (e->ts.type == BT_CHARACTER);
769
770 /* Character scalars. */
771 if (e->rank == 0)
772 {
773 gfc_conv_expr (&se, e);
774 gfc_conv_string_parameter (&se);
775 tmp = se.expr;
c3238e32 776 se.expr = build_int_cst (pchar_type_node, 0);
109b0ac2
PT
777 }
778
779 /* Character array. */
64db4d29 780 else if (e->rank > 0)
109b0ac2 781 {
1d6b7f39 782 if (is_subref_array (e))
d4feb3d3
PT
783 {
784 /* Use a temporary for components of arrays of derived types
785 or substring array references. */
1d6b7f39 786 gfc_conv_subref_array_arg (&se, e, 0,
430f2d1f 787 last_dt == READ ? INTENT_IN : INTENT_OUT, false);
db3927fb
AH
788 tmp = build_fold_indirect_ref_loc (input_location,
789 se.expr);
d4feb3d3
PT
790 se.expr = gfc_build_addr_expr (pchar_type_node, tmp);
791 tmp = gfc_conv_descriptor_data_get (tmp);
792 }
793 else
794 {
795 /* Return the data pointer and rank from the descriptor. */
2960a368 796 gfc_conv_expr_descriptor (&se, e);
d4feb3d3
PT
797 tmp = gfc_conv_descriptor_data_get (se.expr);
798 se.expr = gfc_build_addr_expr (pchar_type_node, se.expr);
799 }
109b0ac2
PT
800 }
801 else
802 gcc_unreachable ();
803
804 /* The cast is needed for character substrings and the descriptor
805 data. */
726a989a
RB
806 gfc_add_modify (&se.pre, io, fold_convert (TREE_TYPE (io), tmp));
807 gfc_add_modify (&se.pre, len,
d4feb3d3 808 fold_convert (TREE_TYPE (len), se.string_length));
726a989a 809 gfc_add_modify (&se.pre, desc, se.expr);
109b0ac2
PT
810
811 gfc_add_block_to_block (block, &se.pre);
d4feb3d3 812 gfc_add_block_to_block (post_block, &se.post);
5e805e44 813 return mask;
109b0ac2
PT
814}
815
6de9cd9a
DN
816/* Add a case to a IO-result switch. */
817
818static void
819add_case (int label_value, gfc_st_label * label, stmtblock_t * body)
820{
821 tree tmp, value;
822
823 if (label == NULL)
824 return; /* No label, no case */
825
df09d1d5 826 value = build_int_cst (integer_type_node, label_value);
6de9cd9a
DN
827
828 /* Make a backend label for this case. */
c006df4e 829 tmp = gfc_build_label_decl (NULL_TREE);
6de9cd9a
DN
830
831 /* And the case itself. */
3d528853 832 tmp = build_case_label (value, NULL_TREE, tmp);
6de9cd9a
DN
833 gfc_add_expr_to_block (body, tmp);
834
835 /* Jump to the label. */
836 tmp = build1_v (GOTO_EXPR, gfc_get_label_decl (label));
837 gfc_add_expr_to_block (body, tmp);
838}
839
840
841/* Generate a switch statement that branches to the correct I/O
842 result label. The last statement of an I/O call stores the
843 result into a variable because there is often cleanup that
844 must be done before the switch, so a temporary would have to
845 be created anyway. */
846
847static void
5e805e44 848io_result (stmtblock_t * block, tree var, gfc_st_label * err_label,
6de9cd9a
DN
849 gfc_st_label * end_label, gfc_st_label * eor_label)
850{
851 stmtblock_t body;
852 tree tmp, rc;
5e805e44 853 gfc_st_parameter_field *p = &st_parameter_field[IOPARM_common_flags];
6de9cd9a
DN
854
855 /* If no labels are specified, ignore the result instead
856 of building an empty switch. */
857 if (err_label == NULL
858 && end_label == NULL
859 && eor_label == NULL)
860 return;
861
862 /* Build a switch statement. */
863 gfc_start_block (&body);
864
865 /* The label values here must be the same as the values
866 in the library_return enum in the runtime library */
867 add_case (1, err_label, &body);
868 add_case (2, end_label, &body);
869 add_case (3, eor_label, &body);
870
871 tmp = gfc_finish_block (&body);
872
65a9ca82
TB
873 var = fold_build3_loc (input_location, COMPONENT_REF,
874 st_parameter[IOPARM_ptype_common].type,
875 var, TYPE_FIELDS (TREE_TYPE (var)), NULL_TREE);
876 rc = fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (p->field),
877 var, p->field, NULL_TREE);
878 rc = fold_build2_loc (input_location, BIT_AND_EXPR, TREE_TYPE (rc),
879 rc, build_int_cst (TREE_TYPE (rc),
880 IOPARM_common_libreturn_mask));
6de9cd9a 881
0cd2402d
SB
882 tmp = fold_build3_loc (input_location, SWITCH_EXPR, NULL_TREE,
883 rc, tmp, NULL_TREE);
6de9cd9a
DN
884
885 gfc_add_expr_to_block (block, tmp);
886}
887
888
889/* Store the current file and line number to variables so that if a
890 library call goes awry, we can tell the user where the problem is. */
891
892static void
5e805e44 893set_error_locus (stmtblock_t * block, tree var, locus * where)
6de9cd9a
DN
894{
895 gfc_file *f;
5e805e44 896 tree str, locus_file;
6de9cd9a 897 int line;
5e805e44 898 gfc_st_parameter_field *p = &st_parameter_field[IOPARM_common_filename];
6de9cd9a 899
65a9ca82
TB
900 locus_file = fold_build3_loc (input_location, COMPONENT_REF,
901 st_parameter[IOPARM_ptype_common].type,
902 var, TYPE_FIELDS (TREE_TYPE (var)), NULL_TREE);
903 locus_file = fold_build3_loc (input_location, COMPONENT_REF,
904 TREE_TYPE (p->field), locus_file,
905 p->field, NULL_TREE);
d4fa05b9 906 f = where->lb->file;
5e805e44 907 str = gfc_build_cstring_const (f->filename);
6de9cd9a 908
5e805e44 909 str = gfc_build_addr_expr (pchar_type_node, str);
726a989a 910 gfc_add_modify (block, locus_file, str);
6de9cd9a 911
c8cc8542 912 line = LOCATION_LINE (where->lb->location);
5e805e44 913 set_parameter_const (block, var, IOPARM_common_line, line);
6de9cd9a
DN
914}
915
916
917/* Translate an OPEN statement. */
918
919tree
920gfc_trans_open (gfc_code * code)
921{
922 stmtblock_t block, post_block;
923 gfc_open *p;
5e805e44
JJ
924 tree tmp, var;
925 unsigned int mask = 0;
6de9cd9a 926
5e805e44 927 gfc_start_block (&block);
6de9cd9a
DN
928 gfc_init_block (&post_block);
929
5e805e44
JJ
930 var = gfc_create_var (st_parameter[IOPARM_ptype_open].type, "open_parm");
931
932 set_error_locus (&block, var, &code->loc);
6de9cd9a
DN
933 p = code->ext.open;
934
f96d606f
JD
935 if (p->iomsg)
936 mask |= set_string (&block, &post_block, var, IOPARM_common_iomsg,
937 p->iomsg);
938
939 if (p->iostat)
940 mask |= set_parameter_ref (&block, &post_block, var, IOPARM_common_iostat,
941 p->iostat);
942
943 if (p->err)
944 mask |= IOPARM_common_err;
6de9cd9a
DN
945
946 if (p->file)
5e805e44 947 mask |= set_string (&block, &post_block, var, IOPARM_open_file, p->file);
6de9cd9a
DN
948
949 if (p->status)
5e805e44
JJ
950 mask |= set_string (&block, &post_block, var, IOPARM_open_status,
951 p->status);
6de9cd9a
DN
952
953 if (p->access)
5e805e44
JJ
954 mask |= set_string (&block, &post_block, var, IOPARM_open_access,
955 p->access);
6de9cd9a
DN
956
957 if (p->form)
5e805e44 958 mask |= set_string (&block, &post_block, var, IOPARM_open_form, p->form);
6de9cd9a
DN
959
960 if (p->recl)
5e805e44 961 mask |= set_parameter_value (&block, var, IOPARM_open_recl_in, p->recl);
6de9cd9a
DN
962
963 if (p->blank)
5e805e44
JJ
964 mask |= set_string (&block, &post_block, var, IOPARM_open_blank,
965 p->blank);
6de9cd9a
DN
966
967 if (p->position)
5e805e44
JJ
968 mask |= set_string (&block, &post_block, var, IOPARM_open_position,
969 p->position);
6de9cd9a
DN
970
971 if (p->action)
5e805e44
JJ
972 mask |= set_string (&block, &post_block, var, IOPARM_open_action,
973 p->action);
6de9cd9a
DN
974
975 if (p->delim)
5e805e44
JJ
976 mask |= set_string (&block, &post_block, var, IOPARM_open_delim,
977 p->delim);
6de9cd9a
DN
978
979 if (p->pad)
5e805e44 980 mask |= set_string (&block, &post_block, var, IOPARM_open_pad, p->pad);
6de9cd9a 981
6f0f0b2e
JD
982 if (p->decimal)
983 mask |= set_string (&block, &post_block, var, IOPARM_open_decimal,
984 p->decimal);
985
986 if (p->encoding)
987 mask |= set_string (&block, &post_block, var, IOPARM_open_encoding,
988 p->encoding);
989
990 if (p->round)
991 mask |= set_string (&block, &post_block, var, IOPARM_open_round, p->round);
992
993 if (p->sign)
994 mask |= set_string (&block, &post_block, var, IOPARM_open_sign, p->sign);
995
996 if (p->asynchronous)
997 mask |= set_string (&block, &post_block, var, IOPARM_open_asynchronous,
998 p->asynchronous);
999
181c9f4a
TK
1000 if (p->convert)
1001 mask |= set_string (&block, &post_block, var, IOPARM_open_convert,
1002 p->convert);
9ad55c33
JD
1003
1004 if (p->newunit)
1005 mask |= set_parameter_ref (&block, &post_block, var, IOPARM_open_newunit,
1006 p->newunit);
181c9f4a 1007
5e805e44
JJ
1008 set_parameter_const (&block, var, IOPARM_common_flags, mask);
1009
f96d606f
JD
1010 if (p->unit)
1011 set_parameter_value (&block, var, IOPARM_common_unit, p->unit);
1012 else
1013 set_parameter_const (&block, var, IOPARM_common_unit, 0);
1014
628c189e 1015 tmp = gfc_build_addr_expr (NULL_TREE, var);
db3927fb
AH
1016 tmp = build_call_expr_loc (input_location,
1017 iocall[IOCALL_OPEN], 1, tmp);
6de9cd9a
DN
1018 gfc_add_expr_to_block (&block, tmp);
1019
1020 gfc_add_block_to_block (&block, &post_block);
1021
5e805e44 1022 io_result (&block, var, p->err, NULL, NULL);
6de9cd9a
DN
1023
1024 return gfc_finish_block (&block);
1025}
1026
1027
1028/* Translate a CLOSE statement. */
1029
1030tree
1031gfc_trans_close (gfc_code * code)
1032{
1033 stmtblock_t block, post_block;
1034 gfc_close *p;
5e805e44
JJ
1035 tree tmp, var;
1036 unsigned int mask = 0;
6de9cd9a 1037
5e805e44 1038 gfc_start_block (&block);
6de9cd9a
DN
1039 gfc_init_block (&post_block);
1040
5e805e44
JJ
1041 var = gfc_create_var (st_parameter[IOPARM_ptype_close].type, "close_parm");
1042
1043 set_error_locus (&block, var, &code->loc);
6de9cd9a
DN
1044 p = code->ext.close;
1045
7aba8abe 1046 if (p->iomsg)
5e805e44
JJ
1047 mask |= set_string (&block, &post_block, var, IOPARM_common_iomsg,
1048 p->iomsg);
7aba8abe 1049
6de9cd9a 1050 if (p->iostat)
5e805e44
JJ
1051 mask |= set_parameter_ref (&block, &post_block, var, IOPARM_common_iostat,
1052 p->iostat);
6de9cd9a
DN
1053
1054 if (p->err)
5e805e44
JJ
1055 mask |= IOPARM_common_err;
1056
f96d606f
JD
1057 if (p->status)
1058 mask |= set_string (&block, &post_block, var, IOPARM_close_status,
1059 p->status);
1060
5e805e44 1061 set_parameter_const (&block, var, IOPARM_common_flags, mask);
6de9cd9a 1062
f96d606f
JD
1063 if (p->unit)
1064 set_parameter_value (&block, var, IOPARM_common_unit, p->unit);
1065 else
1066 set_parameter_const (&block, var, IOPARM_common_unit, 0);
1067
628c189e 1068 tmp = gfc_build_addr_expr (NULL_TREE, var);
db3927fb
AH
1069 tmp = build_call_expr_loc (input_location,
1070 iocall[IOCALL_CLOSE], 1, tmp);
6de9cd9a
DN
1071 gfc_add_expr_to_block (&block, tmp);
1072
1073 gfc_add_block_to_block (&block, &post_block);
1074
5e805e44 1075 io_result (&block, var, p->err, NULL, NULL);
6de9cd9a
DN
1076
1077 return gfc_finish_block (&block);
1078}
1079
1080
1081/* Common subroutine for building a file positioning statement. */
1082
1083static tree
1084build_filepos (tree function, gfc_code * code)
1085{
7aba8abe 1086 stmtblock_t block, post_block;
6de9cd9a 1087 gfc_filepos *p;
5e805e44
JJ
1088 tree tmp, var;
1089 unsigned int mask = 0;
6de9cd9a
DN
1090
1091 p = code->ext.filepos;
1092
5e805e44 1093 gfc_start_block (&block);
7aba8abe 1094 gfc_init_block (&post_block);
6de9cd9a 1095
5e805e44
JJ
1096 var = gfc_create_var (st_parameter[IOPARM_ptype_filepos].type,
1097 "filepos_parm");
1098
1099 set_error_locus (&block, var, &code->loc);
6de9cd9a 1100
7aba8abe 1101 if (p->iomsg)
5e805e44
JJ
1102 mask |= set_string (&block, &post_block, var, IOPARM_common_iomsg,
1103 p->iomsg);
7aba8abe 1104
6de9cd9a 1105 if (p->iostat)
5e805e44
JJ
1106 mask |= set_parameter_ref (&block, &post_block, var, IOPARM_common_iostat,
1107 p->iostat);
6de9cd9a
DN
1108
1109 if (p->err)
5e805e44
JJ
1110 mask |= IOPARM_common_err;
1111
1112 set_parameter_const (&block, var, IOPARM_common_flags, mask);
6de9cd9a 1113
f96d606f
JD
1114 if (p->unit)
1115 set_parameter_value (&block, var, IOPARM_common_unit, p->unit);
1116 else
1117 set_parameter_const (&block, var, IOPARM_common_unit, 0);
1118
628c189e 1119 tmp = gfc_build_addr_expr (NULL_TREE, var);
db3927fb
AH
1120 tmp = build_call_expr_loc (input_location,
1121 function, 1, tmp);
6de9cd9a
DN
1122 gfc_add_expr_to_block (&block, tmp);
1123
7aba8abe
TK
1124 gfc_add_block_to_block (&block, &post_block);
1125
5e805e44 1126 io_result (&block, var, p->err, NULL, NULL);
6de9cd9a
DN
1127
1128 return gfc_finish_block (&block);
1129}
1130
1131
1132/* Translate a BACKSPACE statement. */
1133
1134tree
1135gfc_trans_backspace (gfc_code * code)
1136{
5e805e44 1137 return build_filepos (iocall[IOCALL_BACKSPACE], code);
6de9cd9a
DN
1138}
1139
1140
1141/* Translate an ENDFILE statement. */
1142
1143tree
1144gfc_trans_endfile (gfc_code * code)
1145{
5e805e44 1146 return build_filepos (iocall[IOCALL_ENDFILE], code);
6de9cd9a
DN
1147}
1148
1149
1150/* Translate a REWIND statement. */
1151
1152tree
1153gfc_trans_rewind (gfc_code * code)
1154{
5e805e44 1155 return build_filepos (iocall[IOCALL_REWIND], code);
6de9cd9a
DN
1156}
1157
1158
6403ec5f
JB
1159/* Translate a FLUSH statement. */
1160
1161tree
1162gfc_trans_flush (gfc_code * code)
1163{
5e805e44 1164 return build_filepos (iocall[IOCALL_FLUSH], code);
6403ec5f
JB
1165}
1166
1167
c16dd6a8
JD
1168/* Create a dummy iostat variable to catch any error due to bad unit. */
1169
1170static gfc_expr *
1171create_dummy_iostat (void)
1172{
1173 gfc_symtree *st;
1174 gfc_expr *e;
1175
1176 gfc_get_ha_sym_tree ("@iostat", &st);
1177 st->n.sym->ts.type = BT_INTEGER;
1178 st->n.sym->ts.kind = gfc_default_integer_kind;
1179 gfc_set_sym_referenced (st->n.sym);
bc9d9552 1180 gfc_commit_symbol (st->n.sym);
c16dd6a8
JD
1181 st->n.sym->backend_decl
1182 = gfc_create_var (gfc_get_int_type (st->n.sym->ts.kind),
1183 st->n.sym->name);
1184
1185 e = gfc_get_expr ();
1186 e->expr_type = EXPR_VARIABLE;
1187 e->symtree = st;
1188 e->ts.type = BT_INTEGER;
1189 e->ts.kind = st->n.sym->ts.kind;
1190
1191 return e;
1192}
1193
1194
6de9cd9a
DN
1195/* Translate the non-IOLENGTH form of an INQUIRE statement. */
1196
1197tree
1198gfc_trans_inquire (gfc_code * code)
1199{
1200 stmtblock_t block, post_block;
1201 gfc_inquire *p;
5e805e44 1202 tree tmp, var;
6f0f0b2e 1203 unsigned int mask = 0, mask2 = 0;
6de9cd9a 1204
5e805e44 1205 gfc_start_block (&block);
6de9cd9a
DN
1206 gfc_init_block (&post_block);
1207
5e805e44
JJ
1208 var = gfc_create_var (st_parameter[IOPARM_ptype_inquire].type,
1209 "inquire_parm");
1210
1211 set_error_locus (&block, var, &code->loc);
6de9cd9a
DN
1212 p = code->ext.inquire;
1213
7aba8abe 1214 if (p->iomsg)
5e805e44
JJ
1215 mask |= set_string (&block, &post_block, var, IOPARM_common_iomsg,
1216 p->iomsg);
7aba8abe 1217
6de9cd9a 1218 if (p->iostat)
5e805e44
JJ
1219 mask |= set_parameter_ref (&block, &post_block, var, IOPARM_common_iostat,
1220 p->iostat);
6de9cd9a 1221
f96d606f
JD
1222 if (p->err)
1223 mask |= IOPARM_common_err;
1224
1225 /* Sanity check. */
1226 if (p->unit && p->file)
1227 gfc_error ("INQUIRE statement at %L cannot contain both FILE and UNIT specifiers", &code->loc);
1228
1229 if (p->file)
1230 mask |= set_string (&block, &post_block, var, IOPARM_inquire_file,
1231 p->file);
1232
6de9cd9a 1233 if (p->exist)
c16dd6a8
JD
1234 {
1235 mask |= set_parameter_ref (&block, &post_block, var, IOPARM_inquire_exist,
1236 p->exist);
1237
1238 if (p->unit && !p->iostat)
1239 {
1240 p->iostat = create_dummy_iostat ();
1241 mask |= set_parameter_ref (&block, &post_block, var,
1242 IOPARM_common_iostat, p->iostat);
1243 }
1244 }
6de9cd9a
DN
1245
1246 if (p->opened)
5e805e44
JJ
1247 mask |= set_parameter_ref (&block, &post_block, var, IOPARM_inquire_opened,
1248 p->opened);
6de9cd9a
DN
1249
1250 if (p->number)
5e805e44
JJ
1251 mask |= set_parameter_ref (&block, &post_block, var, IOPARM_inquire_number,
1252 p->number);
6de9cd9a
DN
1253
1254 if (p->named)
5e805e44
JJ
1255 mask |= set_parameter_ref (&block, &post_block, var, IOPARM_inquire_named,
1256 p->named);
6de9cd9a
DN
1257
1258 if (p->name)
5e805e44
JJ
1259 mask |= set_string (&block, &post_block, var, IOPARM_inquire_name,
1260 p->name);
6de9cd9a
DN
1261
1262 if (p->access)
5e805e44
JJ
1263 mask |= set_string (&block, &post_block, var, IOPARM_inquire_access,
1264 p->access);
6de9cd9a
DN
1265
1266 if (p->sequential)
5e805e44
JJ
1267 mask |= set_string (&block, &post_block, var, IOPARM_inquire_sequential,
1268 p->sequential);
6de9cd9a
DN
1269
1270 if (p->direct)
5e805e44
JJ
1271 mask |= set_string (&block, &post_block, var, IOPARM_inquire_direct,
1272 p->direct);
6de9cd9a
DN
1273
1274 if (p->form)
5e805e44
JJ
1275 mask |= set_string (&block, &post_block, var, IOPARM_inquire_form,
1276 p->form);
6de9cd9a
DN
1277
1278 if (p->formatted)
5e805e44
JJ
1279 mask |= set_string (&block, &post_block, var, IOPARM_inquire_formatted,
1280 p->formatted);
6de9cd9a
DN
1281
1282 if (p->unformatted)
5e805e44
JJ
1283 mask |= set_string (&block, &post_block, var, IOPARM_inquire_unformatted,
1284 p->unformatted);
6de9cd9a
DN
1285
1286 if (p->recl)
5e805e44
JJ
1287 mask |= set_parameter_ref (&block, &post_block, var,
1288 IOPARM_inquire_recl_out, p->recl);
6de9cd9a
DN
1289
1290 if (p->nextrec)
5e805e44
JJ
1291 mask |= set_parameter_ref (&block, &post_block, var,
1292 IOPARM_inquire_nextrec, p->nextrec);
6de9cd9a
DN
1293
1294 if (p->blank)
5e805e44
JJ
1295 mask |= set_string (&block, &post_block, var, IOPARM_inquire_blank,
1296 p->blank);
6de9cd9a 1297
d06b3496
JD
1298 if (p->delim)
1299 mask |= set_string (&block, &post_block, var, IOPARM_inquire_delim,
1300 p->delim);
1301
6de9cd9a 1302 if (p->position)
5e805e44
JJ
1303 mask |= set_string (&block, &post_block, var, IOPARM_inquire_position,
1304 p->position);
6de9cd9a
DN
1305
1306 if (p->action)
5e805e44
JJ
1307 mask |= set_string (&block, &post_block, var, IOPARM_inquire_action,
1308 p->action);
6de9cd9a
DN
1309
1310 if (p->read)
5e805e44
JJ
1311 mask |= set_string (&block, &post_block, var, IOPARM_inquire_read,
1312 p->read);
6de9cd9a
DN
1313
1314 if (p->write)
5e805e44
JJ
1315 mask |= set_string (&block, &post_block, var, IOPARM_inquire_write,
1316 p->write);
6de9cd9a
DN
1317
1318 if (p->readwrite)
5e805e44
JJ
1319 mask |= set_string (&block, &post_block, var, IOPARM_inquire_readwrite,
1320 p->readwrite);
6de9cd9a 1321
dae24534 1322 if (p->pad)
5e805e44
JJ
1323 mask |= set_string (&block, &post_block, var, IOPARM_inquire_pad,
1324 p->pad);
d06b3496 1325
181c9f4a
TK
1326 if (p->convert)
1327 mask |= set_string (&block, &post_block, var, IOPARM_inquire_convert,
1328 p->convert);
1329
014ec6ee
JD
1330 if (p->strm_pos)
1331 mask |= set_parameter_ref (&block, &post_block, var,
1332 IOPARM_inquire_strm_pos_out, p->strm_pos);
1333
6f0f0b2e
JD
1334 /* The second series of flags. */
1335 if (p->asynchronous)
1336 mask2 |= set_string (&block, &post_block, var, IOPARM_inquire_asynchronous,
1337 p->asynchronous);
1338
1339 if (p->decimal)
1340 mask2 |= set_string (&block, &post_block, var, IOPARM_inquire_decimal,
1341 p->decimal);
1342
1343 if (p->encoding)
1344 mask2 |= set_string (&block, &post_block, var, IOPARM_inquire_encoding,
1345 p->encoding);
1346
1347 if (p->round)
1348 mask2 |= set_string (&block, &post_block, var, IOPARM_inquire_round,
1349 p->round);
1350
1351 if (p->sign)
1352 mask2 |= set_string (&block, &post_block, var, IOPARM_inquire_sign,
1353 p->sign);
1354
1355 if (p->pending)
1356 mask2 |= set_parameter_ref (&block, &post_block, var,
1357 IOPARM_inquire_pending, p->pending);
1358
1359 if (p->size)
1360 mask2 |= set_parameter_ref (&block, &post_block, var, IOPARM_inquire_size,
1361 p->size);
1362
1363 if (p->id)
d06b3496
JD
1364 mask2 |= set_parameter_ref (&block, &post_block,var, IOPARM_inquire_id,
1365 p->id);
93e8af19
JD
1366 if (p->iqstream)
1367 mask2 |= set_string (&block, &post_block, var, IOPARM_inquire_iqstream,
1368 p->iqstream);
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
fc2655fb 1616 if (ts->type == BT_DERIVED && ts->u.derived->components)
29dc5138
PT
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
76c1a7ec
TB
1785 gfc_free_expr (nmlname);
1786
5e805e44
JJ
1787 if (last_dt == READ)
1788 mask |= IOPARM_dt_namelist_read_mode;
29dc5138 1789
5e805e44 1790 set_parameter_const (&block, var, IOPARM_common_flags, mask);
29dc5138 1791
5e805e44
JJ
1792 dt_parm = var;
1793
1794 for (nml = dt->namelist->namelist; nml; nml = nml->next)
1795 transfer_namelist_element (&block, nml->sym->name, nml->sym,
71ff73f3 1796 NULL, NULL_TREE);
5e805e44
JJ
1797 }
1798 else
1799 set_parameter_const (&block, var, IOPARM_common_flags, mask);
f96d606f
JD
1800
1801 if (dt->io_unit && dt->io_unit->ts.type == BT_INTEGER)
1802 set_parameter_value (&block, var, IOPARM_common_unit, dt->io_unit);
6de9cd9a 1803 }
5e805e44
JJ
1804 else
1805 set_parameter_const (&block, var, IOPARM_common_flags, mask);
6de9cd9a 1806
628c189e 1807 tmp = gfc_build_addr_expr (NULL_TREE, var);
033e7d21 1808 tmp = build_call_expr_loc (UNKNOWN_LOCATION,
db3927fb 1809 function, 1, tmp);
6de9cd9a
DN
1810 gfc_add_expr_to_block (&block, tmp);
1811
1812 gfc_add_block_to_block (&block, &post_block);
1813
5e805e44
JJ
1814 dt_parm = var;
1815 dt_post_end_block = &post_end_block;
1816
bc51e726
JD
1817 /* Set implied do loop exit condition. */
1818 if (last_dt == READ || last_dt == WRITE)
1819 {
1820 gfc_st_parameter_field *p = &st_parameter_field[IOPARM_common_flags];
1821
65a9ca82
TB
1822 tmp = fold_build3_loc (input_location, COMPONENT_REF,
1823 st_parameter[IOPARM_ptype_common].type,
1824 dt_parm, TYPE_FIELDS (TREE_TYPE (dt_parm)),
1825 NULL_TREE);
1826 tmp = fold_build3_loc (input_location, COMPONENT_REF,
1827 TREE_TYPE (p->field), tmp, p->field, NULL_TREE);
1828 tmp = fold_build2_loc (input_location, BIT_AND_EXPR, TREE_TYPE (tmp),
1829 tmp, build_int_cst (TREE_TYPE (tmp),
1830 IOPARM_common_libreturn_mask));
bc51e726
JD
1831 }
1832 else /* IOLENGTH */
1833 tmp = NULL_TREE;
1834
1835 gfc_add_expr_to_block (&block, gfc_trans_code_cond (code->block->next, tmp));
5e805e44 1836
d4feb3d3
PT
1837 gfc_add_block_to_block (&block, &post_iu_block);
1838
5e805e44
JJ
1839 dt_parm = NULL;
1840 dt_post_end_block = NULL;
1841
6de9cd9a
DN
1842 return gfc_finish_block (&block);
1843}
1844
1845
8750f9cd
JB
1846/* Translate the IOLENGTH form of an INQUIRE statement. We treat
1847 this as a third sort of data transfer statement, except that
e7dc5b4f 1848 lengths are summed instead of actually transferring any data. */
8750f9cd
JB
1849
1850tree
1851gfc_trans_iolength (gfc_code * code)
1852{
8750f9cd 1853 last_dt = IOLENGTH;
5e805e44 1854 return build_dt (iocall[IOCALL_IOLENGTH], code);
8750f9cd
JB
1855}
1856
1857
6de9cd9a
DN
1858/* Translate a READ statement. */
1859
1860tree
1861gfc_trans_read (gfc_code * code)
1862{
6de9cd9a 1863 last_dt = READ;
5e805e44 1864 return build_dt (iocall[IOCALL_READ], code);
6de9cd9a
DN
1865}
1866
1867
1868/* Translate a WRITE statement */
1869
1870tree
1871gfc_trans_write (gfc_code * code)
1872{
6de9cd9a 1873 last_dt = WRITE;
5e805e44 1874 return build_dt (iocall[IOCALL_WRITE], code);
6de9cd9a
DN
1875}
1876
1877
1878/* Finish a data transfer statement. */
1879
1880tree
1881gfc_trans_dt_end (gfc_code * code)
1882{
1883 tree function, tmp;
1884 stmtblock_t block;
1885
1886 gfc_init_block (&block);
1887
8750f9cd
JB
1888 switch (last_dt)
1889 {
1890 case READ:
5e805e44 1891 function = iocall[IOCALL_READ_DONE];
8750f9cd
JB
1892 break;
1893
1894 case WRITE:
5e805e44 1895 function = iocall[IOCALL_WRITE_DONE];
8750f9cd
JB
1896 break;
1897
1898 case IOLENGTH:
5e805e44 1899 function = iocall[IOCALL_IOLENGTH_DONE];
8750f9cd
JB
1900 break;
1901
1902 default:
6e45f57b 1903 gcc_unreachable ();
8750f9cd 1904 }
6de9cd9a 1905
628c189e 1906 tmp = gfc_build_addr_expr (NULL_TREE, dt_parm);
db3927fb
AH
1907 tmp = build_call_expr_loc (input_location,
1908 function, 1, tmp);
6de9cd9a 1909 gfc_add_expr_to_block (&block, tmp);
5e805e44
JJ
1910 gfc_add_block_to_block (&block, dt_post_end_block);
1911 gfc_init_block (dt_post_end_block);
6de9cd9a 1912
8750f9cd
JB
1913 if (last_dt != IOLENGTH)
1914 {
6e45f57b 1915 gcc_assert (code->ext.dt != NULL);
5e805e44 1916 io_result (&block, dt_parm, code->ext.dt->err,
8750f9cd
JB
1917 code->ext.dt->end, code->ext.dt->eor);
1918 }
6de9cd9a
DN
1919
1920 return gfc_finish_block (&block);
1921}
1922
d2ccf6aa 1923static void
aa5e22f0 1924transfer_expr (gfc_se * se, gfc_typespec * ts, tree addr_expr, gfc_code * code);
d2ccf6aa
VL
1925
1926/* Given an array field in a derived type variable, generate the code
1927 for the loop that iterates over array elements, and the code that
1928 accesses those array elements. Use transfer_expr to generate code
1929 for transferring that element. Because elements may also be
1930 derived types, transfer_expr and transfer_array_component are mutually
1931 recursive. */
1932
1933static tree
bdfd2ff0 1934transfer_array_component (tree expr, gfc_component * cm, locus * where)
d2ccf6aa
VL
1935{
1936 tree tmp;
1937 stmtblock_t body;
1938 stmtblock_t block;
1939 gfc_loopinfo loop;
1940 int n;
1941 gfc_ss *ss;
1942 gfc_se se;
08dcec61 1943 gfc_array_info *ss_array;
d2ccf6aa
VL
1944
1945 gfc_start_block (&block);
1946 gfc_init_se (&se, NULL);
1947
1948 /* Create and initialize Scalarization Status. Unlike in
1949 gfc_trans_transfer, we can't simply use gfc_walk_expr to take
1950 care of this task, because we don't have a gfc_expr at hand.
1951 Build one manually, as in gfc_trans_subarray_assign. */
1952
66877276
MM
1953 ss = gfc_get_array_ss (gfc_ss_terminator, NULL, cm->as->rank,
1954 GFC_SS_COMPONENT);
1838afec 1955 ss_array = &ss->info->data.array;
08dcec61
MM
1956 ss_array->shape = gfc_get_shape (cm->as->rank);
1957 ss_array->descriptor = expr;
1958 ss_array->data = gfc_conv_array_data (expr);
1959 ss_array->offset = gfc_conv_array_offset (expr);
d2ccf6aa
VL
1960 for (n = 0; n < cm->as->rank; n++)
1961 {
08dcec61
MM
1962 ss_array->start[n] = gfc_conv_array_lbound (expr, n);
1963 ss_array->stride[n] = gfc_index_one_node;
d2ccf6aa 1964
08dcec61
MM
1965 mpz_init (ss_array->shape[n]);
1966 mpz_sub (ss_array->shape[n], cm->as->upper[n]->value.integer,
d2ccf6aa 1967 cm->as->lower[n]->value.integer);
08dcec61 1968 mpz_add_ui (ss_array->shape[n], ss_array->shape[n], 1);
d2ccf6aa
VL
1969 }
1970
f7b529fa 1971 /* Once we got ss, we use scalarizer to create the loop. */
d2ccf6aa
VL
1972
1973 gfc_init_loopinfo (&loop);
1974 gfc_add_ss_to_loop (&loop, ss);
1975 gfc_conv_ss_startstride (&loop);
bdfd2ff0 1976 gfc_conv_loop_setup (&loop, where);
d2ccf6aa
VL
1977 gfc_mark_ss_chain_used (ss, 1);
1978 gfc_start_scalarized_body (&loop, &body);
1979
1980 gfc_copy_loopinfo_to_se (&se, &loop);
1981 se.ss = ss;
1982
1983 /* gfc_conv_tmp_array_ref assumes that se.expr contains the array. */
1984 se.expr = expr;
1985 gfc_conv_tmp_array_ref (&se);
1986
1987 /* Now se.expr contains an element of the array. Take the address and pass
1988 it to the IO routines. */
628c189e 1989 tmp = gfc_build_addr_expr (NULL_TREE, se.expr);
aa5e22f0 1990 transfer_expr (&se, &cm->ts, tmp, NULL);
d2ccf6aa
VL
1991
1992 /* We are done now with the loop body. Wrap up the scalarizer and
f7b529fa 1993 return. */
d2ccf6aa
VL
1994
1995 gfc_add_block_to_block (&body, &se.pre);
1996 gfc_add_block_to_block (&body, &se.post);
1997
1998 gfc_trans_scalarizing_loops (&loop, &body);
1999
2000 gfc_add_block_to_block (&block, &loop.pre);
2001 gfc_add_block_to_block (&block, &loop.post);
2002
08dcec61
MM
2003 gcc_assert (ss_array->shape != NULL);
2004 gfc_free_shape (&ss_array->shape, cm->as->rank);
96654664
PB
2005 gfc_cleanup_loop (&loop);
2006
d2ccf6aa
VL
2007 return gfc_finish_block (&block);
2008}
6de9cd9a
DN
2009
2010/* Generate the call for a scalar transfer node. */
2011
2012static void
aa5e22f0 2013transfer_expr (gfc_se * se, gfc_typespec * ts, tree addr_expr, gfc_code * code)
6de9cd9a 2014{
8a221914 2015 tree tmp, function, arg2, arg3, field, expr;
6de9cd9a
DN
2016 gfc_component *c;
2017 int kind;
2018
a8b3b0b6
CR
2019 /* It is possible to get a C_NULL_PTR or C_NULL_FUNPTR expression here if
2020 the user says something like: print *, 'c_null_ptr: ', c_null_ptr
2021 We need to translate the expression to a constant if it's either
aa5e22f0
CR
2022 C_NULL_PTR or C_NULL_FUNPTR. We could also get a user variable of
2023 type C_PTR or C_FUNPTR, in which case the ts->type may no longer be
2024 BT_DERIVED (could have been changed by gfc_conv_expr). */
bc21d315
JW
2025 if ((ts->type == BT_DERIVED || ts->type == BT_INTEGER)
2026 && ts->u.derived != NULL
2027 && (ts->is_iso_c == 1 || ts->u.derived->ts.is_iso_c == 1))
a8b3b0b6 2028 {
cadddfdd
TB
2029 ts->type = BT_INTEGER;
2030 ts->kind = gfc_index_integer_kind;
a8b3b0b6
CR
2031 }
2032
6de9cd9a
DN
2033 kind = ts->kind;
2034 function = NULL;
2035 arg2 = NULL;
8a221914 2036 arg3 = NULL;
6de9cd9a
DN
2037
2038 switch (ts->type)
2039 {
2040 case BT_INTEGER:
df09d1d5 2041 arg2 = build_int_cst (integer_type_node, kind);
6eb6875d
TK
2042 if (last_dt == READ)
2043 function = iocall[IOCALL_X_INTEGER];
2044 else
2045 function = iocall[IOCALL_X_INTEGER_WRITE];
2046
6de9cd9a
DN
2047 break;
2048
2049 case BT_REAL:
df09d1d5 2050 arg2 = build_int_cst (integer_type_node, kind);
6eb6875d 2051 if (last_dt == READ)
1ec601bf
FXC
2052 {
2053 if (gfc_real16_is_float128 && ts->kind == 16)
2054 function = iocall[IOCALL_X_REAL128];
2055 else
2056 function = iocall[IOCALL_X_REAL];
2057 }
6eb6875d 2058 else
1ec601bf
FXC
2059 {
2060 if (gfc_real16_is_float128 && ts->kind == 16)
2061 function = iocall[IOCALL_X_REAL128_WRITE];
2062 else
2063 function = iocall[IOCALL_X_REAL_WRITE];
2064 }
6eb6875d 2065
6de9cd9a
DN
2066 break;
2067
2068 case BT_COMPLEX:
df09d1d5 2069 arg2 = build_int_cst (integer_type_node, kind);
6eb6875d 2070 if (last_dt == READ)
1ec601bf
FXC
2071 {
2072 if (gfc_real16_is_float128 && ts->kind == 16)
2073 function = iocall[IOCALL_X_COMPLEX128];
2074 else
2075 function = iocall[IOCALL_X_COMPLEX];
2076 }
6eb6875d 2077 else
1ec601bf
FXC
2078 {
2079 if (gfc_real16_is_float128 && ts->kind == 16)
2080 function = iocall[IOCALL_X_COMPLEX128_WRITE];
2081 else
2082 function = iocall[IOCALL_X_COMPLEX_WRITE];
2083 }
6eb6875d 2084
6de9cd9a
DN
2085 break;
2086
2087 case BT_LOGICAL:
df09d1d5 2088 arg2 = build_int_cst (integer_type_node, kind);
6eb6875d
TK
2089 if (last_dt == READ)
2090 function = iocall[IOCALL_X_LOGICAL];
2091 else
2092 function = iocall[IOCALL_X_LOGICAL_WRITE];
2093
6de9cd9a
DN
2094 break;
2095
2096 case BT_CHARACTER:
8a221914
JD
2097 if (kind == 4)
2098 {
2099 if (se->string_length)
2100 arg2 = se->string_length;
2101 else
2102 {
db3927fb
AH
2103 tmp = build_fold_indirect_ref_loc (input_location,
2104 addr_expr);
8a221914
JD
2105 gcc_assert (TREE_CODE (TREE_TYPE (tmp)) == ARRAY_TYPE);
2106 arg2 = TYPE_MAX_VALUE (TYPE_DOMAIN (TREE_TYPE (tmp)));
2107 arg2 = fold_convert (gfc_charlen_type_node, arg2);
2108 }
df09d1d5 2109 arg3 = build_int_cst (integer_type_node, kind);
6eb6875d
TK
2110 if (last_dt == READ)
2111 function = iocall[IOCALL_X_CHARACTER_WIDE];
2112 else
2113 function = iocall[IOCALL_X_CHARACTER_WIDE_WRITE];
2114
628c189e 2115 tmp = gfc_build_addr_expr (NULL_TREE, dt_parm);
db3927fb
AH
2116 tmp = build_call_expr_loc (input_location,
2117 function, 4, tmp, addr_expr, arg2, arg3);
8a221914
JD
2118 gfc_add_expr_to_block (&se->pre, tmp);
2119 gfc_add_block_to_block (&se->pre, &se->post);
2120 return;
2121 }
2122 /* Fall through. */
7b95e2a8 2123 case BT_HOLLERITH:
d2ccf6aa
VL
2124 if (se->string_length)
2125 arg2 = se->string_length;
2126 else
2127 {
db3927fb
AH
2128 tmp = build_fold_indirect_ref_loc (input_location,
2129 addr_expr);
d2ccf6aa
VL
2130 gcc_assert (TREE_CODE (TREE_TYPE (tmp)) == ARRAY_TYPE);
2131 arg2 = TYPE_MAX_VALUE (TYPE_DOMAIN (TREE_TYPE (tmp)));
2132 }
6eb6875d
TK
2133 if (last_dt == READ)
2134 function = iocall[IOCALL_X_CHARACTER];
2135 else
2136 function = iocall[IOCALL_X_CHARACTER_WRITE];
2137
6de9cd9a
DN
2138 break;
2139
2140 case BT_DERIVED:
fc2655fb
TB
2141 if (ts->u.derived->components == NULL)
2142 return;
2143
d2ccf6aa 2144 /* Recurse into the elements of the derived type. */
6de9cd9a 2145 expr = gfc_evaluate_now (addr_expr, &se->pre);
db3927fb
AH
2146 expr = build_fold_indirect_ref_loc (input_location,
2147 expr);
6de9cd9a 2148
bc21d315 2149 for (c = ts->u.derived->components; c; c = c->next)
6de9cd9a
DN
2150 {
2151 field = c->backend_decl;
6e45f57b 2152 gcc_assert (field && TREE_CODE (field) == FIELD_DECL);
6de9cd9a 2153
db3927fb
AH
2154 tmp = fold_build3_loc (UNKNOWN_LOCATION,
2155 COMPONENT_REF, TREE_TYPE (field),
44855d8c 2156 expr, field, NULL_TREE);
6de9cd9a 2157
d4b7d0f0 2158 if (c->attr.dimension)
d2ccf6aa 2159 {
bdfd2ff0 2160 tmp = transfer_array_component (tmp, c, & code->loc);
d2ccf6aa
VL
2161 gfc_add_expr_to_block (&se->pre, tmp);
2162 }
2163 else
2164 {
d4b7d0f0 2165 if (!c->attr.pointer)
628c189e 2166 tmp = gfc_build_addr_expr (NULL_TREE, tmp);
aa5e22f0 2167 transfer_expr (se, &c->ts, tmp, code);
d2ccf6aa 2168 }
6de9cd9a
DN
2169 }
2170 return;
2171
2172 default:
2173 internal_error ("Bad IO basetype (%d)", ts->type);
2174 }
2175
628c189e 2176 tmp = gfc_build_addr_expr (NULL_TREE, dt_parm);
db3927fb
AH
2177 tmp = build_call_expr_loc (input_location,
2178 function, 3, tmp, addr_expr, arg2);
6de9cd9a
DN
2179 gfc_add_expr_to_block (&se->pre, tmp);
2180 gfc_add_block_to_block (&se->pre, &se->post);
8750f9cd 2181
6de9cd9a
DN
2182}
2183
2184
18623fae
JB
2185/* Generate a call to pass an array descriptor to the IO library. The
2186 array should be of one of the intrinsic types. */
2187
2188static void
2189transfer_array_desc (gfc_se * se, gfc_typespec * ts, tree addr_expr)
2190{
6eb6875d 2191 tree tmp, charlen_arg, kind_arg, io_call;
18623fae
JB
2192
2193 if (ts->type == BT_CHARACTER)
2194 charlen_arg = se->string_length;
2195 else
df09d1d5 2196 charlen_arg = build_int_cst (gfc_charlen_type_node, 0);
18623fae 2197
df09d1d5 2198 kind_arg = build_int_cst (integer_type_node, ts->kind);
e5ef4b3b 2199
628c189e 2200 tmp = gfc_build_addr_expr (NULL_TREE, dt_parm);
6eb6875d
TK
2201 if (last_dt == READ)
2202 io_call = iocall[IOCALL_X_ARRAY];
2203 else
2204 io_call = iocall[IOCALL_X_ARRAY_WRITE];
2205
033e7d21 2206 tmp = build_call_expr_loc (UNKNOWN_LOCATION,
6eb6875d 2207 io_call, 4,
5039610b 2208 tmp, addr_expr, kind_arg, charlen_arg);
18623fae
JB
2209 gfc_add_expr_to_block (&se->pre, tmp);
2210 gfc_add_block_to_block (&se->pre, &se->post);
2211}
2212
2213
6de9cd9a
DN
2214/* gfc_trans_transfer()-- Translate a TRANSFER code node */
2215
2216tree
2217gfc_trans_transfer (gfc_code * code)
2218{
2219 stmtblock_t block, body;
2220 gfc_loopinfo loop;
2221 gfc_expr *expr;
99c7ab42 2222 gfc_ref *ref;
6de9cd9a
DN
2223 gfc_ss *ss;
2224 gfc_se se;
2225 tree tmp;
c63173dd 2226 int n;
6de9cd9a
DN
2227
2228 gfc_start_block (&block);
18623fae 2229 gfc_init_block (&body);
6de9cd9a 2230
a513927a 2231 expr = code->expr1;
99c7ab42 2232 ref = NULL;
6de9cd9a
DN
2233 gfc_init_se (&se, NULL);
2234
2960a368 2235 if (expr->rank == 0)
18623fae 2236 {
815d8045 2237 /* Transfer a scalar value. */
18623fae 2238 gfc_conv_expr_reference (&se, expr);
aa5e22f0 2239 transfer_expr (&se, &expr->ts, se.expr, code);
18623fae 2240 }
815d8045 2241 else
6de9cd9a 2242 {
99c7ab42
PT
2243 /* Transfer an array. If it is an array of an intrinsic
2244 type, pass the descriptor to the library. Otherwise
2245 scalarize the transfer. */
2a573572 2246 if (expr->ref && !gfc_is_proc_ptr_comp (expr))
99c7ab42
PT
2247 {
2248 for (ref = expr->ref; ref && ref->type != REF_ARRAY;
fc2655fb
TB
2249 ref = ref->next);
2250 gcc_assert (ref && ref->type == REF_ARRAY);
99c7ab42
PT
2251 }
2252
1d6b7f39
PT
2253 if (expr->ts.type != BT_DERIVED
2254 && ref && ref->next == NULL
2255 && !is_subref_array (expr))
815d8045 2256 {
c63173dd
PT
2257 bool seen_vector = false;
2258
2259 if (ref && ref->u.ar.type == AR_SECTION)
2260 {
2261 for (n = 0; n < ref->u.ar.dimen; n++)
2262 if (ref->u.ar.dimen_type[n] == DIMEN_VECTOR)
2263 seen_vector = true;
2264 }
2265
2266 if (seen_vector && last_dt == READ)
2267 {
2268 /* Create a temp, read to that and copy it back. */
430f2d1f 2269 gfc_conv_subref_array_arg (&se, expr, 0, INTENT_OUT, false);
c63173dd
PT
2270 tmp = se.expr;
2271 }
2272 else
2273 {
2274 /* Get the descriptor. */
2960a368 2275 gfc_conv_expr_descriptor (&se, expr);
628c189e 2276 tmp = gfc_build_addr_expr (NULL_TREE, se.expr);
c63173dd
PT
2277 }
2278
99c7ab42
PT
2279 transfer_array_desc (&se, &expr->ts, tmp);
2280 goto finish_block_label;
815d8045 2281 }
2960a368 2282
6de9cd9a 2283 /* Initialize the scalarizer. */
2960a368 2284 ss = gfc_walk_expr (expr);
6de9cd9a
DN
2285 gfc_init_loopinfo (&loop);
2286 gfc_add_ss_to_loop (&loop, ss);
2287
2288 /* Initialize the loop. */
2289 gfc_conv_ss_startstride (&loop);
a513927a 2290 gfc_conv_loop_setup (&loop, &code->expr1->where);
6de9cd9a
DN
2291
2292 /* The main loop body. */
2293 gfc_mark_ss_chain_used (ss, 1);
2294 gfc_start_scalarized_body (&loop, &body);
2295
2296 gfc_copy_loopinfo_to_se (&se, &loop);
2297 se.ss = ss;
6de9cd9a 2298
18623fae 2299 gfc_conv_expr_reference (&se, expr);
aa5e22f0 2300 transfer_expr (&se, &expr->ts, se.expr, code);
18623fae 2301 }
815d8045
JB
2302
2303 finish_block_label:
6de9cd9a
DN
2304
2305 gfc_add_block_to_block (&body, &se.pre);
2306 gfc_add_block_to_block (&body, &se.post);
2307
2308 if (se.ss == NULL)
2309 tmp = gfc_finish_block (&body);
2310 else
2311 {
770caa74 2312 gcc_assert (expr->rank != 0);
6e45f57b 2313 gcc_assert (se.ss == gfc_ss_terminator);
6de9cd9a
DN
2314 gfc_trans_scalarizing_loops (&loop, &body);
2315
2316 gfc_add_block_to_block (&loop.pre, &loop.post);
2317 tmp = gfc_finish_block (&loop.pre);
2318 gfc_cleanup_loop (&loop);
2319 }
2320
2321 gfc_add_expr_to_block (&block, tmp);
2322
d2ccf6aa 2323 return gfc_finish_block (&block);
6de9cd9a
DN
2324}
2325
2326#include "gt-fortran-trans-io.h"