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