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