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