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