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