]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/fortran/trans-io.c
re PR target/54222 ([avr] Implement fixed-point support)
[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
2960a368 667 gfc_conv_array_parameter (se, 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 782 {
1d6b7f39 783 if (is_subref_array (e))
d4feb3d3
PT
784 {
785 /* Use a temporary for components of arrays of derived types
786 or substring array references. */
1d6b7f39 787 gfc_conv_subref_array_arg (&se, e, 0,
430f2d1f 788 last_dt == READ ? INTENT_IN : INTENT_OUT, false);
db3927fb
AH
789 tmp = build_fold_indirect_ref_loc (input_location,
790 se.expr);
d4feb3d3
PT
791 se.expr = gfc_build_addr_expr (pchar_type_node, tmp);
792 tmp = gfc_conv_descriptor_data_get (tmp);
793 }
794 else
795 {
796 /* Return the data pointer and rank from the descriptor. */
2960a368 797 gfc_conv_expr_descriptor (&se, e);
d4feb3d3
PT
798 tmp = gfc_conv_descriptor_data_get (se.expr);
799 se.expr = gfc_build_addr_expr (pchar_type_node, se.expr);
800 }
109b0ac2
PT
801 }
802 else
803 gcc_unreachable ();
804
805 /* The cast is needed for character substrings and the descriptor
806 data. */
726a989a
RB
807 gfc_add_modify (&se.pre, io, fold_convert (TREE_TYPE (io), tmp));
808 gfc_add_modify (&se.pre, len,
d4feb3d3 809 fold_convert (TREE_TYPE (len), se.string_length));
726a989a 810 gfc_add_modify (&se.pre, desc, se.expr);
109b0ac2
PT
811
812 gfc_add_block_to_block (block, &se.pre);
d4feb3d3 813 gfc_add_block_to_block (post_block, &se.post);
5e805e44 814 return mask;
109b0ac2
PT
815}
816
6de9cd9a
DN
817/* Add a case to a IO-result switch. */
818
819static void
820add_case (int label_value, gfc_st_label * label, stmtblock_t * body)
821{
822 tree tmp, value;
823
824 if (label == NULL)
825 return; /* No label, no case */
826
df09d1d5 827 value = build_int_cst (integer_type_node, label_value);
6de9cd9a
DN
828
829 /* Make a backend label for this case. */
c006df4e 830 tmp = gfc_build_label_decl (NULL_TREE);
6de9cd9a
DN
831
832 /* And the case itself. */
3d528853 833 tmp = build_case_label (value, NULL_TREE, tmp);
6de9cd9a
DN
834 gfc_add_expr_to_block (body, tmp);
835
836 /* Jump to the label. */
837 tmp = build1_v (GOTO_EXPR, gfc_get_label_decl (label));
838 gfc_add_expr_to_block (body, tmp);
839}
840
841
842/* Generate a switch statement that branches to the correct I/O
843 result label. The last statement of an I/O call stores the
844 result into a variable because there is often cleanup that
845 must be done before the switch, so a temporary would have to
846 be created anyway. */
847
848static void
5e805e44 849io_result (stmtblock_t * block, tree var, gfc_st_label * err_label,
6de9cd9a
DN
850 gfc_st_label * end_label, gfc_st_label * eor_label)
851{
852 stmtblock_t body;
853 tree tmp, rc;
5e805e44 854 gfc_st_parameter_field *p = &st_parameter_field[IOPARM_common_flags];
6de9cd9a
DN
855
856 /* If no labels are specified, ignore the result instead
857 of building an empty switch. */
858 if (err_label == NULL
859 && end_label == NULL
860 && eor_label == NULL)
861 return;
862
863 /* Build a switch statement. */
864 gfc_start_block (&body);
865
866 /* The label values here must be the same as the values
867 in the library_return enum in the runtime library */
868 add_case (1, err_label, &body);
869 add_case (2, end_label, &body);
870 add_case (3, eor_label, &body);
871
872 tmp = gfc_finish_block (&body);
873
65a9ca82
TB
874 var = fold_build3_loc (input_location, COMPONENT_REF,
875 st_parameter[IOPARM_ptype_common].type,
876 var, TYPE_FIELDS (TREE_TYPE (var)), NULL_TREE);
877 rc = fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (p->field),
878 var, p->field, NULL_TREE);
879 rc = fold_build2_loc (input_location, BIT_AND_EXPR, TREE_TYPE (rc),
880 rc, build_int_cst (TREE_TYPE (rc),
881 IOPARM_common_libreturn_mask));
6de9cd9a 882
0cd2402d
SB
883 tmp = fold_build3_loc (input_location, SWITCH_EXPR, NULL_TREE,
884 rc, tmp, NULL_TREE);
6de9cd9a
DN
885
886 gfc_add_expr_to_block (block, tmp);
887}
888
889
890/* Store the current file and line number to variables so that if a
891 library call goes awry, we can tell the user where the problem is. */
892
893static void
5e805e44 894set_error_locus (stmtblock_t * block, tree var, locus * where)
6de9cd9a
DN
895{
896 gfc_file *f;
5e805e44 897 tree str, locus_file;
6de9cd9a 898 int line;
5e805e44 899 gfc_st_parameter_field *p = &st_parameter_field[IOPARM_common_filename];
6de9cd9a 900
65a9ca82
TB
901 locus_file = fold_build3_loc (input_location, COMPONENT_REF,
902 st_parameter[IOPARM_ptype_common].type,
903 var, TYPE_FIELDS (TREE_TYPE (var)), NULL_TREE);
904 locus_file = fold_build3_loc (input_location, COMPONENT_REF,
905 TREE_TYPE (p->field), locus_file,
906 p->field, NULL_TREE);
d4fa05b9 907 f = where->lb->file;
5e805e44 908 str = gfc_build_cstring_const (f->filename);
6de9cd9a 909
5e805e44 910 str = gfc_build_addr_expr (pchar_type_node, str);
726a989a 911 gfc_add_modify (block, locus_file, str);
6de9cd9a 912
c8cc8542 913 line = LOCATION_LINE (where->lb->location);
5e805e44 914 set_parameter_const (block, var, IOPARM_common_line, line);
6de9cd9a
DN
915}
916
917
918/* Translate an OPEN statement. */
919
920tree
921gfc_trans_open (gfc_code * code)
922{
923 stmtblock_t block, post_block;
924 gfc_open *p;
5e805e44
JJ
925 tree tmp, var;
926 unsigned int mask = 0;
6de9cd9a 927
5e805e44 928 gfc_start_block (&block);
6de9cd9a
DN
929 gfc_init_block (&post_block);
930
5e805e44
JJ
931 var = gfc_create_var (st_parameter[IOPARM_ptype_open].type, "open_parm");
932
933 set_error_locus (&block, var, &code->loc);
6de9cd9a
DN
934 p = code->ext.open;
935
f96d606f
JD
936 if (p->iomsg)
937 mask |= set_string (&block, &post_block, var, IOPARM_common_iomsg,
938 p->iomsg);
939
940 if (p->iostat)
941 mask |= set_parameter_ref (&block, &post_block, var, IOPARM_common_iostat,
942 p->iostat);
943
944 if (p->err)
945 mask |= IOPARM_common_err;
6de9cd9a
DN
946
947 if (p->file)
5e805e44 948 mask |= set_string (&block, &post_block, var, IOPARM_open_file, p->file);
6de9cd9a
DN
949
950 if (p->status)
5e805e44
JJ
951 mask |= set_string (&block, &post_block, var, IOPARM_open_status,
952 p->status);
6de9cd9a
DN
953
954 if (p->access)
5e805e44
JJ
955 mask |= set_string (&block, &post_block, var, IOPARM_open_access,
956 p->access);
6de9cd9a
DN
957
958 if (p->form)
5e805e44 959 mask |= set_string (&block, &post_block, var, IOPARM_open_form, p->form);
6de9cd9a
DN
960
961 if (p->recl)
5e805e44 962 mask |= set_parameter_value (&block, var, IOPARM_open_recl_in, p->recl);
6de9cd9a
DN
963
964 if (p->blank)
5e805e44
JJ
965 mask |= set_string (&block, &post_block, var, IOPARM_open_blank,
966 p->blank);
6de9cd9a
DN
967
968 if (p->position)
5e805e44
JJ
969 mask |= set_string (&block, &post_block, var, IOPARM_open_position,
970 p->position);
6de9cd9a
DN
971
972 if (p->action)
5e805e44
JJ
973 mask |= set_string (&block, &post_block, var, IOPARM_open_action,
974 p->action);
6de9cd9a
DN
975
976 if (p->delim)
5e805e44
JJ
977 mask |= set_string (&block, &post_block, var, IOPARM_open_delim,
978 p->delim);
6de9cd9a
DN
979
980 if (p->pad)
5e805e44 981 mask |= set_string (&block, &post_block, var, IOPARM_open_pad, p->pad);
6de9cd9a 982
6f0f0b2e
JD
983 if (p->decimal)
984 mask |= set_string (&block, &post_block, var, IOPARM_open_decimal,
985 p->decimal);
986
987 if (p->encoding)
988 mask |= set_string (&block, &post_block, var, IOPARM_open_encoding,
989 p->encoding);
990
991 if (p->round)
992 mask |= set_string (&block, &post_block, var, IOPARM_open_round, p->round);
993
994 if (p->sign)
995 mask |= set_string (&block, &post_block, var, IOPARM_open_sign, p->sign);
996
997 if (p->asynchronous)
998 mask |= set_string (&block, &post_block, var, IOPARM_open_asynchronous,
999 p->asynchronous);
1000
181c9f4a
TK
1001 if (p->convert)
1002 mask |= set_string (&block, &post_block, var, IOPARM_open_convert,
1003 p->convert);
9ad55c33
JD
1004
1005 if (p->newunit)
1006 mask |= set_parameter_ref (&block, &post_block, var, IOPARM_open_newunit,
1007 p->newunit);
181c9f4a 1008
5e805e44
JJ
1009 set_parameter_const (&block, var, IOPARM_common_flags, mask);
1010
f96d606f
JD
1011 if (p->unit)
1012 set_parameter_value (&block, var, IOPARM_common_unit, p->unit);
1013 else
1014 set_parameter_const (&block, var, IOPARM_common_unit, 0);
1015
628c189e 1016 tmp = gfc_build_addr_expr (NULL_TREE, var);
db3927fb
AH
1017 tmp = build_call_expr_loc (input_location,
1018 iocall[IOCALL_OPEN], 1, tmp);
6de9cd9a
DN
1019 gfc_add_expr_to_block (&block, tmp);
1020
1021 gfc_add_block_to_block (&block, &post_block);
1022
5e805e44 1023 io_result (&block, var, p->err, NULL, NULL);
6de9cd9a
DN
1024
1025 return gfc_finish_block (&block);
1026}
1027
1028
1029/* Translate a CLOSE statement. */
1030
1031tree
1032gfc_trans_close (gfc_code * code)
1033{
1034 stmtblock_t block, post_block;
1035 gfc_close *p;
5e805e44
JJ
1036 tree tmp, var;
1037 unsigned int mask = 0;
6de9cd9a 1038
5e805e44 1039 gfc_start_block (&block);
6de9cd9a
DN
1040 gfc_init_block (&post_block);
1041
5e805e44
JJ
1042 var = gfc_create_var (st_parameter[IOPARM_ptype_close].type, "close_parm");
1043
1044 set_error_locus (&block, var, &code->loc);
6de9cd9a
DN
1045 p = code->ext.close;
1046
7aba8abe 1047 if (p->iomsg)
5e805e44
JJ
1048 mask |= set_string (&block, &post_block, var, IOPARM_common_iomsg,
1049 p->iomsg);
7aba8abe 1050
6de9cd9a 1051 if (p->iostat)
5e805e44
JJ
1052 mask |= set_parameter_ref (&block, &post_block, var, IOPARM_common_iostat,
1053 p->iostat);
6de9cd9a
DN
1054
1055 if (p->err)
5e805e44
JJ
1056 mask |= IOPARM_common_err;
1057
f96d606f
JD
1058 if (p->status)
1059 mask |= set_string (&block, &post_block, var, IOPARM_close_status,
1060 p->status);
1061
5e805e44 1062 set_parameter_const (&block, var, IOPARM_common_flags, mask);
6de9cd9a 1063
f96d606f
JD
1064 if (p->unit)
1065 set_parameter_value (&block, var, IOPARM_common_unit, p->unit);
1066 else
1067 set_parameter_const (&block, var, IOPARM_common_unit, 0);
1068
628c189e 1069 tmp = gfc_build_addr_expr (NULL_TREE, var);
db3927fb
AH
1070 tmp = build_call_expr_loc (input_location,
1071 iocall[IOCALL_CLOSE], 1, tmp);
6de9cd9a
DN
1072 gfc_add_expr_to_block (&block, tmp);
1073
1074 gfc_add_block_to_block (&block, &post_block);
1075
5e805e44 1076 io_result (&block, var, p->err, NULL, NULL);
6de9cd9a
DN
1077
1078 return gfc_finish_block (&block);
1079}
1080
1081
1082/* Common subroutine for building a file positioning statement. */
1083
1084static tree
1085build_filepos (tree function, gfc_code * code)
1086{
7aba8abe 1087 stmtblock_t block, post_block;
6de9cd9a 1088 gfc_filepos *p;
5e805e44
JJ
1089 tree tmp, var;
1090 unsigned int mask = 0;
6de9cd9a
DN
1091
1092 p = code->ext.filepos;
1093
5e805e44 1094 gfc_start_block (&block);
7aba8abe 1095 gfc_init_block (&post_block);
6de9cd9a 1096
5e805e44
JJ
1097 var = gfc_create_var (st_parameter[IOPARM_ptype_filepos].type,
1098 "filepos_parm");
1099
1100 set_error_locus (&block, var, &code->loc);
6de9cd9a 1101
7aba8abe 1102 if (p->iomsg)
5e805e44
JJ
1103 mask |= set_string (&block, &post_block, var, IOPARM_common_iomsg,
1104 p->iomsg);
7aba8abe 1105
6de9cd9a 1106 if (p->iostat)
5e805e44
JJ
1107 mask |= set_parameter_ref (&block, &post_block, var, IOPARM_common_iostat,
1108 p->iostat);
6de9cd9a
DN
1109
1110 if (p->err)
5e805e44
JJ
1111 mask |= IOPARM_common_err;
1112
1113 set_parameter_const (&block, var, IOPARM_common_flags, mask);
6de9cd9a 1114
f96d606f
JD
1115 if (p->unit)
1116 set_parameter_value (&block, var, IOPARM_common_unit, p->unit);
1117 else
1118 set_parameter_const (&block, var, IOPARM_common_unit, 0);
1119
628c189e 1120 tmp = gfc_build_addr_expr (NULL_TREE, var);
db3927fb
AH
1121 tmp = build_call_expr_loc (input_location,
1122 function, 1, tmp);
6de9cd9a
DN
1123 gfc_add_expr_to_block (&block, tmp);
1124
7aba8abe
TK
1125 gfc_add_block_to_block (&block, &post_block);
1126
5e805e44 1127 io_result (&block, var, p->err, NULL, NULL);
6de9cd9a
DN
1128
1129 return gfc_finish_block (&block);
1130}
1131
1132
1133/* Translate a BACKSPACE statement. */
1134
1135tree
1136gfc_trans_backspace (gfc_code * code)
1137{
5e805e44 1138 return build_filepos (iocall[IOCALL_BACKSPACE], code);
6de9cd9a
DN
1139}
1140
1141
1142/* Translate an ENDFILE statement. */
1143
1144tree
1145gfc_trans_endfile (gfc_code * code)
1146{
5e805e44 1147 return build_filepos (iocall[IOCALL_ENDFILE], code);
6de9cd9a
DN
1148}
1149
1150
1151/* Translate a REWIND statement. */
1152
1153tree
1154gfc_trans_rewind (gfc_code * code)
1155{
5e805e44 1156 return build_filepos (iocall[IOCALL_REWIND], code);
6de9cd9a
DN
1157}
1158
1159
6403ec5f
JB
1160/* Translate a FLUSH statement. */
1161
1162tree
1163gfc_trans_flush (gfc_code * code)
1164{
5e805e44 1165 return build_filepos (iocall[IOCALL_FLUSH], code);
6403ec5f
JB
1166}
1167
1168
c16dd6a8
JD
1169/* Create a dummy iostat variable to catch any error due to bad unit. */
1170
1171static gfc_expr *
1172create_dummy_iostat (void)
1173{
1174 gfc_symtree *st;
1175 gfc_expr *e;
1176
1177 gfc_get_ha_sym_tree ("@iostat", &st);
1178 st->n.sym->ts.type = BT_INTEGER;
1179 st->n.sym->ts.kind = gfc_default_integer_kind;
1180 gfc_set_sym_referenced (st->n.sym);
bc9d9552 1181 gfc_commit_symbol (st->n.sym);
c16dd6a8
JD
1182 st->n.sym->backend_decl
1183 = gfc_create_var (gfc_get_int_type (st->n.sym->ts.kind),
1184 st->n.sym->name);
1185
1186 e = gfc_get_expr ();
1187 e->expr_type = EXPR_VARIABLE;
1188 e->symtree = st;
1189 e->ts.type = BT_INTEGER;
1190 e->ts.kind = st->n.sym->ts.kind;
1191
1192 return e;
1193}
1194
1195
6de9cd9a
DN
1196/* Translate the non-IOLENGTH form of an INQUIRE statement. */
1197
1198tree
1199gfc_trans_inquire (gfc_code * code)
1200{
1201 stmtblock_t block, post_block;
1202 gfc_inquire *p;
5e805e44 1203 tree tmp, var;
6f0f0b2e 1204 unsigned int mask = 0, mask2 = 0;
6de9cd9a 1205
5e805e44 1206 gfc_start_block (&block);
6de9cd9a
DN
1207 gfc_init_block (&post_block);
1208
5e805e44
JJ
1209 var = gfc_create_var (st_parameter[IOPARM_ptype_inquire].type,
1210 "inquire_parm");
1211
1212 set_error_locus (&block, var, &code->loc);
6de9cd9a
DN
1213 p = code->ext.inquire;
1214
7aba8abe 1215 if (p->iomsg)
5e805e44
JJ
1216 mask |= set_string (&block, &post_block, var, IOPARM_common_iomsg,
1217 p->iomsg);
7aba8abe 1218
6de9cd9a 1219 if (p->iostat)
5e805e44
JJ
1220 mask |= set_parameter_ref (&block, &post_block, var, IOPARM_common_iostat,
1221 p->iostat);
6de9cd9a 1222
f96d606f
JD
1223 if (p->err)
1224 mask |= IOPARM_common_err;
1225
1226 /* Sanity check. */
1227 if (p->unit && p->file)
1228 gfc_error ("INQUIRE statement at %L cannot contain both FILE and UNIT specifiers", &code->loc);
1229
1230 if (p->file)
1231 mask |= set_string (&block, &post_block, var, IOPARM_inquire_file,
1232 p->file);
1233
6de9cd9a 1234 if (p->exist)
c16dd6a8
JD
1235 {
1236 mask |= set_parameter_ref (&block, &post_block, var, IOPARM_inquire_exist,
1237 p->exist);
1238
1239 if (p->unit && !p->iostat)
1240 {
1241 p->iostat = create_dummy_iostat ();
1242 mask |= set_parameter_ref (&block, &post_block, var,
1243 IOPARM_common_iostat, p->iostat);
1244 }
1245 }
6de9cd9a
DN
1246
1247 if (p->opened)
5e805e44
JJ
1248 mask |= set_parameter_ref (&block, &post_block, var, IOPARM_inquire_opened,
1249 p->opened);
6de9cd9a
DN
1250
1251 if (p->number)
5e805e44
JJ
1252 mask |= set_parameter_ref (&block, &post_block, var, IOPARM_inquire_number,
1253 p->number);
6de9cd9a
DN
1254
1255 if (p->named)
5e805e44
JJ
1256 mask |= set_parameter_ref (&block, &post_block, var, IOPARM_inquire_named,
1257 p->named);
6de9cd9a
DN
1258
1259 if (p->name)
5e805e44
JJ
1260 mask |= set_string (&block, &post_block, var, IOPARM_inquire_name,
1261 p->name);
6de9cd9a
DN
1262
1263 if (p->access)
5e805e44
JJ
1264 mask |= set_string (&block, &post_block, var, IOPARM_inquire_access,
1265 p->access);
6de9cd9a
DN
1266
1267 if (p->sequential)
5e805e44
JJ
1268 mask |= set_string (&block, &post_block, var, IOPARM_inquire_sequential,
1269 p->sequential);
6de9cd9a
DN
1270
1271 if (p->direct)
5e805e44
JJ
1272 mask |= set_string (&block, &post_block, var, IOPARM_inquire_direct,
1273 p->direct);
6de9cd9a
DN
1274
1275 if (p->form)
5e805e44
JJ
1276 mask |= set_string (&block, &post_block, var, IOPARM_inquire_form,
1277 p->form);
6de9cd9a
DN
1278
1279 if (p->formatted)
5e805e44
JJ
1280 mask |= set_string (&block, &post_block, var, IOPARM_inquire_formatted,
1281 p->formatted);
6de9cd9a
DN
1282
1283 if (p->unformatted)
5e805e44
JJ
1284 mask |= set_string (&block, &post_block, var, IOPARM_inquire_unformatted,
1285 p->unformatted);
6de9cd9a
DN
1286
1287 if (p->recl)
5e805e44
JJ
1288 mask |= set_parameter_ref (&block, &post_block, var,
1289 IOPARM_inquire_recl_out, p->recl);
6de9cd9a
DN
1290
1291 if (p->nextrec)
5e805e44
JJ
1292 mask |= set_parameter_ref (&block, &post_block, var,
1293 IOPARM_inquire_nextrec, p->nextrec);
6de9cd9a
DN
1294
1295 if (p->blank)
5e805e44
JJ
1296 mask |= set_string (&block, &post_block, var, IOPARM_inquire_blank,
1297 p->blank);
6de9cd9a 1298
d06b3496
JD
1299 if (p->delim)
1300 mask |= set_string (&block, &post_block, var, IOPARM_inquire_delim,
1301 p->delim);
1302
6de9cd9a 1303 if (p->position)
5e805e44
JJ
1304 mask |= set_string (&block, &post_block, var, IOPARM_inquire_position,
1305 p->position);
6de9cd9a
DN
1306
1307 if (p->action)
5e805e44
JJ
1308 mask |= set_string (&block, &post_block, var, IOPARM_inquire_action,
1309 p->action);
6de9cd9a
DN
1310
1311 if (p->read)
5e805e44
JJ
1312 mask |= set_string (&block, &post_block, var, IOPARM_inquire_read,
1313 p->read);
6de9cd9a
DN
1314
1315 if (p->write)
5e805e44
JJ
1316 mask |= set_string (&block, &post_block, var, IOPARM_inquire_write,
1317 p->write);
6de9cd9a
DN
1318
1319 if (p->readwrite)
5e805e44
JJ
1320 mask |= set_string (&block, &post_block, var, IOPARM_inquire_readwrite,
1321 p->readwrite);
6de9cd9a 1322
dae24534 1323 if (p->pad)
5e805e44
JJ
1324 mask |= set_string (&block, &post_block, var, IOPARM_inquire_pad,
1325 p->pad);
d06b3496 1326
181c9f4a
TK
1327 if (p->convert)
1328 mask |= set_string (&block, &post_block, var, IOPARM_inquire_convert,
1329 p->convert);
1330
014ec6ee
JD
1331 if (p->strm_pos)
1332 mask |= set_parameter_ref (&block, &post_block, var,
1333 IOPARM_inquire_strm_pos_out, p->strm_pos);
1334
6f0f0b2e
JD
1335 /* The second series of flags. */
1336 if (p->asynchronous)
1337 mask2 |= set_string (&block, &post_block, var, IOPARM_inquire_asynchronous,
1338 p->asynchronous);
1339
1340 if (p->decimal)
1341 mask2 |= set_string (&block, &post_block, var, IOPARM_inquire_decimal,
1342 p->decimal);
1343
1344 if (p->encoding)
1345 mask2 |= set_string (&block, &post_block, var, IOPARM_inquire_encoding,
1346 p->encoding);
1347
1348 if (p->round)
1349 mask2 |= set_string (&block, &post_block, var, IOPARM_inquire_round,
1350 p->round);
1351
1352 if (p->sign)
1353 mask2 |= set_string (&block, &post_block, var, IOPARM_inquire_sign,
1354 p->sign);
1355
1356 if (p->pending)
1357 mask2 |= set_parameter_ref (&block, &post_block, var,
1358 IOPARM_inquire_pending, p->pending);
1359
1360 if (p->size)
1361 mask2 |= set_parameter_ref (&block, &post_block, var, IOPARM_inquire_size,
1362 p->size);
1363
1364 if (p->id)
d06b3496
JD
1365 mask2 |= set_parameter_ref (&block, &post_block,var, IOPARM_inquire_id,
1366 p->id);
6f0f0b2e 1367
6f0f0b2e 1368 if (mask2)
e1456843 1369 mask |= set_parameter_const (&block, var, IOPARM_inquire_flags2, mask2);
6f0f0b2e 1370
5e805e44 1371 set_parameter_const (&block, var, IOPARM_common_flags, mask);
6de9cd9a 1372
f96d606f
JD
1373 if (p->unit)
1374 set_parameter_value (&block, var, IOPARM_common_unit, p->unit);
1375 else
1376 set_parameter_const (&block, var, IOPARM_common_unit, 0);
1377
628c189e 1378 tmp = gfc_build_addr_expr (NULL_TREE, var);
db3927fb
AH
1379 tmp = build_call_expr_loc (input_location,
1380 iocall[IOCALL_INQUIRE], 1, tmp);
6de9cd9a
DN
1381 gfc_add_expr_to_block (&block, tmp);
1382
1383 gfc_add_block_to_block (&block, &post_block);
1384
5e805e44 1385 io_result (&block, var, p->err, NULL, NULL);
6de9cd9a
DN
1386
1387 return gfc_finish_block (&block);
1388}
1389
6f0f0b2e
JD
1390
1391tree
1392gfc_trans_wait (gfc_code * code)
1393{
1394 stmtblock_t block, post_block;
1395 gfc_wait *p;
1396 tree tmp, var;
1397 unsigned int mask = 0;
1398
1399 gfc_start_block (&block);
1400 gfc_init_block (&post_block);
1401
1402 var = gfc_create_var (st_parameter[IOPARM_ptype_wait].type,
1403 "wait_parm");
1404
1405 set_error_locus (&block, var, &code->loc);
1406 p = code->ext.wait;
1407
1408 /* Set parameters here. */
1409 if (p->iomsg)
1410 mask |= set_string (&block, &post_block, var, IOPARM_common_iomsg,
1411 p->iomsg);
1412
1413 if (p->iostat)
1414 mask |= set_parameter_ref (&block, &post_block, var, IOPARM_common_iostat,
1415 p->iostat);
1416
1417 if (p->err)
1418 mask |= IOPARM_common_err;
1419
1420 if (p->id)
1421 mask |= set_parameter_value (&block, var, IOPARM_wait_id, p->id);
1422
1423 set_parameter_const (&block, var, IOPARM_common_flags, mask);
1424
1425 if (p->unit)
1426 set_parameter_value (&block, var, IOPARM_common_unit, p->unit);
1427
628c189e 1428 tmp = gfc_build_addr_expr (NULL_TREE, var);
db3927fb
AH
1429 tmp = build_call_expr_loc (input_location,
1430 iocall[IOCALL_WAIT], 1, tmp);
6f0f0b2e
JD
1431 gfc_add_expr_to_block (&block, tmp);
1432
1433 gfc_add_block_to_block (&block, &post_block);
1434
1435 io_result (&block, var, p->err, NULL, NULL);
1436
1437 return gfc_finish_block (&block);
1438
1439}
1440
6de9cd9a 1441
29dc5138 1442/* nml_full_name builds up the fully qualified name of a
66e4ab31 1443 derived type component. */
29dc5138
PT
1444
1445static char*
1446nml_full_name (const char* var_name, const char* cmp_name)
6de9cd9a 1447{
29dc5138
PT
1448 int full_name_length;
1449 char * full_name;
1450
1451 full_name_length = strlen (var_name) + strlen (cmp_name) + 1;
93acb62c 1452 full_name = XCNEWVEC (char, full_name_length + 1);
29dc5138
PT
1453 strcpy (full_name, var_name);
1454 full_name = strcat (full_name, "%");
1455 full_name = strcat (full_name, cmp_name);
1456 return full_name;
6de9cd9a
DN
1457}
1458
19d36107 1459
29dc5138
PT
1460/* nml_get_addr_expr builds an address expression from the
1461 gfc_symbol or gfc_component backend_decl's. An offset is
1462 provided so that the address of an element of an array of
1463 derived types is returned. This is used in the runtime to
66e4ab31 1464 determine that span of the derived type. */
29dc5138
PT
1465
1466static tree
1467nml_get_addr_expr (gfc_symbol * sym, gfc_component * c,
1468 tree base_addr)
1469{
1470 tree decl = NULL_TREE;
1471 tree tmp;
29dc5138
PT
1472
1473 if (sym)
1474 {
1475 sym->attr.referenced = 1;
1476 decl = gfc_get_symbol_decl (sym);
847b053d
PT
1477
1478 /* If this is the enclosing function declaration, use
1479 the fake result instead. */
1480 if (decl == current_function_decl)
1481 decl = gfc_get_fake_result_decl (sym, 0);
1482 else if (decl == DECL_CONTEXT (current_function_decl))
1483 decl = gfc_get_fake_result_decl (sym, 1);
29dc5138
PT
1484 }
1485 else
1486 decl = c->backend_decl;
1487
1488 gcc_assert (decl && ((TREE_CODE (decl) == FIELD_DECL
1489 || TREE_CODE (decl) == VAR_DECL
1490 || TREE_CODE (decl) == PARM_DECL)
1491 || TREE_CODE (decl) == COMPONENT_REF));
1492
1493 tmp = decl;
1494
1495 /* Build indirect reference, if dummy argument. */
1496
19d36107
TB
1497 if (POINTER_TYPE_P (TREE_TYPE(tmp)))
1498 tmp = build_fold_indirect_ref_loc (input_location, tmp);
29dc5138
PT
1499
1500 /* Treat the component of a derived type, using base_addr for
1501 the derived type. */
1502
1503 if (TREE_CODE (decl) == FIELD_DECL)
65a9ca82
TB
1504 tmp = fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (tmp),
1505 base_addr, tmp, NULL_TREE);
29dc5138 1506
19d36107
TB
1507 if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (tmp)))
1508 tmp = gfc_conv_array_data (tmp);
1509 else
1510 {
1511 if (!POINTER_TYPE_P (TREE_TYPE (tmp)))
1512 tmp = gfc_build_addr_expr (NULL_TREE, tmp);
29dc5138 1513
19d36107
TB
1514 if (TREE_CODE (TREE_TYPE (tmp)) == ARRAY_TYPE)
1515 tmp = gfc_build_array_ref (tmp, gfc_index_zero_node, NULL);
29dc5138 1516
19d36107
TB
1517 if (!POINTER_TYPE_P (TREE_TYPE (tmp)))
1518 tmp = build_fold_indirect_ref_loc (input_location,
db3927fb 1519 tmp);
19d36107 1520 }
29dc5138
PT
1521
1522 gcc_assert (tmp && POINTER_TYPE_P (TREE_TYPE (tmp)));
1523
1524 return tmp;
1525}
3bc268e6 1526
19d36107 1527
29dc5138 1528/* For an object VAR_NAME whose base address is BASE_ADDR, generate a
5e805e44
JJ
1529 call to iocall[IOCALL_SET_NML_VAL]. For derived type variable, recursively
1530 generate calls to iocall[IOCALL_SET_NML_VAL] for each component. */
3bc268e6 1531
29dc5138 1532#define IARG(i) build_int_cst (gfc_array_index_type, i)
3bc268e6
VL
1533
1534static void
29dc5138
PT
1535transfer_namelist_element (stmtblock_t * block, const char * var_name,
1536 gfc_symbol * sym, gfc_component * c,
1537 tree base_addr)
3bc268e6 1538{
29dc5138
PT
1539 gfc_typespec * ts = NULL;
1540 gfc_array_spec * as = NULL;
1541 tree addr_expr = NULL;
1542 tree dt = NULL;
1543 tree string;
1544 tree tmp;
29dc5138 1545 tree dtype;
5e805e44 1546 tree dt_parm_addr;
19d36107 1547 tree decl = NULL_TREE;
29dc5138
PT
1548 int n_dim;
1549 int itype;
1550 int rank = 0;
3bc268e6 1551
29dc5138 1552 gcc_assert (sym || c);
3bc268e6 1553
29dc5138
PT
1554 /* Build the namelist object name. */
1555
1556 string = gfc_build_cstring_const (var_name);
1557 string = gfc_build_addr_expr (pchar_type_node, string);
1558
1559 /* Build ts, as and data address using symbol or component. */
1560
1561 ts = (sym) ? &sym->ts : &c->ts;
1562 as = (sym) ? sym->as : c->as;
1563
1564 addr_expr = nml_get_addr_expr (sym, c, base_addr);
1565
1566 if (as)
1567 rank = as->rank;
1568
1569 if (rank)
3bc268e6 1570 {
19d36107
TB
1571 decl = (sym) ? sym->backend_decl : c->backend_decl;
1572 if (sym && sym->attr.dummy)
1573 decl = build_fold_indirect_ref_loc (input_location, decl);
1574 dt = TREE_TYPE (decl);
29dc5138 1575 dtype = gfc_get_dtype (dt);
3bc268e6 1576 }
29dc5138
PT
1577 else
1578 {
a11930ba 1579 itype = ts->type;
29dc5138 1580 dtype = IARG (itype << GFC_DTYPE_TYPE_SHIFT);
3bc268e6
VL
1581 }
1582
29dc5138
PT
1583 /* Build up the arguments for the transfer call.
1584 The call for the scalar part transfers:
1585 (address, name, type, kind or string_length, dtype) */
1586
628c189e 1587 dt_parm_addr = gfc_build_addr_expr (NULL_TREE, dt_parm);
29dc5138
PT
1588
1589 if (ts->type == BT_CHARACTER)
bc21d315 1590 tmp = ts->u.cl->backend_decl;
29dc5138 1591 else
5039610b 1592 tmp = build_int_cst (gfc_charlen_type_node, 0);
db3927fb
AH
1593 tmp = build_call_expr_loc (input_location,
1594 iocall[IOCALL_SET_NML_VAL], 6,
5039610b
SL
1595 dt_parm_addr, addr_expr, string,
1596 IARG (ts->kind), tmp, dtype);
3bc268e6 1597 gfc_add_expr_to_block (block, tmp);
29dc5138
PT
1598
1599 /* If the object is an array, transfer rank times:
1600 (null pointer, name, stride, lbound, ubound) */
1601
1602 for ( n_dim = 0 ; n_dim < rank ; n_dim++ )
1603 {
db3927fb
AH
1604 tmp = build_call_expr_loc (input_location,
1605 iocall[IOCALL_SET_NML_VAL_DIM], 5,
5039610b
SL
1606 dt_parm_addr,
1607 IARG (n_dim),
19d36107
TB
1608 gfc_conv_array_stride (decl, n_dim),
1609 gfc_conv_array_lbound (decl, n_dim),
1610 gfc_conv_array_ubound (decl, n_dim));
29dc5138
PT
1611 gfc_add_expr_to_block (block, tmp);
1612 }
1613
fc2655fb 1614 if (ts->type == BT_DERIVED && ts->u.derived->components)
29dc5138
PT
1615 {
1616 gfc_component *cmp;
1617
1618 /* Provide the RECORD_TYPE to build component references. */
1619
db3927fb
AH
1620 tree expr = build_fold_indirect_ref_loc (input_location,
1621 addr_expr);
29dc5138 1622
bc21d315 1623 for (cmp = ts->u.derived->components; cmp; cmp = cmp->next)
29dc5138
PT
1624 {
1625 char *full_name = nml_full_name (var_name, cmp->name);
1626 transfer_namelist_element (block,
1627 full_name,
1628 NULL, cmp, expr);
cede9502 1629 free (full_name);
29dc5138
PT
1630 }
1631 }
3bc268e6 1632}
6de9cd9a 1633
29dc5138 1634#undef IARG
29dc5138 1635
6de9cd9a
DN
1636/* Create a data transfer statement. Not all of the fields are valid
1637 for both reading and writing, but improper use has been filtered
1638 out by now. */
1639
1640static tree
5e805e44 1641build_dt (tree function, gfc_code * code)
6de9cd9a 1642{
d4feb3d3 1643 stmtblock_t block, post_block, post_end_block, post_iu_block;
6de9cd9a 1644 gfc_dt *dt;
5e805e44 1645 tree tmp, var;
29dc5138 1646 gfc_expr *nmlname;
3bc268e6 1647 gfc_namelist *nml;
5e1bdeb7 1648 unsigned int mask = 0;
6de9cd9a 1649
5e805e44 1650 gfc_start_block (&block);
6de9cd9a 1651 gfc_init_block (&post_block);
5e805e44 1652 gfc_init_block (&post_end_block);
d4feb3d3 1653 gfc_init_block (&post_iu_block);
5e805e44
JJ
1654
1655 var = gfc_create_var (st_parameter[IOPARM_ptype_dt].type, "dt_parm");
1656
1657 set_error_locus (&block, var, &code->loc);
6de9cd9a 1658
5e805e44
JJ
1659 if (last_dt == IOLENGTH)
1660 {
1661 gfc_inquire *inq;
1662
1663 inq = code->ext.inquire;
6de9cd9a 1664
5e805e44
JJ
1665 /* First check that preconditions are met. */
1666 gcc_assert (inq != NULL);
1667 gcc_assert (inq->iolength != NULL);
1668
1669 /* Connect to the iolength variable. */
1670 mask |= set_parameter_ref (&block, &post_end_block, var,
1671 IOPARM_dt_iolength, inq->iolength);
1672 dt = NULL;
1673 }
1674 else
1675 {
1676 dt = code->ext.dt;
1677 gcc_assert (dt != NULL);
1678 }
8750f9cd 1679
5e805e44 1680 if (dt && dt->io_unit)
6de9cd9a
DN
1681 {
1682 if (dt->io_unit->ts.type == BT_CHARACTER)
1683 {
d4feb3d3
PT
1684 mask |= set_internal_unit (&block, &post_iu_block,
1685 var, dt->io_unit);
c8dce2cf
JD
1686 set_parameter_const (&block, var, IOPARM_common_unit,
1687 dt->io_unit->ts.kind == 1 ? 0 : -1);
6de9cd9a 1688 }
6de9cd9a 1689 }
5e805e44
JJ
1690 else
1691 set_parameter_const (&block, var, IOPARM_common_unit, 0);
6de9cd9a 1692
5e805e44
JJ
1693 if (dt)
1694 {
f96d606f
JD
1695 if (dt->iomsg)
1696 mask |= set_string (&block, &post_block, var, IOPARM_common_iomsg,
1697 dt->iomsg);
1698
1699 if (dt->iostat)
1700 mask |= set_parameter_ref (&block, &post_end_block, var,
1701 IOPARM_common_iostat, dt->iostat);
1702
1703 if (dt->err)
1704 mask |= IOPARM_common_err;
1705
1706 if (dt->eor)
1707 mask |= IOPARM_common_eor;
1708
1709 if (dt->end)
1710 mask |= IOPARM_common_end;
1711
6f0f0b2e
JD
1712 if (dt->id)
1713 mask |= set_parameter_ref (&block, &post_end_block, var,
1714 IOPARM_dt_id, dt->id);
1715
1716 if (dt->pos)
1717 mask |= set_parameter_value (&block, var, IOPARM_dt_pos, dt->pos);
1718
1719 if (dt->asynchronous)
1720 mask |= set_string (&block, &post_block, var, IOPARM_dt_asynchronous,
1721 dt->asynchronous);
1722
1723 if (dt->blank)
1724 mask |= set_string (&block, &post_block, var, IOPARM_dt_blank,
1725 dt->blank);
1726
1727 if (dt->decimal)
1728 mask |= set_string (&block, &post_block, var, IOPARM_dt_decimal,
1729 dt->decimal);
1730
1731 if (dt->delim)
1732 mask |= set_string (&block, &post_block, var, IOPARM_dt_delim,
1733 dt->delim);
1734
1735 if (dt->pad)
1736 mask |= set_string (&block, &post_block, var, IOPARM_dt_pad,
1737 dt->pad);
1738
1739 if (dt->round)
1740 mask |= set_string (&block, &post_block, var, IOPARM_dt_round,
1741 dt->round);
1742
1743 if (dt->sign)
1744 mask |= set_string (&block, &post_block, var, IOPARM_dt_sign,
1745 dt->sign);
1746
5e805e44
JJ
1747 if (dt->rec)
1748 mask |= set_parameter_value (&block, var, IOPARM_dt_rec, dt->rec);
6de9cd9a 1749
5e805e44
JJ
1750 if (dt->advance)
1751 mask |= set_string (&block, &post_block, var, IOPARM_dt_advance,
1752 dt->advance);
6de9cd9a 1753
5e805e44 1754 if (dt->format_expr)
9341698a 1755 mask |= set_string (&block, &post_end_block, var, IOPARM_dt_format,
5e805e44 1756 dt->format_expr);
6de9cd9a 1757
5e805e44
JJ
1758 if (dt->format_label)
1759 {
1760 if (dt->format_label == &format_asterisk)
1761 mask |= IOPARM_dt_list_format;
1762 else
1763 mask |= set_string (&block, &post_block, var, IOPARM_dt_format,
1764 dt->format_label->format);
1765 }
6de9cd9a 1766
5e805e44
JJ
1767 if (dt->size)
1768 mask |= set_parameter_ref (&block, &post_end_block, var,
1769 IOPARM_dt_size, dt->size);
6de9cd9a 1770
5e805e44
JJ
1771 if (dt->namelist)
1772 {
1773 if (dt->format_expr || dt->format_label)
1774 gfc_internal_error ("build_dt: format with namelist");
1775
b7e75771
JD
1776 nmlname = gfc_get_character_expr (gfc_default_character_kind, NULL,
1777 dt->namelist->name,
1778 strlen (dt->namelist->name));
29dc5138 1779
5e805e44
JJ
1780 mask |= set_string (&block, &post_block, var, IOPARM_dt_namelist_name,
1781 nmlname);
29dc5138 1782
5e805e44
JJ
1783 if (last_dt == READ)
1784 mask |= IOPARM_dt_namelist_read_mode;
29dc5138 1785
5e805e44 1786 set_parameter_const (&block, var, IOPARM_common_flags, mask);
29dc5138 1787
5e805e44
JJ
1788 dt_parm = var;
1789
1790 for (nml = dt->namelist->namelist; nml; nml = nml->next)
1791 transfer_namelist_element (&block, nml->sym->name, nml->sym,
71ff73f3 1792 NULL, NULL_TREE);
5e805e44
JJ
1793 }
1794 else
1795 set_parameter_const (&block, var, IOPARM_common_flags, mask);
f96d606f
JD
1796
1797 if (dt->io_unit && dt->io_unit->ts.type == BT_INTEGER)
1798 set_parameter_value (&block, var, IOPARM_common_unit, dt->io_unit);
6de9cd9a 1799 }
5e805e44
JJ
1800 else
1801 set_parameter_const (&block, var, IOPARM_common_flags, mask);
6de9cd9a 1802
628c189e 1803 tmp = gfc_build_addr_expr (NULL_TREE, var);
033e7d21 1804 tmp = build_call_expr_loc (UNKNOWN_LOCATION,
db3927fb 1805 function, 1, tmp);
6de9cd9a
DN
1806 gfc_add_expr_to_block (&block, tmp);
1807
1808 gfc_add_block_to_block (&block, &post_block);
1809
5e805e44
JJ
1810 dt_parm = var;
1811 dt_post_end_block = &post_end_block;
1812
bc51e726
JD
1813 /* Set implied do loop exit condition. */
1814 if (last_dt == READ || last_dt == WRITE)
1815 {
1816 gfc_st_parameter_field *p = &st_parameter_field[IOPARM_common_flags];
1817
65a9ca82
TB
1818 tmp = fold_build3_loc (input_location, COMPONENT_REF,
1819 st_parameter[IOPARM_ptype_common].type,
1820 dt_parm, TYPE_FIELDS (TREE_TYPE (dt_parm)),
1821 NULL_TREE);
1822 tmp = fold_build3_loc (input_location, COMPONENT_REF,
1823 TREE_TYPE (p->field), tmp, p->field, NULL_TREE);
1824 tmp = fold_build2_loc (input_location, BIT_AND_EXPR, TREE_TYPE (tmp),
1825 tmp, build_int_cst (TREE_TYPE (tmp),
1826 IOPARM_common_libreturn_mask));
bc51e726
JD
1827 }
1828 else /* IOLENGTH */
1829 tmp = NULL_TREE;
1830
1831 gfc_add_expr_to_block (&block, gfc_trans_code_cond (code->block->next, tmp));
5e805e44 1832
d4feb3d3
PT
1833 gfc_add_block_to_block (&block, &post_iu_block);
1834
5e805e44
JJ
1835 dt_parm = NULL;
1836 dt_post_end_block = NULL;
1837
6de9cd9a
DN
1838 return gfc_finish_block (&block);
1839}
1840
1841
8750f9cd
JB
1842/* Translate the IOLENGTH form of an INQUIRE statement. We treat
1843 this as a third sort of data transfer statement, except that
e7dc5b4f 1844 lengths are summed instead of actually transferring any data. */
8750f9cd
JB
1845
1846tree
1847gfc_trans_iolength (gfc_code * code)
1848{
8750f9cd 1849 last_dt = IOLENGTH;
5e805e44 1850 return build_dt (iocall[IOCALL_IOLENGTH], code);
8750f9cd
JB
1851}
1852
1853
6de9cd9a
DN
1854/* Translate a READ statement. */
1855
1856tree
1857gfc_trans_read (gfc_code * code)
1858{
6de9cd9a 1859 last_dt = READ;
5e805e44 1860 return build_dt (iocall[IOCALL_READ], code);
6de9cd9a
DN
1861}
1862
1863
1864/* Translate a WRITE statement */
1865
1866tree
1867gfc_trans_write (gfc_code * code)
1868{
6de9cd9a 1869 last_dt = WRITE;
5e805e44 1870 return build_dt (iocall[IOCALL_WRITE], code);
6de9cd9a
DN
1871}
1872
1873
1874/* Finish a data transfer statement. */
1875
1876tree
1877gfc_trans_dt_end (gfc_code * code)
1878{
1879 tree function, tmp;
1880 stmtblock_t block;
1881
1882 gfc_init_block (&block);
1883
8750f9cd
JB
1884 switch (last_dt)
1885 {
1886 case READ:
5e805e44 1887 function = iocall[IOCALL_READ_DONE];
8750f9cd
JB
1888 break;
1889
1890 case WRITE:
5e805e44 1891 function = iocall[IOCALL_WRITE_DONE];
8750f9cd
JB
1892 break;
1893
1894 case IOLENGTH:
5e805e44 1895 function = iocall[IOCALL_IOLENGTH_DONE];
8750f9cd
JB
1896 break;
1897
1898 default:
6e45f57b 1899 gcc_unreachable ();
8750f9cd 1900 }
6de9cd9a 1901
628c189e 1902 tmp = gfc_build_addr_expr (NULL_TREE, dt_parm);
db3927fb
AH
1903 tmp = build_call_expr_loc (input_location,
1904 function, 1, tmp);
6de9cd9a 1905 gfc_add_expr_to_block (&block, tmp);
5e805e44
JJ
1906 gfc_add_block_to_block (&block, dt_post_end_block);
1907 gfc_init_block (dt_post_end_block);
6de9cd9a 1908
8750f9cd
JB
1909 if (last_dt != IOLENGTH)
1910 {
6e45f57b 1911 gcc_assert (code->ext.dt != NULL);
5e805e44 1912 io_result (&block, dt_parm, code->ext.dt->err,
8750f9cd
JB
1913 code->ext.dt->end, code->ext.dt->eor);
1914 }
6de9cd9a
DN
1915
1916 return gfc_finish_block (&block);
1917}
1918
d2ccf6aa 1919static void
aa5e22f0 1920transfer_expr (gfc_se * se, gfc_typespec * ts, tree addr_expr, gfc_code * code);
d2ccf6aa
VL
1921
1922/* Given an array field in a derived type variable, generate the code
1923 for the loop that iterates over array elements, and the code that
1924 accesses those array elements. Use transfer_expr to generate code
1925 for transferring that element. Because elements may also be
1926 derived types, transfer_expr and transfer_array_component are mutually
1927 recursive. */
1928
1929static tree
bdfd2ff0 1930transfer_array_component (tree expr, gfc_component * cm, locus * where)
d2ccf6aa
VL
1931{
1932 tree tmp;
1933 stmtblock_t body;
1934 stmtblock_t block;
1935 gfc_loopinfo loop;
1936 int n;
1937 gfc_ss *ss;
1938 gfc_se se;
08dcec61 1939 gfc_array_info *ss_array;
d2ccf6aa
VL
1940
1941 gfc_start_block (&block);
1942 gfc_init_se (&se, NULL);
1943
1944 /* Create and initialize Scalarization Status. Unlike in
1945 gfc_trans_transfer, we can't simply use gfc_walk_expr to take
1946 care of this task, because we don't have a gfc_expr at hand.
1947 Build one manually, as in gfc_trans_subarray_assign. */
1948
66877276
MM
1949 ss = gfc_get_array_ss (gfc_ss_terminator, NULL, cm->as->rank,
1950 GFC_SS_COMPONENT);
1838afec 1951 ss_array = &ss->info->data.array;
08dcec61
MM
1952 ss_array->shape = gfc_get_shape (cm->as->rank);
1953 ss_array->descriptor = expr;
1954 ss_array->data = gfc_conv_array_data (expr);
1955 ss_array->offset = gfc_conv_array_offset (expr);
d2ccf6aa
VL
1956 for (n = 0; n < cm->as->rank; n++)
1957 {
08dcec61
MM
1958 ss_array->start[n] = gfc_conv_array_lbound (expr, n);
1959 ss_array->stride[n] = gfc_index_one_node;
d2ccf6aa 1960
08dcec61
MM
1961 mpz_init (ss_array->shape[n]);
1962 mpz_sub (ss_array->shape[n], cm->as->upper[n]->value.integer,
d2ccf6aa 1963 cm->as->lower[n]->value.integer);
08dcec61 1964 mpz_add_ui (ss_array->shape[n], ss_array->shape[n], 1);
d2ccf6aa
VL
1965 }
1966
f7b529fa 1967 /* Once we got ss, we use scalarizer to create the loop. */
d2ccf6aa
VL
1968
1969 gfc_init_loopinfo (&loop);
1970 gfc_add_ss_to_loop (&loop, ss);
1971 gfc_conv_ss_startstride (&loop);
bdfd2ff0 1972 gfc_conv_loop_setup (&loop, where);
d2ccf6aa
VL
1973 gfc_mark_ss_chain_used (ss, 1);
1974 gfc_start_scalarized_body (&loop, &body);
1975
1976 gfc_copy_loopinfo_to_se (&se, &loop);
1977 se.ss = ss;
1978
1979 /* gfc_conv_tmp_array_ref assumes that se.expr contains the array. */
1980 se.expr = expr;
1981 gfc_conv_tmp_array_ref (&se);
1982
1983 /* Now se.expr contains an element of the array. Take the address and pass
1984 it to the IO routines. */
628c189e 1985 tmp = gfc_build_addr_expr (NULL_TREE, se.expr);
aa5e22f0 1986 transfer_expr (&se, &cm->ts, tmp, NULL);
d2ccf6aa
VL
1987
1988 /* We are done now with the loop body. Wrap up the scalarizer and
f7b529fa 1989 return. */
d2ccf6aa
VL
1990
1991 gfc_add_block_to_block (&body, &se.pre);
1992 gfc_add_block_to_block (&body, &se.post);
1993
1994 gfc_trans_scalarizing_loops (&loop, &body);
1995
1996 gfc_add_block_to_block (&block, &loop.pre);
1997 gfc_add_block_to_block (&block, &loop.post);
1998
08dcec61
MM
1999 gcc_assert (ss_array->shape != NULL);
2000 gfc_free_shape (&ss_array->shape, cm->as->rank);
96654664
PB
2001 gfc_cleanup_loop (&loop);
2002
d2ccf6aa
VL
2003 return gfc_finish_block (&block);
2004}
6de9cd9a
DN
2005
2006/* Generate the call for a scalar transfer node. */
2007
2008static void
aa5e22f0 2009transfer_expr (gfc_se * se, gfc_typespec * ts, tree addr_expr, gfc_code * code)
6de9cd9a 2010{
8a221914 2011 tree tmp, function, arg2, arg3, field, expr;
6de9cd9a
DN
2012 gfc_component *c;
2013 int kind;
2014
a8b3b0b6
CR
2015 /* It is possible to get a C_NULL_PTR or C_NULL_FUNPTR expression here if
2016 the user says something like: print *, 'c_null_ptr: ', c_null_ptr
2017 We need to translate the expression to a constant if it's either
aa5e22f0
CR
2018 C_NULL_PTR or C_NULL_FUNPTR. We could also get a user variable of
2019 type C_PTR or C_FUNPTR, in which case the ts->type may no longer be
2020 BT_DERIVED (could have been changed by gfc_conv_expr). */
bc21d315
JW
2021 if ((ts->type == BT_DERIVED || ts->type == BT_INTEGER)
2022 && ts->u.derived != NULL
2023 && (ts->is_iso_c == 1 || ts->u.derived->ts.is_iso_c == 1))
a8b3b0b6 2024 {
aa5e22f0
CR
2025 /* C_PTR and C_FUNPTR have private components which means they can not
2026 be printed. However, if -std=gnu and not -pedantic, allow
2027 the component to be printed to help debugging. */
2028 if (gfc_notification_std (GFC_STD_GNU) != SILENT)
2029 {
2030 gfc_error_now ("Derived type '%s' at %L has PRIVATE components",
bc21d315 2031 ts->u.derived->name, code != NULL ? &(code->loc) :
aa5e22f0
CR
2032 &gfc_current_locus);
2033 return;
2034 }
2035
bc21d315
JW
2036 ts->type = ts->u.derived->ts.type;
2037 ts->kind = ts->u.derived->ts.kind;
2038 ts->f90_type = ts->u.derived->ts.f90_type;
a8b3b0b6
CR
2039 }
2040
6de9cd9a
DN
2041 kind = ts->kind;
2042 function = NULL;
2043 arg2 = NULL;
8a221914 2044 arg3 = NULL;
6de9cd9a
DN
2045
2046 switch (ts->type)
2047 {
2048 case BT_INTEGER:
df09d1d5 2049 arg2 = build_int_cst (integer_type_node, kind);
6eb6875d
TK
2050 if (last_dt == READ)
2051 function = iocall[IOCALL_X_INTEGER];
2052 else
2053 function = iocall[IOCALL_X_INTEGER_WRITE];
2054
6de9cd9a
DN
2055 break;
2056
2057 case BT_REAL:
df09d1d5 2058 arg2 = build_int_cst (integer_type_node, kind);
6eb6875d 2059 if (last_dt == READ)
1ec601bf
FXC
2060 {
2061 if (gfc_real16_is_float128 && ts->kind == 16)
2062 function = iocall[IOCALL_X_REAL128];
2063 else
2064 function = iocall[IOCALL_X_REAL];
2065 }
6eb6875d 2066 else
1ec601bf
FXC
2067 {
2068 if (gfc_real16_is_float128 && ts->kind == 16)
2069 function = iocall[IOCALL_X_REAL128_WRITE];
2070 else
2071 function = iocall[IOCALL_X_REAL_WRITE];
2072 }
6eb6875d 2073
6de9cd9a
DN
2074 break;
2075
2076 case BT_COMPLEX:
df09d1d5 2077 arg2 = build_int_cst (integer_type_node, kind);
6eb6875d 2078 if (last_dt == READ)
1ec601bf
FXC
2079 {
2080 if (gfc_real16_is_float128 && ts->kind == 16)
2081 function = iocall[IOCALL_X_COMPLEX128];
2082 else
2083 function = iocall[IOCALL_X_COMPLEX];
2084 }
6eb6875d 2085 else
1ec601bf
FXC
2086 {
2087 if (gfc_real16_is_float128 && ts->kind == 16)
2088 function = iocall[IOCALL_X_COMPLEX128_WRITE];
2089 else
2090 function = iocall[IOCALL_X_COMPLEX_WRITE];
2091 }
6eb6875d 2092
6de9cd9a
DN
2093 break;
2094
2095 case BT_LOGICAL:
df09d1d5 2096 arg2 = build_int_cst (integer_type_node, kind);
6eb6875d
TK
2097 if (last_dt == READ)
2098 function = iocall[IOCALL_X_LOGICAL];
2099 else
2100 function = iocall[IOCALL_X_LOGICAL_WRITE];
2101
6de9cd9a
DN
2102 break;
2103
2104 case BT_CHARACTER:
8a221914
JD
2105 if (kind == 4)
2106 {
2107 if (se->string_length)
2108 arg2 = se->string_length;
2109 else
2110 {
db3927fb
AH
2111 tmp = build_fold_indirect_ref_loc (input_location,
2112 addr_expr);
8a221914
JD
2113 gcc_assert (TREE_CODE (TREE_TYPE (tmp)) == ARRAY_TYPE);
2114 arg2 = TYPE_MAX_VALUE (TYPE_DOMAIN (TREE_TYPE (tmp)));
2115 arg2 = fold_convert (gfc_charlen_type_node, arg2);
2116 }
df09d1d5 2117 arg3 = build_int_cst (integer_type_node, kind);
6eb6875d
TK
2118 if (last_dt == READ)
2119 function = iocall[IOCALL_X_CHARACTER_WIDE];
2120 else
2121 function = iocall[IOCALL_X_CHARACTER_WIDE_WRITE];
2122
628c189e 2123 tmp = gfc_build_addr_expr (NULL_TREE, dt_parm);
db3927fb
AH
2124 tmp = build_call_expr_loc (input_location,
2125 function, 4, tmp, addr_expr, arg2, arg3);
8a221914
JD
2126 gfc_add_expr_to_block (&se->pre, tmp);
2127 gfc_add_block_to_block (&se->pre, &se->post);
2128 return;
2129 }
2130 /* Fall through. */
7b95e2a8 2131 case BT_HOLLERITH:
d2ccf6aa
VL
2132 if (se->string_length)
2133 arg2 = se->string_length;
2134 else
2135 {
db3927fb
AH
2136 tmp = build_fold_indirect_ref_loc (input_location,
2137 addr_expr);
d2ccf6aa
VL
2138 gcc_assert (TREE_CODE (TREE_TYPE (tmp)) == ARRAY_TYPE);
2139 arg2 = TYPE_MAX_VALUE (TYPE_DOMAIN (TREE_TYPE (tmp)));
2140 }
6eb6875d
TK
2141 if (last_dt == READ)
2142 function = iocall[IOCALL_X_CHARACTER];
2143 else
2144 function = iocall[IOCALL_X_CHARACTER_WRITE];
2145
6de9cd9a
DN
2146 break;
2147
2148 case BT_DERIVED:
fc2655fb
TB
2149 if (ts->u.derived->components == NULL)
2150 return;
2151
d2ccf6aa 2152 /* Recurse into the elements of the derived type. */
6de9cd9a 2153 expr = gfc_evaluate_now (addr_expr, &se->pre);
db3927fb
AH
2154 expr = build_fold_indirect_ref_loc (input_location,
2155 expr);
6de9cd9a 2156
bc21d315 2157 for (c = ts->u.derived->components; c; c = c->next)
6de9cd9a
DN
2158 {
2159 field = c->backend_decl;
6e45f57b 2160 gcc_assert (field && TREE_CODE (field) == FIELD_DECL);
6de9cd9a 2161
db3927fb
AH
2162 tmp = fold_build3_loc (UNKNOWN_LOCATION,
2163 COMPONENT_REF, TREE_TYPE (field),
44855d8c 2164 expr, field, NULL_TREE);
6de9cd9a 2165
d4b7d0f0 2166 if (c->attr.dimension)
d2ccf6aa 2167 {
bdfd2ff0 2168 tmp = transfer_array_component (tmp, c, & code->loc);
d2ccf6aa
VL
2169 gfc_add_expr_to_block (&se->pre, tmp);
2170 }
2171 else
2172 {
d4b7d0f0 2173 if (!c->attr.pointer)
628c189e 2174 tmp = gfc_build_addr_expr (NULL_TREE, tmp);
aa5e22f0 2175 transfer_expr (se, &c->ts, tmp, code);
d2ccf6aa 2176 }
6de9cd9a
DN
2177 }
2178 return;
2179
2180 default:
2181 internal_error ("Bad IO basetype (%d)", ts->type);
2182 }
2183
628c189e 2184 tmp = gfc_build_addr_expr (NULL_TREE, dt_parm);
db3927fb
AH
2185 tmp = build_call_expr_loc (input_location,
2186 function, 3, tmp, addr_expr, arg2);
6de9cd9a
DN
2187 gfc_add_expr_to_block (&se->pre, tmp);
2188 gfc_add_block_to_block (&se->pre, &se->post);
8750f9cd 2189
6de9cd9a
DN
2190}
2191
2192
18623fae
JB
2193/* Generate a call to pass an array descriptor to the IO library. The
2194 array should be of one of the intrinsic types. */
2195
2196static void
2197transfer_array_desc (gfc_se * se, gfc_typespec * ts, tree addr_expr)
2198{
6eb6875d 2199 tree tmp, charlen_arg, kind_arg, io_call;
18623fae
JB
2200
2201 if (ts->type == BT_CHARACTER)
2202 charlen_arg = se->string_length;
2203 else
df09d1d5 2204 charlen_arg = build_int_cst (gfc_charlen_type_node, 0);
18623fae 2205
df09d1d5 2206 kind_arg = build_int_cst (integer_type_node, ts->kind);
e5ef4b3b 2207
628c189e 2208 tmp = gfc_build_addr_expr (NULL_TREE, dt_parm);
6eb6875d
TK
2209 if (last_dt == READ)
2210 io_call = iocall[IOCALL_X_ARRAY];
2211 else
2212 io_call = iocall[IOCALL_X_ARRAY_WRITE];
2213
033e7d21 2214 tmp = build_call_expr_loc (UNKNOWN_LOCATION,
6eb6875d 2215 io_call, 4,
5039610b 2216 tmp, addr_expr, kind_arg, charlen_arg);
18623fae
JB
2217 gfc_add_expr_to_block (&se->pre, tmp);
2218 gfc_add_block_to_block (&se->pre, &se->post);
2219}
2220
2221
6de9cd9a
DN
2222/* gfc_trans_transfer()-- Translate a TRANSFER code node */
2223
2224tree
2225gfc_trans_transfer (gfc_code * code)
2226{
2227 stmtblock_t block, body;
2228 gfc_loopinfo loop;
2229 gfc_expr *expr;
99c7ab42 2230 gfc_ref *ref;
6de9cd9a
DN
2231 gfc_ss *ss;
2232 gfc_se se;
2233 tree tmp;
c63173dd 2234 int n;
6de9cd9a
DN
2235
2236 gfc_start_block (&block);
18623fae 2237 gfc_init_block (&body);
6de9cd9a 2238
a513927a 2239 expr = code->expr1;
99c7ab42 2240 ref = NULL;
6de9cd9a
DN
2241 gfc_init_se (&se, NULL);
2242
2960a368 2243 if (expr->rank == 0)
18623fae 2244 {
815d8045 2245 /* Transfer a scalar value. */
18623fae 2246 gfc_conv_expr_reference (&se, expr);
aa5e22f0 2247 transfer_expr (&se, &expr->ts, se.expr, code);
18623fae 2248 }
815d8045 2249 else
6de9cd9a 2250 {
99c7ab42
PT
2251 /* Transfer an array. If it is an array of an intrinsic
2252 type, pass the descriptor to the library. Otherwise
2253 scalarize the transfer. */
2a573572 2254 if (expr->ref && !gfc_is_proc_ptr_comp (expr))
99c7ab42
PT
2255 {
2256 for (ref = expr->ref; ref && ref->type != REF_ARRAY;
fc2655fb
TB
2257 ref = ref->next);
2258 gcc_assert (ref && ref->type == REF_ARRAY);
99c7ab42
PT
2259 }
2260
1d6b7f39
PT
2261 if (expr->ts.type != BT_DERIVED
2262 && ref && ref->next == NULL
2263 && !is_subref_array (expr))
815d8045 2264 {
c63173dd
PT
2265 bool seen_vector = false;
2266
2267 if (ref && ref->u.ar.type == AR_SECTION)
2268 {
2269 for (n = 0; n < ref->u.ar.dimen; n++)
2270 if (ref->u.ar.dimen_type[n] == DIMEN_VECTOR)
2271 seen_vector = true;
2272 }
2273
2274 if (seen_vector && last_dt == READ)
2275 {
2276 /* Create a temp, read to that and copy it back. */
430f2d1f 2277 gfc_conv_subref_array_arg (&se, expr, 0, INTENT_OUT, false);
c63173dd
PT
2278 tmp = se.expr;
2279 }
2280 else
2281 {
2282 /* Get the descriptor. */
2960a368 2283 gfc_conv_expr_descriptor (&se, expr);
628c189e 2284 tmp = gfc_build_addr_expr (NULL_TREE, se.expr);
c63173dd
PT
2285 }
2286
99c7ab42
PT
2287 transfer_array_desc (&se, &expr->ts, tmp);
2288 goto finish_block_label;
815d8045 2289 }
2960a368 2290
6de9cd9a 2291 /* Initialize the scalarizer. */
2960a368 2292 ss = gfc_walk_expr (expr);
6de9cd9a
DN
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"