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