1 /* IO Code translation/library interface
2 Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008 Free Software
4 Contributed by Paul Brook
6 This file is part of GCC.
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
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
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/>. */
25 #include "coretypes.h"
27 #include "tree-gimple.h"
33 #include "trans-stmt.h"
34 #include "trans-array.h"
35 #include "trans-types.h"
36 #include "trans-const.h"
38 /* Members of the ioparm structure. */
66 typedef struct gfc_st_parameter_field GTY(())
70 enum ioparam_type param_type;
71 enum iofield_type type;
75 gfc_st_parameter_field;
77 typedef struct gfc_st_parameter GTY(())
86 #define IOPARM(param_type, name, mask, type) IOPARM_##param_type##_##name,
92 static GTY(()) gfc_st_parameter st_parameter[] =
102 static GTY(()) gfc_st_parameter_field st_parameter_field[] =
104 #define IOPARM(param_type, name, mask, type) \
105 { #name, mask, IOPARM_ptype_##param_type, IOPARM_type_##type, NULL, NULL },
106 #include "ioparm.def"
108 { NULL, 0, 0, 0, NULL, NULL }
111 /* Library I/O subroutines */
129 IOCALL_IOLENGTH_DONE,
135 IOCALL_SET_NML_VAL_DIM,
139 static GTY(()) tree iocall[IOCALL_NUM];
141 /* Variable for keeping track of what the last data transfer statement
142 was. Used for deciding which subroutine to call when the data
143 transfer is complete. */
144 static enum { READ, WRITE, IOLENGTH } last_dt;
146 /* The data transfer parameter block that should be shared by all
147 data transfer calls belonging to the same read/write/iolength. */
148 static GTY(()) tree dt_parm;
149 static stmtblock_t *dt_post_end_block;
152 gfc_build_st_parameter (enum ioparam_type ptype, tree *types)
155 gfc_st_parameter_field *p;
158 tree t = make_node (RECORD_TYPE);
160 len = strlen (st_parameter[ptype].name);
161 gcc_assert (len <= sizeof (name) - sizeof ("__st_parameter_"));
162 memcpy (name, "__st_parameter_", sizeof ("__st_parameter_"));
163 memcpy (name + sizeof ("__st_parameter_") - 1, st_parameter[ptype].name,
165 TYPE_NAME (t) = get_identifier (name);
167 for (type = 0, p = st_parameter_field; type < IOPARM_field_num; type++, p++)
168 if (p->param_type == ptype)
171 case IOPARM_type_int4:
172 case IOPARM_type_intio:
173 case IOPARM_type_pint4:
174 case IOPARM_type_pintio:
175 case IOPARM_type_parray:
176 case IOPARM_type_pchar:
177 case IOPARM_type_pad:
178 p->field = gfc_add_field_to_struct (&TYPE_FIELDS (t), t,
179 get_identifier (p->name),
182 case IOPARM_type_char1:
183 p->field = gfc_add_field_to_struct (&TYPE_FIELDS (t), t,
184 get_identifier (p->name),
187 case IOPARM_type_char2:
188 len = strlen (p->name);
189 gcc_assert (len <= sizeof (name) - sizeof ("_len"));
190 memcpy (name, p->name, len);
191 memcpy (name + len, "_len", sizeof ("_len"));
192 p->field_len = gfc_add_field_to_struct (&TYPE_FIELDS (t), t,
193 get_identifier (name),
194 gfc_charlen_type_node);
195 if (p->type == IOPARM_type_char2)
196 p->field = gfc_add_field_to_struct (&TYPE_FIELDS (t), t,
197 get_identifier (p->name),
200 case IOPARM_type_common:
202 = gfc_add_field_to_struct (&TYPE_FIELDS (t), t,
203 get_identifier (p->name),
204 st_parameter[IOPARM_ptype_common].type);
206 case IOPARM_type_num:
211 st_parameter[ptype].type = t;
215 /* Build code to test an error condition and call generate_error if needed.
216 Note: This builds calls to generate_error in the runtime library function.
217 The function generate_error is dependent on certain parameters in the
218 st_parameter_common flags to be set. (See libgfortran/runtime/error.c)
219 Therefore, the code to set these flags must be generated before
220 this function is used. */
223 gfc_trans_io_runtime_check (tree cond, tree var, int error_code,
224 const char * msgid, stmtblock_t * pblock)
229 tree arg1, arg2, arg3;
232 if (integer_zerop (cond))
235 /* The code to generate the error. */
236 gfc_start_block (&block);
238 arg1 = build_fold_addr_expr (var);
240 arg2 = build_int_cst (integer_type_node, error_code),
242 asprintf (&message, "%s", _(msgid));
243 arg3 = gfc_build_addr_expr (pchar_type_node,
244 gfc_build_localized_cstring_const (message));
247 tmp = build_call_expr (gfor_fndecl_generate_error, 3, arg1, arg2, arg3);
249 gfc_add_expr_to_block (&block, tmp);
251 body = gfc_finish_block (&block);
253 if (integer_onep (cond))
255 gfc_add_expr_to_block (pblock, body);
259 /* Tell the compiler that this isn't likely. */
260 cond = fold_convert (long_integer_type_node, cond);
261 tmp = build_int_cst (long_integer_type_node, 0);
262 cond = build_call_expr (built_in_decls[BUILT_IN_EXPECT], 2, cond, tmp);
263 cond = fold_convert (boolean_type_node, cond);
265 tmp = build3_v (COND_EXPR, cond, body, build_empty_stmt ());
266 gfc_add_expr_to_block (pblock, tmp);
271 /* Create function decls for IO library functions. */
274 gfc_build_io_library_fndecls (void)
276 tree types[IOPARM_type_num], pad_idx, gfc_int4_type_node;
277 tree gfc_intio_type_node;
278 tree parm_type, dt_parm_type;
279 HOST_WIDE_INT pad_size;
280 enum ioparam_type ptype;
282 types[IOPARM_type_int4] = gfc_int4_type_node = gfc_get_int_type (4);
283 types[IOPARM_type_intio] = gfc_intio_type_node
284 = gfc_get_int_type (gfc_intio_kind);
285 types[IOPARM_type_pint4] = build_pointer_type (gfc_int4_type_node);
286 types[IOPARM_type_pintio]
287 = build_pointer_type (gfc_intio_type_node);
288 types[IOPARM_type_parray] = pchar_type_node;
289 types[IOPARM_type_pchar] = pchar_type_node;
290 pad_size = 16 * TREE_INT_CST_LOW (TYPE_SIZE_UNIT (pchar_type_node));
291 pad_size += 32 * TREE_INT_CST_LOW (TYPE_SIZE_UNIT (integer_type_node));
292 pad_idx = build_index_type (build_int_cst (NULL_TREE, pad_size));
293 types[IOPARM_type_pad] = build_array_type (char_type_node, pad_idx);
295 /* pad actually contains pointers and integers so it needs to have an
296 alignment that is at least as large as the needed alignment for those
297 types. See the st_parameter_dt structure in libgfortran/io/io.h for
298 what really goes into this space. */
299 TYPE_ALIGN (types[IOPARM_type_pad]) = MAX (TYPE_ALIGN (pchar_type_node),
300 TYPE_ALIGN (gfc_get_int_type (gfc_max_integer_kind)));
302 for (ptype = IOPARM_ptype_common; ptype < IOPARM_ptype_num; ptype++)
303 gfc_build_st_parameter (ptype, types);
305 /* Define the transfer functions. */
307 dt_parm_type = build_pointer_type (st_parameter[IOPARM_ptype_dt].type);
309 iocall[IOCALL_X_INTEGER] =
310 gfc_build_library_function_decl (get_identifier
311 (PREFIX("transfer_integer")),
312 void_type_node, 3, dt_parm_type,
313 pvoid_type_node, gfc_int4_type_node);
315 iocall[IOCALL_X_LOGICAL] =
316 gfc_build_library_function_decl (get_identifier
317 (PREFIX("transfer_logical")),
318 void_type_node, 3, dt_parm_type,
319 pvoid_type_node, gfc_int4_type_node);
321 iocall[IOCALL_X_CHARACTER] =
322 gfc_build_library_function_decl (get_identifier
323 (PREFIX("transfer_character")),
324 void_type_node, 3, dt_parm_type,
325 pvoid_type_node, gfc_int4_type_node);
327 iocall[IOCALL_X_REAL] =
328 gfc_build_library_function_decl (get_identifier (PREFIX("transfer_real")),
329 void_type_node, 3, dt_parm_type,
330 pvoid_type_node, gfc_int4_type_node);
332 iocall[IOCALL_X_COMPLEX] =
333 gfc_build_library_function_decl (get_identifier
334 (PREFIX("transfer_complex")),
335 void_type_node, 3, dt_parm_type,
336 pvoid_type_node, gfc_int4_type_node);
338 iocall[IOCALL_X_ARRAY] =
339 gfc_build_library_function_decl (get_identifier
340 (PREFIX("transfer_array")),
341 void_type_node, 4, dt_parm_type,
342 pvoid_type_node, integer_type_node,
343 gfc_charlen_type_node);
345 /* Library entry points */
347 iocall[IOCALL_READ] =
348 gfc_build_library_function_decl (get_identifier (PREFIX("st_read")),
349 void_type_node, 1, dt_parm_type);
351 iocall[IOCALL_WRITE] =
352 gfc_build_library_function_decl (get_identifier (PREFIX("st_write")),
353 void_type_node, 1, dt_parm_type);
355 parm_type = build_pointer_type (st_parameter[IOPARM_ptype_open].type);
356 iocall[IOCALL_OPEN] =
357 gfc_build_library_function_decl (get_identifier (PREFIX("st_open")),
358 void_type_node, 1, parm_type);
361 parm_type = build_pointer_type (st_parameter[IOPARM_ptype_close].type);
362 iocall[IOCALL_CLOSE] =
363 gfc_build_library_function_decl (get_identifier (PREFIX("st_close")),
364 void_type_node, 1, parm_type);
366 parm_type = build_pointer_type (st_parameter[IOPARM_ptype_inquire].type);
367 iocall[IOCALL_INQUIRE] =
368 gfc_build_library_function_decl (get_identifier (PREFIX("st_inquire")),
369 gfc_int4_type_node, 1, parm_type);
371 iocall[IOCALL_IOLENGTH] =
372 gfc_build_library_function_decl(get_identifier (PREFIX("st_iolength")),
373 void_type_node, 1, dt_parm_type);
375 parm_type = build_pointer_type (st_parameter[IOPARM_ptype_filepos].type);
376 iocall[IOCALL_REWIND] =
377 gfc_build_library_function_decl (get_identifier (PREFIX("st_rewind")),
378 gfc_int4_type_node, 1, parm_type);
380 iocall[IOCALL_BACKSPACE] =
381 gfc_build_library_function_decl (get_identifier (PREFIX("st_backspace")),
382 gfc_int4_type_node, 1, parm_type);
384 iocall[IOCALL_ENDFILE] =
385 gfc_build_library_function_decl (get_identifier (PREFIX("st_endfile")),
386 gfc_int4_type_node, 1, parm_type);
388 iocall[IOCALL_FLUSH] =
389 gfc_build_library_function_decl (get_identifier (PREFIX("st_flush")),
390 gfc_int4_type_node, 1, parm_type);
392 /* Library helpers */
394 iocall[IOCALL_READ_DONE] =
395 gfc_build_library_function_decl (get_identifier (PREFIX("st_read_done")),
396 gfc_int4_type_node, 1, dt_parm_type);
398 iocall[IOCALL_WRITE_DONE] =
399 gfc_build_library_function_decl (get_identifier (PREFIX("st_write_done")),
400 gfc_int4_type_node, 1, dt_parm_type);
402 iocall[IOCALL_IOLENGTH_DONE] =
403 gfc_build_library_function_decl (get_identifier (PREFIX("st_iolength_done")),
404 gfc_int4_type_node, 1, dt_parm_type);
407 iocall[IOCALL_SET_NML_VAL] =
408 gfc_build_library_function_decl (get_identifier (PREFIX("st_set_nml_var")),
409 void_type_node, 6, dt_parm_type,
410 pvoid_type_node, pvoid_type_node,
411 gfc_int4_type_node, gfc_charlen_type_node,
414 iocall[IOCALL_SET_NML_VAL_DIM] =
415 gfc_build_library_function_decl (get_identifier (PREFIX("st_set_nml_var_dim")),
416 void_type_node, 5, dt_parm_type,
417 gfc_int4_type_node, gfc_array_index_type,
418 gfc_array_index_type, gfc_array_index_type);
422 /* Generate code to store an integer constant into the
423 st_parameter_XXX structure. */
426 set_parameter_const (stmtblock_t *block, tree var, enum iofield type,
430 gfc_st_parameter_field *p = &st_parameter_field[type];
432 if (p->param_type == IOPARM_ptype_common)
433 var = fold_build3 (COMPONENT_REF, st_parameter[IOPARM_ptype_common].type,
434 var, TYPE_FIELDS (TREE_TYPE (var)), NULL_TREE);
435 tmp = fold_build3 (COMPONENT_REF, TREE_TYPE (p->field), var, p->field,
437 gfc_add_modify_expr (block, tmp, build_int_cst (TREE_TYPE (p->field), val));
442 /* Generate code to store a non-string I/O parameter into the
443 st_parameter_XXX structure. This is a pass by value. */
446 set_parameter_value (stmtblock_t *block, tree var, enum iofield type,
451 gfc_st_parameter_field *p = &st_parameter_field[type];
452 tree dest_type = TREE_TYPE (p->field);
454 gfc_init_se (&se, NULL);
455 gfc_conv_expr_val (&se, e);
457 /* If we're storing a UNIT number, we need to check it first. */
458 if (type == IOPARM_common_unit && e->ts.kind != 4)
463 /* Don't evaluate the UNIT number multiple times. */
464 se.expr = gfc_evaluate_now (se.expr, &se.pre);
466 /* UNIT numbers should be nonnegative. */
467 cond = fold_build2 (LT_EXPR, boolean_type_node, se.expr,
468 build_int_cst (TREE_TYPE (se.expr),0));
469 gfc_trans_io_runtime_check (cond, var, LIBERROR_BAD_UNIT,
470 "Negative unit number in I/O statement",
473 /* UNIT numbers should be less than the max. */
474 i = gfc_validate_kind (BT_INTEGER, 4, false);
475 max = gfc_conv_mpz_to_tree (gfc_integer_kinds[i].huge, 4);
476 cond = fold_build2 (GT_EXPR, boolean_type_node, se.expr,
477 fold_convert (TREE_TYPE (se.expr), max));
478 gfc_trans_io_runtime_check (cond, var, LIBERROR_BAD_UNIT,
479 "Unit number in I/O statement too large",
484 se.expr = convert (dest_type, se.expr);
485 gfc_add_block_to_block (block, &se.pre);
487 if (p->param_type == IOPARM_ptype_common)
488 var = fold_build3 (COMPONENT_REF, st_parameter[IOPARM_ptype_common].type,
489 var, TYPE_FIELDS (TREE_TYPE (var)), NULL_TREE);
491 tmp = fold_build3 (COMPONENT_REF, dest_type, var, p->field, NULL_TREE);
492 gfc_add_modify_expr (block, tmp, se.expr);
497 /* Generate code to store a non-string I/O parameter into the
498 st_parameter_XXX structure. This is pass by reference. */
501 set_parameter_ref (stmtblock_t *block, stmtblock_t *postblock,
502 tree var, enum iofield type, gfc_expr *e)
506 gfc_st_parameter_field *p = &st_parameter_field[type];
508 gcc_assert (e->ts.type == BT_INTEGER || e->ts.type == BT_LOGICAL);
509 gfc_init_se (&se, NULL);
510 gfc_conv_expr_lhs (&se, e);
512 gfc_add_block_to_block (block, &se.pre);
514 if (TYPE_MODE (TREE_TYPE (se.expr))
515 == TYPE_MODE (TREE_TYPE (TREE_TYPE (p->field))))
517 addr = convert (TREE_TYPE (p->field), build_fold_addr_expr (se.expr));
519 /* If this is for the iostat variable initialize the
520 user variable to LIBERROR_OK which is zero. */
521 if (type == IOPARM_common_iostat)
522 gfc_add_modify_expr (block, se.expr,
523 build_int_cst (TREE_TYPE (se.expr), LIBERROR_OK));
527 /* The type used by the library has different size
528 from the type of the variable supplied by the user.
529 Need to use a temporary. */
530 tree tmpvar = gfc_create_var (TREE_TYPE (TREE_TYPE (p->field)),
531 st_parameter_field[type].name);
533 /* If this is for the iostat variable, initialize the
534 user variable to LIBERROR_OK which is zero. */
535 if (type == IOPARM_common_iostat)
536 gfc_add_modify_expr (block, tmpvar,
537 build_int_cst (TREE_TYPE (tmpvar), LIBERROR_OK));
539 addr = build_fold_addr_expr (tmpvar);
540 /* After the I/O operation, we set the variable from the temporary. */
541 tmp = convert (TREE_TYPE (se.expr), tmpvar);
542 gfc_add_modify_expr (postblock, se.expr, tmp);
545 if (p->param_type == IOPARM_ptype_common)
546 var = fold_build3 (COMPONENT_REF, st_parameter[IOPARM_ptype_common].type,
547 var, TYPE_FIELDS (TREE_TYPE (var)), NULL_TREE);
548 tmp = fold_build3 (COMPONENT_REF, TREE_TYPE (p->field),
549 var, p->field, NULL_TREE);
550 gfc_add_modify_expr (block, tmp, addr);
554 /* Given an array expr, find its address and length to get a string. If the
555 array is full, the string's address is the address of array's first element
556 and the length is the size of the whole array. If it is an element, the
557 string's address is the element's address and the length is the rest size of
562 gfc_convert_array_to_string (gfc_se * se, gfc_expr * e)
571 sym = e->symtree->n.sym;
572 rank = sym->as->rank - 1;
574 if (e->ref->u.ar.type == AR_FULL)
576 se->expr = gfc_get_symbol_decl (sym);
577 se->expr = gfc_conv_array_data (se->expr);
581 gfc_conv_expr (se, e);
584 array = sym->backend_decl;
585 type = TREE_TYPE (array);
587 if (GFC_ARRAY_TYPE_P (type))
588 size = GFC_TYPE_ARRAY_SIZE (type);
591 gcc_assert (GFC_DESCRIPTOR_TYPE_P (type));
592 size = gfc_conv_array_stride (array, rank);
593 tmp = fold_build2 (MINUS_EXPR, gfc_array_index_type,
594 gfc_conv_array_ubound (array, rank),
595 gfc_conv_array_lbound (array, rank));
596 tmp = fold_build2 (PLUS_EXPR, gfc_array_index_type, tmp,
598 size = fold_build2 (MULT_EXPR, gfc_array_index_type, tmp, size);
603 /* If it is an element, we need the its address and size of the rest. */
604 if (e->ref->u.ar.type == AR_ELEMENT)
606 size = fold_build2 (MINUS_EXPR, gfc_array_index_type, size,
607 TREE_OPERAND (se->expr, 1));
608 se->expr = build_fold_addr_expr (se->expr);
611 tmp = TYPE_SIZE_UNIT (gfc_get_element_type (type));
612 size = fold_build2 (MULT_EXPR, gfc_array_index_type, size,
613 fold_convert (gfc_array_index_type, tmp));
615 se->string_length = fold_convert (gfc_charlen_type_node, size);
619 /* Generate code to store a string and its length into the
620 st_parameter_XXX structure. */
623 set_string (stmtblock_t * block, stmtblock_t * postblock, tree var,
624 enum iofield type, gfc_expr * e)
630 gfc_st_parameter_field *p = &st_parameter_field[type];
632 gfc_init_se (&se, NULL);
634 if (p->param_type == IOPARM_ptype_common)
635 var = fold_build3 (COMPONENT_REF, st_parameter[IOPARM_ptype_common].type,
636 var, TYPE_FIELDS (TREE_TYPE (var)), NULL_TREE);
637 io = fold_build3 (COMPONENT_REF, TREE_TYPE (p->field),
638 var, p->field, NULL_TREE);
639 len = fold_build3 (COMPONENT_REF, TREE_TYPE (p->field_len),
640 var, p->field_len, NULL_TREE);
642 /* Integer variable assigned a format label. */
643 if (e->ts.type == BT_INTEGER && e->symtree->n.sym->attr.assign == 1)
648 gfc_conv_label_variable (&se, e);
649 tmp = GFC_DECL_STRING_LEN (se.expr);
650 cond = fold_build2 (LT_EXPR, boolean_type_node,
651 tmp, build_int_cst (TREE_TYPE (tmp), 0));
653 asprintf(&msg, "Label assigned to variable '%s' (%%ld) is not a format "
654 "label", e->symtree->name);
655 gfc_trans_runtime_check (cond, &se.pre, &e->where, msg,
656 fold_convert (long_integer_type_node, tmp));
659 gfc_add_modify_expr (&se.pre, io,
660 fold_convert (TREE_TYPE (io), GFC_DECL_ASSIGN_ADDR (se.expr)));
661 gfc_add_modify_expr (&se.pre, len, GFC_DECL_STRING_LEN (se.expr));
665 /* General character. */
666 if (e->ts.type == BT_CHARACTER && e->rank == 0)
667 gfc_conv_expr (&se, e);
668 /* Array assigned Hollerith constant or character array. */
669 else if (e->symtree && (e->symtree->n.sym->as->rank > 0))
670 gfc_convert_array_to_string (&se, e);
674 gfc_conv_string_parameter (&se);
675 gfc_add_modify_expr (&se.pre, io, fold_convert (TREE_TYPE (io), se.expr));
676 gfc_add_modify_expr (&se.pre, len, se.string_length);
679 gfc_add_block_to_block (block, &se.pre);
680 gfc_add_block_to_block (postblock, &se.post);
685 /* Generate code to store the character (array) and the character length
686 for an internal unit. */
689 set_internal_unit (stmtblock_t * block, stmtblock_t * post_block,
690 tree var, gfc_expr * e)
697 gfc_st_parameter_field *p;
700 gfc_init_se (&se, NULL);
702 p = &st_parameter_field[IOPARM_dt_internal_unit];
704 io = fold_build3 (COMPONENT_REF, TREE_TYPE (p->field),
705 var, p->field, NULL_TREE);
706 len = fold_build3 (COMPONENT_REF, TREE_TYPE (p->field_len),
707 var, p->field_len, NULL_TREE);
708 p = &st_parameter_field[IOPARM_dt_internal_unit_desc];
709 desc = fold_build3 (COMPONENT_REF, TREE_TYPE (p->field),
710 var, p->field, NULL_TREE);
712 gcc_assert (e->ts.type == BT_CHARACTER);
714 /* Character scalars. */
717 gfc_conv_expr (&se, e);
718 gfc_conv_string_parameter (&se);
720 se.expr = build_int_cst (pchar_type_node, 0);
723 /* Character array. */
724 else if (e->rank > 0)
726 se.ss = gfc_walk_expr (e);
728 if (is_subref_array (e))
730 /* Use a temporary for components of arrays of derived types
731 or substring array references. */
732 gfc_conv_subref_array_arg (&se, e, 0,
733 last_dt == READ ? INTENT_IN : INTENT_OUT);
734 tmp = build_fold_indirect_ref (se.expr);
735 se.expr = gfc_build_addr_expr (pchar_type_node, tmp);
736 tmp = gfc_conv_descriptor_data_get (tmp);
740 /* Return the data pointer and rank from the descriptor. */
741 gfc_conv_expr_descriptor (&se, e, se.ss);
742 tmp = gfc_conv_descriptor_data_get (se.expr);
743 se.expr = gfc_build_addr_expr (pchar_type_node, se.expr);
749 /* The cast is needed for character substrings and the descriptor
751 gfc_add_modify_expr (&se.pre, io, fold_convert (TREE_TYPE (io), tmp));
752 gfc_add_modify_expr (&se.pre, len,
753 fold_convert (TREE_TYPE (len), se.string_length));
754 gfc_add_modify_expr (&se.pre, desc, se.expr);
756 gfc_add_block_to_block (block, &se.pre);
757 gfc_add_block_to_block (post_block, &se.post);
761 /* Add a case to a IO-result switch. */
764 add_case (int label_value, gfc_st_label * label, stmtblock_t * body)
769 return; /* No label, no case */
771 value = build_int_cst (NULL_TREE, label_value);
773 /* Make a backend label for this case. */
774 tmp = gfc_build_label_decl (NULL_TREE);
776 /* And the case itself. */
777 tmp = build3_v (CASE_LABEL_EXPR, value, NULL_TREE, tmp);
778 gfc_add_expr_to_block (body, tmp);
780 /* Jump to the label. */
781 tmp = build1_v (GOTO_EXPR, gfc_get_label_decl (label));
782 gfc_add_expr_to_block (body, tmp);
786 /* Generate a switch statement that branches to the correct I/O
787 result label. The last statement of an I/O call stores the
788 result into a variable because there is often cleanup that
789 must be done before the switch, so a temporary would have to
790 be created anyway. */
793 io_result (stmtblock_t * block, tree var, gfc_st_label * err_label,
794 gfc_st_label * end_label, gfc_st_label * eor_label)
798 gfc_st_parameter_field *p = &st_parameter_field[IOPARM_common_flags];
800 /* If no labels are specified, ignore the result instead
801 of building an empty switch. */
802 if (err_label == NULL
804 && eor_label == NULL)
807 /* Build a switch statement. */
808 gfc_start_block (&body);
810 /* The label values here must be the same as the values
811 in the library_return enum in the runtime library */
812 add_case (1, err_label, &body);
813 add_case (2, end_label, &body);
814 add_case (3, eor_label, &body);
816 tmp = gfc_finish_block (&body);
818 var = fold_build3 (COMPONENT_REF, st_parameter[IOPARM_ptype_common].type,
819 var, TYPE_FIELDS (TREE_TYPE (var)), NULL_TREE);
820 rc = fold_build3 (COMPONENT_REF, TREE_TYPE (p->field),
821 var, p->field, NULL_TREE);
822 rc = fold_build2 (BIT_AND_EXPR, TREE_TYPE (rc),
823 rc, build_int_cst (TREE_TYPE (rc),
824 IOPARM_common_libreturn_mask));
826 tmp = build3_v (SWITCH_EXPR, rc, tmp, NULL_TREE);
828 gfc_add_expr_to_block (block, tmp);
832 /* Store the current file and line number to variables so that if a
833 library call goes awry, we can tell the user where the problem is. */
836 set_error_locus (stmtblock_t * block, tree var, locus * where)
839 tree str, locus_file;
841 gfc_st_parameter_field *p = &st_parameter_field[IOPARM_common_filename];
843 locus_file = fold_build3 (COMPONENT_REF,
844 st_parameter[IOPARM_ptype_common].type,
845 var, TYPE_FIELDS (TREE_TYPE (var)), NULL_TREE);
846 locus_file = fold_build3 (COMPONENT_REF, TREE_TYPE (p->field),
847 locus_file, p->field, NULL_TREE);
849 str = gfc_build_cstring_const (f->filename);
851 str = gfc_build_addr_expr (pchar_type_node, str);
852 gfc_add_modify_expr (block, locus_file, str);
854 #ifdef USE_MAPPED_LOCATION
855 line = LOCATION_LINE (where->lb->location);
857 line = where->lb->linenum;
859 set_parameter_const (block, var, IOPARM_common_line, line);
863 /* Translate an OPEN statement. */
866 gfc_trans_open (gfc_code * code)
868 stmtblock_t block, post_block;
871 unsigned int mask = 0;
873 gfc_start_block (&block);
874 gfc_init_block (&post_block);
876 var = gfc_create_var (st_parameter[IOPARM_ptype_open].type, "open_parm");
878 set_error_locus (&block, var, &code->loc);
882 mask |= set_string (&block, &post_block, var, IOPARM_common_iomsg,
886 mask |= set_parameter_ref (&block, &post_block, var, IOPARM_common_iostat,
890 mask |= IOPARM_common_err;
893 mask |= set_string (&block, &post_block, var, IOPARM_open_file, p->file);
896 mask |= set_string (&block, &post_block, var, IOPARM_open_status,
900 mask |= set_string (&block, &post_block, var, IOPARM_open_access,
904 mask |= set_string (&block, &post_block, var, IOPARM_open_form, p->form);
907 mask |= set_parameter_value (&block, var, IOPARM_open_recl_in, p->recl);
910 mask |= set_string (&block, &post_block, var, IOPARM_open_blank,
914 mask |= set_string (&block, &post_block, var, IOPARM_open_position,
918 mask |= set_string (&block, &post_block, var, IOPARM_open_action,
922 mask |= set_string (&block, &post_block, var, IOPARM_open_delim,
926 mask |= set_string (&block, &post_block, var, IOPARM_open_pad, p->pad);
929 mask |= set_string (&block, &post_block, var, IOPARM_open_convert,
932 set_parameter_const (&block, var, IOPARM_common_flags, mask);
935 set_parameter_value (&block, var, IOPARM_common_unit, p->unit);
937 set_parameter_const (&block, var, IOPARM_common_unit, 0);
939 tmp = build_fold_addr_expr (var);
940 tmp = build_call_expr (iocall[IOCALL_OPEN], 1, tmp);
941 gfc_add_expr_to_block (&block, tmp);
943 gfc_add_block_to_block (&block, &post_block);
945 io_result (&block, var, p->err, NULL, NULL);
947 return gfc_finish_block (&block);
951 /* Translate a CLOSE statement. */
954 gfc_trans_close (gfc_code * code)
956 stmtblock_t block, post_block;
959 unsigned int mask = 0;
961 gfc_start_block (&block);
962 gfc_init_block (&post_block);
964 var = gfc_create_var (st_parameter[IOPARM_ptype_close].type, "close_parm");
966 set_error_locus (&block, var, &code->loc);
970 mask |= set_string (&block, &post_block, var, IOPARM_common_iomsg,
974 mask |= set_parameter_ref (&block, &post_block, var, IOPARM_common_iostat,
978 mask |= IOPARM_common_err;
981 mask |= set_string (&block, &post_block, var, IOPARM_close_status,
984 set_parameter_const (&block, var, IOPARM_common_flags, mask);
987 set_parameter_value (&block, var, IOPARM_common_unit, p->unit);
989 set_parameter_const (&block, var, IOPARM_common_unit, 0);
991 tmp = build_fold_addr_expr (var);
992 tmp = build_call_expr (iocall[IOCALL_CLOSE], 1, tmp);
993 gfc_add_expr_to_block (&block, tmp);
995 gfc_add_block_to_block (&block, &post_block);
997 io_result (&block, var, p->err, NULL, NULL);
999 return gfc_finish_block (&block);
1003 /* Common subroutine for building a file positioning statement. */
1006 build_filepos (tree function, gfc_code * code)
1008 stmtblock_t block, post_block;
1011 unsigned int mask = 0;
1013 p = code->ext.filepos;
1015 gfc_start_block (&block);
1016 gfc_init_block (&post_block);
1018 var = gfc_create_var (st_parameter[IOPARM_ptype_filepos].type,
1021 set_error_locus (&block, var, &code->loc);
1024 mask |= set_string (&block, &post_block, var, IOPARM_common_iomsg,
1028 mask |= set_parameter_ref (&block, &post_block, var, IOPARM_common_iostat,
1032 mask |= IOPARM_common_err;
1034 set_parameter_const (&block, var, IOPARM_common_flags, mask);
1037 set_parameter_value (&block, var, IOPARM_common_unit, p->unit);
1039 set_parameter_const (&block, var, IOPARM_common_unit, 0);
1041 tmp = build_fold_addr_expr (var);
1042 tmp = build_call_expr (function, 1, tmp);
1043 gfc_add_expr_to_block (&block, tmp);
1045 gfc_add_block_to_block (&block, &post_block);
1047 io_result (&block, var, p->err, NULL, NULL);
1049 return gfc_finish_block (&block);
1053 /* Translate a BACKSPACE statement. */
1056 gfc_trans_backspace (gfc_code * code)
1058 return build_filepos (iocall[IOCALL_BACKSPACE], code);
1062 /* Translate an ENDFILE statement. */
1065 gfc_trans_endfile (gfc_code * code)
1067 return build_filepos (iocall[IOCALL_ENDFILE], code);
1071 /* Translate a REWIND statement. */
1074 gfc_trans_rewind (gfc_code * code)
1076 return build_filepos (iocall[IOCALL_REWIND], code);
1080 /* Translate a FLUSH statement. */
1083 gfc_trans_flush (gfc_code * code)
1085 return build_filepos (iocall[IOCALL_FLUSH], code);
1089 /* Create a dummy iostat variable to catch any error due to bad unit. */
1092 create_dummy_iostat (void)
1097 gfc_get_ha_sym_tree ("@iostat", &st);
1098 st->n.sym->ts.type = BT_INTEGER;
1099 st->n.sym->ts.kind = gfc_default_integer_kind;
1100 gfc_set_sym_referenced (st->n.sym);
1101 gfc_commit_symbol (st->n.sym);
1102 st->n.sym->backend_decl
1103 = gfc_create_var (gfc_get_int_type (st->n.sym->ts.kind),
1106 e = gfc_get_expr ();
1107 e->expr_type = EXPR_VARIABLE;
1109 e->ts.type = BT_INTEGER;
1110 e->ts.kind = st->n.sym->ts.kind;
1116 /* Translate the non-IOLENGTH form of an INQUIRE statement. */
1119 gfc_trans_inquire (gfc_code * code)
1121 stmtblock_t block, post_block;
1124 unsigned int mask = 0;
1126 gfc_start_block (&block);
1127 gfc_init_block (&post_block);
1129 var = gfc_create_var (st_parameter[IOPARM_ptype_inquire].type,
1132 set_error_locus (&block, var, &code->loc);
1133 p = code->ext.inquire;
1136 mask |= set_string (&block, &post_block, var, IOPARM_common_iomsg,
1140 mask |= set_parameter_ref (&block, &post_block, var, IOPARM_common_iostat,
1144 mask |= IOPARM_common_err;
1147 if (p->unit && p->file)
1148 gfc_error ("INQUIRE statement at %L cannot contain both FILE and UNIT specifiers", &code->loc);
1151 mask |= set_string (&block, &post_block, var, IOPARM_inquire_file,
1156 mask |= set_parameter_ref (&block, &post_block, var, IOPARM_inquire_exist,
1159 if (p->unit && !p->iostat)
1161 p->iostat = create_dummy_iostat ();
1162 mask |= set_parameter_ref (&block, &post_block, var,
1163 IOPARM_common_iostat, p->iostat);
1168 mask |= set_parameter_ref (&block, &post_block, var, IOPARM_inquire_opened,
1172 mask |= set_parameter_ref (&block, &post_block, var, IOPARM_inquire_number,
1176 mask |= set_parameter_ref (&block, &post_block, var, IOPARM_inquire_named,
1180 mask |= set_string (&block, &post_block, var, IOPARM_inquire_name,
1184 mask |= set_string (&block, &post_block, var, IOPARM_inquire_access,
1188 mask |= set_string (&block, &post_block, var, IOPARM_inquire_sequential,
1192 mask |= set_string (&block, &post_block, var, IOPARM_inquire_direct,
1196 mask |= set_string (&block, &post_block, var, IOPARM_inquire_form,
1200 mask |= set_string (&block, &post_block, var, IOPARM_inquire_formatted,
1204 mask |= set_string (&block, &post_block, var, IOPARM_inquire_unformatted,
1208 mask |= set_parameter_ref (&block, &post_block, var,
1209 IOPARM_inquire_recl_out, p->recl);
1212 mask |= set_parameter_ref (&block, &post_block, var,
1213 IOPARM_inquire_nextrec, p->nextrec);
1216 mask |= set_string (&block, &post_block, var, IOPARM_inquire_blank,
1220 mask |= set_string (&block, &post_block, var, IOPARM_inquire_position,
1224 mask |= set_string (&block, &post_block, var, IOPARM_inquire_action,
1228 mask |= set_string (&block, &post_block, var, IOPARM_inquire_read,
1232 mask |= set_string (&block, &post_block, var, IOPARM_inquire_write,
1236 mask |= set_string (&block, &post_block, var, IOPARM_inquire_readwrite,
1240 mask |= set_string (&block, &post_block, var, IOPARM_inquire_delim,
1244 mask |= set_string (&block, &post_block, var, IOPARM_inquire_pad,
1248 mask |= set_string (&block, &post_block, var, IOPARM_inquire_convert,
1252 mask |= set_parameter_ref (&block, &post_block, var,
1253 IOPARM_inquire_strm_pos_out, p->strm_pos);
1255 set_parameter_const (&block, var, IOPARM_common_flags, mask);
1258 set_parameter_value (&block, var, IOPARM_common_unit, p->unit);
1260 set_parameter_const (&block, var, IOPARM_common_unit, 0);
1262 tmp = build_fold_addr_expr (var);
1263 tmp = build_call_expr (iocall[IOCALL_INQUIRE], 1, tmp);
1264 gfc_add_expr_to_block (&block, tmp);
1266 gfc_add_block_to_block (&block, &post_block);
1268 io_result (&block, var, p->err, NULL, NULL);
1270 return gfc_finish_block (&block);
1274 gfc_new_nml_name_expr (const char * name)
1276 gfc_expr * nml_name;
1278 nml_name = gfc_get_expr();
1279 nml_name->ref = NULL;
1280 nml_name->expr_type = EXPR_CONSTANT;
1281 nml_name->ts.kind = gfc_default_character_kind;
1282 nml_name->ts.type = BT_CHARACTER;
1283 nml_name->value.character.length = strlen(name);
1284 nml_name->value.character.string = gfc_getmem (strlen (name) + 1);
1285 strcpy (nml_name->value.character.string, name);
1290 /* nml_full_name builds up the fully qualified name of a
1291 derived type component. */
1294 nml_full_name (const char* var_name, const char* cmp_name)
1296 int full_name_length;
1299 full_name_length = strlen (var_name) + strlen (cmp_name) + 1;
1300 full_name = (char*)gfc_getmem (full_name_length + 1);
1301 strcpy (full_name, var_name);
1302 full_name = strcat (full_name, "%");
1303 full_name = strcat (full_name, cmp_name);
1307 /* nml_get_addr_expr builds an address expression from the
1308 gfc_symbol or gfc_component backend_decl's. An offset is
1309 provided so that the address of an element of an array of
1310 derived types is returned. This is used in the runtime to
1311 determine that span of the derived type. */
1314 nml_get_addr_expr (gfc_symbol * sym, gfc_component * c,
1317 tree decl = NULL_TREE;
1321 int dummy_arg_flagged;
1325 sym->attr.referenced = 1;
1326 decl = gfc_get_symbol_decl (sym);
1328 /* If this is the enclosing function declaration, use
1329 the fake result instead. */
1330 if (decl == current_function_decl)
1331 decl = gfc_get_fake_result_decl (sym, 0);
1332 else if (decl == DECL_CONTEXT (current_function_decl))
1333 decl = gfc_get_fake_result_decl (sym, 1);
1336 decl = c->backend_decl;
1338 gcc_assert (decl && ((TREE_CODE (decl) == FIELD_DECL
1339 || TREE_CODE (decl) == VAR_DECL
1340 || TREE_CODE (decl) == PARM_DECL)
1341 || TREE_CODE (decl) == COMPONENT_REF));
1345 /* Build indirect reference, if dummy argument. */
1347 dummy_arg_flagged = POINTER_TYPE_P (TREE_TYPE(tmp));
1349 itmp = (dummy_arg_flagged) ? build_fold_indirect_ref (tmp) : tmp;
1351 /* If an array, set flag and use indirect ref. if built. */
1353 array_flagged = (TREE_CODE (TREE_TYPE (itmp)) == ARRAY_TYPE
1354 && !TYPE_STRING_FLAG (TREE_TYPE (itmp)));
1359 /* Treat the component of a derived type, using base_addr for
1360 the derived type. */
1362 if (TREE_CODE (decl) == FIELD_DECL)
1363 tmp = fold_build3 (COMPONENT_REF, TREE_TYPE (tmp),
1364 base_addr, tmp, NULL_TREE);
1366 /* If we have a derived type component, a reference to the first
1367 element of the array is built. This is done so that base_addr,
1368 used in the build of the component reference, always points to
1372 tmp = gfc_build_array_ref (tmp, gfc_index_zero_node, NULL);
1374 /* Now build the address expression. */
1376 tmp = build_fold_addr_expr (tmp);
1378 /* If scalar dummy, resolve indirect reference now. */
1380 if (dummy_arg_flagged && !array_flagged)
1381 tmp = build_fold_indirect_ref (tmp);
1383 gcc_assert (tmp && POINTER_TYPE_P (TREE_TYPE (tmp)));
1388 /* For an object VAR_NAME whose base address is BASE_ADDR, generate a
1389 call to iocall[IOCALL_SET_NML_VAL]. For derived type variable, recursively
1390 generate calls to iocall[IOCALL_SET_NML_VAL] for each component. */
1392 #define IARG(i) build_int_cst (gfc_array_index_type, i)
1395 transfer_namelist_element (stmtblock_t * block, const char * var_name,
1396 gfc_symbol * sym, gfc_component * c,
1399 gfc_typespec * ts = NULL;
1400 gfc_array_spec * as = NULL;
1401 tree addr_expr = NULL;
1411 gcc_assert (sym || c);
1413 /* Build the namelist object name. */
1415 string = gfc_build_cstring_const (var_name);
1416 string = gfc_build_addr_expr (pchar_type_node, string);
1418 /* Build ts, as and data address using symbol or component. */
1420 ts = (sym) ? &sym->ts : &c->ts;
1421 as = (sym) ? sym->as : c->as;
1423 addr_expr = nml_get_addr_expr (sym, c, base_addr);
1430 dt = TREE_TYPE ((sym) ? sym->backend_decl : c->backend_decl);
1431 dtype = gfc_get_dtype (dt);
1435 itype = GFC_DTYPE_UNKNOWN;
1441 itype = GFC_DTYPE_INTEGER;
1444 itype = GFC_DTYPE_LOGICAL;
1447 itype = GFC_DTYPE_REAL;
1450 itype = GFC_DTYPE_COMPLEX;
1453 itype = GFC_DTYPE_DERIVED;
1456 itype = GFC_DTYPE_CHARACTER;
1462 dtype = IARG (itype << GFC_DTYPE_TYPE_SHIFT);
1465 /* Build up the arguments for the transfer call.
1466 The call for the scalar part transfers:
1467 (address, name, type, kind or string_length, dtype) */
1469 dt_parm_addr = build_fold_addr_expr (dt_parm);
1471 if (ts->type == BT_CHARACTER)
1472 tmp = ts->cl->backend_decl;
1474 tmp = build_int_cst (gfc_charlen_type_node, 0);
1475 tmp = build_call_expr (iocall[IOCALL_SET_NML_VAL], 6,
1476 dt_parm_addr, addr_expr, string,
1477 IARG (ts->kind), tmp, dtype);
1478 gfc_add_expr_to_block (block, tmp);
1480 /* If the object is an array, transfer rank times:
1481 (null pointer, name, stride, lbound, ubound) */
1483 for ( n_dim = 0 ; n_dim < rank ; n_dim++ )
1485 tmp = build_call_expr (iocall[IOCALL_SET_NML_VAL_DIM], 5,
1488 GFC_TYPE_ARRAY_STRIDE (dt, n_dim),
1489 GFC_TYPE_ARRAY_LBOUND (dt, n_dim),
1490 GFC_TYPE_ARRAY_UBOUND (dt, n_dim));
1491 gfc_add_expr_to_block (block, tmp);
1494 if (ts->type == BT_DERIVED)
1498 /* Provide the RECORD_TYPE to build component references. */
1500 tree expr = build_fold_indirect_ref (addr_expr);
1502 for (cmp = ts->derived->components; cmp; cmp = cmp->next)
1504 char *full_name = nml_full_name (var_name, cmp->name);
1505 transfer_namelist_element (block,
1508 gfc_free (full_name);
1515 /* Create a data transfer statement. Not all of the fields are valid
1516 for both reading and writing, but improper use has been filtered
1520 build_dt (tree function, gfc_code * code)
1522 stmtblock_t block, post_block, post_end_block, post_iu_block;
1527 unsigned int mask = 0;
1529 gfc_start_block (&block);
1530 gfc_init_block (&post_block);
1531 gfc_init_block (&post_end_block);
1532 gfc_init_block (&post_iu_block);
1534 var = gfc_create_var (st_parameter[IOPARM_ptype_dt].type, "dt_parm");
1536 set_error_locus (&block, var, &code->loc);
1538 if (last_dt == IOLENGTH)
1542 inq = code->ext.inquire;
1544 /* First check that preconditions are met. */
1545 gcc_assert (inq != NULL);
1546 gcc_assert (inq->iolength != NULL);
1548 /* Connect to the iolength variable. */
1549 mask |= set_parameter_ref (&block, &post_end_block, var,
1550 IOPARM_dt_iolength, inq->iolength);
1556 gcc_assert (dt != NULL);
1559 if (dt && dt->io_unit)
1561 if (dt->io_unit->ts.type == BT_CHARACTER)
1563 mask |= set_internal_unit (&block, &post_iu_block,
1565 set_parameter_const (&block, var, IOPARM_common_unit, 0);
1569 set_parameter_const (&block, var, IOPARM_common_unit, 0);
1574 mask |= set_string (&block, &post_block, var, IOPARM_common_iomsg,
1578 mask |= set_parameter_ref (&block, &post_end_block, var,
1579 IOPARM_common_iostat, dt->iostat);
1582 mask |= IOPARM_common_err;
1585 mask |= IOPARM_common_eor;
1588 mask |= IOPARM_common_end;
1591 mask |= set_parameter_value (&block, var, IOPARM_dt_rec, dt->rec);
1594 mask |= set_string (&block, &post_block, var, IOPARM_dt_advance,
1597 if (dt->format_expr)
1598 mask |= set_string (&block, &post_end_block, var, IOPARM_dt_format,
1601 if (dt->format_label)
1603 if (dt->format_label == &format_asterisk)
1604 mask |= IOPARM_dt_list_format;
1606 mask |= set_string (&block, &post_block, var, IOPARM_dt_format,
1607 dt->format_label->format);
1611 mask |= set_parameter_ref (&block, &post_end_block, var,
1612 IOPARM_dt_size, dt->size);
1616 if (dt->format_expr || dt->format_label)
1617 gfc_internal_error ("build_dt: format with namelist");
1619 nmlname = gfc_new_nml_name_expr (dt->namelist->name);
1621 mask |= set_string (&block, &post_block, var, IOPARM_dt_namelist_name,
1624 if (last_dt == READ)
1625 mask |= IOPARM_dt_namelist_read_mode;
1627 set_parameter_const (&block, var, IOPARM_common_flags, mask);
1631 for (nml = dt->namelist->namelist; nml; nml = nml->next)
1632 transfer_namelist_element (&block, nml->sym->name, nml->sym,
1636 set_parameter_const (&block, var, IOPARM_common_flags, mask);
1638 if (dt->io_unit && dt->io_unit->ts.type == BT_INTEGER)
1639 set_parameter_value (&block, var, IOPARM_common_unit, dt->io_unit);
1642 set_parameter_const (&block, var, IOPARM_common_flags, mask);
1644 tmp = build_fold_addr_expr (var);
1645 tmp = build_call_expr (function, 1, tmp);
1646 gfc_add_expr_to_block (&block, tmp);
1648 gfc_add_block_to_block (&block, &post_block);
1651 dt_post_end_block = &post_end_block;
1653 gfc_add_expr_to_block (&block, gfc_trans_code (code->block->next));
1655 gfc_add_block_to_block (&block, &post_iu_block);
1658 dt_post_end_block = NULL;
1660 return gfc_finish_block (&block);
1664 /* Translate the IOLENGTH form of an INQUIRE statement. We treat
1665 this as a third sort of data transfer statement, except that
1666 lengths are summed instead of actually transferring any data. */
1669 gfc_trans_iolength (gfc_code * code)
1672 return build_dt (iocall[IOCALL_IOLENGTH], code);
1676 /* Translate a READ statement. */
1679 gfc_trans_read (gfc_code * code)
1682 return build_dt (iocall[IOCALL_READ], code);
1686 /* Translate a WRITE statement */
1689 gfc_trans_write (gfc_code * code)
1692 return build_dt (iocall[IOCALL_WRITE], code);
1696 /* Finish a data transfer statement. */
1699 gfc_trans_dt_end (gfc_code * code)
1704 gfc_init_block (&block);
1709 function = iocall[IOCALL_READ_DONE];
1713 function = iocall[IOCALL_WRITE_DONE];
1717 function = iocall[IOCALL_IOLENGTH_DONE];
1724 tmp = build_fold_addr_expr (dt_parm);
1725 tmp = build_call_expr (function, 1, tmp);
1726 gfc_add_expr_to_block (&block, tmp);
1727 gfc_add_block_to_block (&block, dt_post_end_block);
1728 gfc_init_block (dt_post_end_block);
1730 if (last_dt != IOLENGTH)
1732 gcc_assert (code->ext.dt != NULL);
1733 io_result (&block, dt_parm, code->ext.dt->err,
1734 code->ext.dt->end, code->ext.dt->eor);
1737 return gfc_finish_block (&block);
1741 transfer_expr (gfc_se * se, gfc_typespec * ts, tree addr_expr, gfc_code * code);
1743 /* Given an array field in a derived type variable, generate the code
1744 for the loop that iterates over array elements, and the code that
1745 accesses those array elements. Use transfer_expr to generate code
1746 for transferring that element. Because elements may also be
1747 derived types, transfer_expr and transfer_array_component are mutually
1751 transfer_array_component (tree expr, gfc_component * cm)
1761 gfc_start_block (&block);
1762 gfc_init_se (&se, NULL);
1764 /* Create and initialize Scalarization Status. Unlike in
1765 gfc_trans_transfer, we can't simply use gfc_walk_expr to take
1766 care of this task, because we don't have a gfc_expr at hand.
1767 Build one manually, as in gfc_trans_subarray_assign. */
1770 ss->type = GFC_SS_COMPONENT;
1772 ss->shape = gfc_get_shape (cm->as->rank);
1773 ss->next = gfc_ss_terminator;
1774 ss->data.info.dimen = cm->as->rank;
1775 ss->data.info.descriptor = expr;
1776 ss->data.info.data = gfc_conv_array_data (expr);
1777 ss->data.info.offset = gfc_conv_array_offset (expr);
1778 for (n = 0; n < cm->as->rank; n++)
1780 ss->data.info.dim[n] = n;
1781 ss->data.info.start[n] = gfc_conv_array_lbound (expr, n);
1782 ss->data.info.stride[n] = gfc_index_one_node;
1784 mpz_init (ss->shape[n]);
1785 mpz_sub (ss->shape[n], cm->as->upper[n]->value.integer,
1786 cm->as->lower[n]->value.integer);
1787 mpz_add_ui (ss->shape[n], ss->shape[n], 1);
1790 /* Once we got ss, we use scalarizer to create the loop. */
1792 gfc_init_loopinfo (&loop);
1793 gfc_add_ss_to_loop (&loop, ss);
1794 gfc_conv_ss_startstride (&loop);
1795 gfc_conv_loop_setup (&loop);
1796 gfc_mark_ss_chain_used (ss, 1);
1797 gfc_start_scalarized_body (&loop, &body);
1799 gfc_copy_loopinfo_to_se (&se, &loop);
1802 /* gfc_conv_tmp_array_ref assumes that se.expr contains the array. */
1804 gfc_conv_tmp_array_ref (&se);
1806 /* Now se.expr contains an element of the array. Take the address and pass
1807 it to the IO routines. */
1808 tmp = build_fold_addr_expr (se.expr);
1809 transfer_expr (&se, &cm->ts, tmp, NULL);
1811 /* We are done now with the loop body. Wrap up the scalarizer and
1814 gfc_add_block_to_block (&body, &se.pre);
1815 gfc_add_block_to_block (&body, &se.post);
1817 gfc_trans_scalarizing_loops (&loop, &body);
1819 gfc_add_block_to_block (&block, &loop.pre);
1820 gfc_add_block_to_block (&block, &loop.post);
1822 for (n = 0; n < cm->as->rank; n++)
1823 mpz_clear (ss->shape[n]);
1824 gfc_free (ss->shape);
1826 gfc_cleanup_loop (&loop);
1828 return gfc_finish_block (&block);
1831 /* Generate the call for a scalar transfer node. */
1834 transfer_expr (gfc_se * se, gfc_typespec * ts, tree addr_expr, gfc_code * code)
1836 tree tmp, function, arg2, field, expr;
1840 /* It is possible to get a C_NULL_PTR or C_NULL_FUNPTR expression here if
1841 the user says something like: print *, 'c_null_ptr: ', c_null_ptr
1842 We need to translate the expression to a constant if it's either
1843 C_NULL_PTR or C_NULL_FUNPTR. We could also get a user variable of
1844 type C_PTR or C_FUNPTR, in which case the ts->type may no longer be
1845 BT_DERIVED (could have been changed by gfc_conv_expr). */
1846 if ((ts->type == BT_DERIVED && ts->is_iso_c == 1 && ts->derived != NULL)
1847 || (ts->derived != NULL && ts->derived->ts.is_iso_c == 1))
1849 /* C_PTR and C_FUNPTR have private components which means they can not
1850 be printed. However, if -std=gnu and not -pedantic, allow
1851 the component to be printed to help debugging. */
1852 if (gfc_notification_std (GFC_STD_GNU) != SILENT)
1854 gfc_error_now ("Derived type '%s' at %L has PRIVATE components",
1855 ts->derived->name, code != NULL ? &(code->loc) :
1856 &gfc_current_locus);
1860 ts->type = ts->derived->ts.type;
1861 ts->kind = ts->derived->ts.kind;
1862 ts->f90_type = ts->derived->ts.f90_type;
1872 arg2 = build_int_cst (NULL_TREE, kind);
1873 function = iocall[IOCALL_X_INTEGER];
1877 arg2 = build_int_cst (NULL_TREE, kind);
1878 function = iocall[IOCALL_X_REAL];
1882 arg2 = build_int_cst (NULL_TREE, kind);
1883 function = iocall[IOCALL_X_COMPLEX];
1887 arg2 = build_int_cst (NULL_TREE, kind);
1888 function = iocall[IOCALL_X_LOGICAL];
1893 if (se->string_length)
1894 arg2 = se->string_length;
1897 tmp = build_fold_indirect_ref (addr_expr);
1898 gcc_assert (TREE_CODE (TREE_TYPE (tmp)) == ARRAY_TYPE);
1899 arg2 = TYPE_MAX_VALUE (TYPE_DOMAIN (TREE_TYPE (tmp)));
1901 function = iocall[IOCALL_X_CHARACTER];
1905 /* Recurse into the elements of the derived type. */
1906 expr = gfc_evaluate_now (addr_expr, &se->pre);
1907 expr = build_fold_indirect_ref (expr);
1909 for (c = ts->derived->components; c; c = c->next)
1911 field = c->backend_decl;
1912 gcc_assert (field && TREE_CODE (field) == FIELD_DECL);
1914 tmp = fold_build3 (COMPONENT_REF, TREE_TYPE (field),
1915 expr, field, NULL_TREE);
1919 tmp = transfer_array_component (tmp, c);
1920 gfc_add_expr_to_block (&se->pre, tmp);
1925 tmp = build_fold_addr_expr (tmp);
1926 transfer_expr (se, &c->ts, tmp, code);
1932 internal_error ("Bad IO basetype (%d)", ts->type);
1935 tmp = build_fold_addr_expr (dt_parm);
1936 tmp = build_call_expr (function, 3, tmp, addr_expr, arg2);
1937 gfc_add_expr_to_block (&se->pre, tmp);
1938 gfc_add_block_to_block (&se->pre, &se->post);
1943 /* Generate a call to pass an array descriptor to the IO library. The
1944 array should be of one of the intrinsic types. */
1947 transfer_array_desc (gfc_se * se, gfc_typespec * ts, tree addr_expr)
1949 tree tmp, charlen_arg, kind_arg;
1951 if (ts->type == BT_CHARACTER)
1952 charlen_arg = se->string_length;
1954 charlen_arg = build_int_cst (NULL_TREE, 0);
1956 kind_arg = build_int_cst (NULL_TREE, ts->kind);
1958 tmp = build_fold_addr_expr (dt_parm);
1959 tmp = build_call_expr (iocall[IOCALL_X_ARRAY], 4,
1960 tmp, addr_expr, kind_arg, charlen_arg);
1961 gfc_add_expr_to_block (&se->pre, tmp);
1962 gfc_add_block_to_block (&se->pre, &se->post);
1966 /* gfc_trans_transfer()-- Translate a TRANSFER code node */
1969 gfc_trans_transfer (gfc_code * code)
1971 stmtblock_t block, body;
1980 gfc_start_block (&block);
1981 gfc_init_block (&body);
1984 ss = gfc_walk_expr (expr);
1987 gfc_init_se (&se, NULL);
1989 if (ss == gfc_ss_terminator)
1991 /* Transfer a scalar value. */
1992 gfc_conv_expr_reference (&se, expr);
1993 transfer_expr (&se, &expr->ts, se.expr, code);
1997 /* Transfer an array. If it is an array of an intrinsic
1998 type, pass the descriptor to the library. Otherwise
1999 scalarize the transfer. */
2002 for (ref = expr->ref; ref && ref->type != REF_ARRAY;
2004 gcc_assert (ref->type == REF_ARRAY);
2007 if (expr->ts.type != BT_DERIVED
2008 && ref && ref->next == NULL
2009 && !is_subref_array (expr))
2011 bool seen_vector = false;
2013 if (ref && ref->u.ar.type == AR_SECTION)
2015 for (n = 0; n < ref->u.ar.dimen; n++)
2016 if (ref->u.ar.dimen_type[n] == DIMEN_VECTOR)
2020 if (seen_vector && last_dt == READ)
2022 /* Create a temp, read to that and copy it back. */
2023 gfc_conv_subref_array_arg (&se, expr, 0, INTENT_OUT);
2028 /* Get the descriptor. */
2029 gfc_conv_expr_descriptor (&se, expr, ss);
2030 tmp = build_fold_addr_expr (se.expr);
2033 transfer_array_desc (&se, &expr->ts, tmp);
2034 goto finish_block_label;
2037 /* Initialize the scalarizer. */
2038 gfc_init_loopinfo (&loop);
2039 gfc_add_ss_to_loop (&loop, ss);
2041 /* Initialize the loop. */
2042 gfc_conv_ss_startstride (&loop);
2043 gfc_conv_loop_setup (&loop);
2045 /* The main loop body. */
2046 gfc_mark_ss_chain_used (ss, 1);
2047 gfc_start_scalarized_body (&loop, &body);
2049 gfc_copy_loopinfo_to_se (&se, &loop);
2052 gfc_conv_expr_reference (&se, expr);
2053 transfer_expr (&se, &expr->ts, se.expr, code);
2058 gfc_add_block_to_block (&body, &se.pre);
2059 gfc_add_block_to_block (&body, &se.post);
2062 tmp = gfc_finish_block (&body);
2065 gcc_assert (se.ss == gfc_ss_terminator);
2066 gfc_trans_scalarizing_loops (&loop, &body);
2068 gfc_add_block_to_block (&loop.pre, &loop.post);
2069 tmp = gfc_finish_block (&loop.pre);
2070 gfc_cleanup_loop (&loop);
2073 gfc_add_expr_to_block (&block, tmp);
2075 return gfc_finish_block (&block);
2078 #include "gt-fortran-trans-io.h"