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