1 /* IO Code translation/library interface
2 Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008
3 Free Software Foundation, Inc.
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"
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. */
67 typedef struct gfc_st_parameter_field
GTY(())
71 enum ioparam_type param_type
;
72 enum iofield_type type
;
76 gfc_st_parameter_field
;
78 typedef struct gfc_st_parameter
GTY(())
87 #define IOPARM(param_type, name, mask, type) IOPARM_##param_type##_##name,
93 static GTY(()) gfc_st_parameter st_parameter
[] =
104 static GTY(()) gfc_st_parameter_field st_parameter_field
[] =
106 #define IOPARM(param_type, name, mask, type) \
107 { #name, mask, IOPARM_ptype_##param_type, IOPARM_type_##type, NULL, NULL },
108 #include "ioparm.def"
110 { NULL
, 0, 0, 0, NULL
, NULL
}
113 /* Library I/O subroutines */
124 IOCALL_X_CHARACTER_WIDE
,
132 IOCALL_IOLENGTH_DONE
,
138 IOCALL_SET_NML_VAL_DIM
,
143 static GTY(()) tree iocall
[IOCALL_NUM
];
145 /* Variable for keeping track of what the last data transfer statement
146 was. Used for deciding which subroutine to call when the data
147 transfer is complete. */
148 static enum { READ
, WRITE
, IOLENGTH
} last_dt
;
150 /* The data transfer parameter block that should be shared by all
151 data transfer calls belonging to the same read/write/iolength. */
152 static GTY(()) tree dt_parm
;
153 static stmtblock_t
*dt_post_end_block
;
156 gfc_build_st_parameter (enum ioparam_type ptype
, tree
*types
)
159 gfc_st_parameter_field
*p
;
162 tree t
= make_node (RECORD_TYPE
);
164 len
= strlen (st_parameter
[ptype
].name
);
165 gcc_assert (len
<= sizeof (name
) - sizeof ("__st_parameter_"));
166 memcpy (name
, "__st_parameter_", sizeof ("__st_parameter_"));
167 memcpy (name
+ sizeof ("__st_parameter_") - 1, st_parameter
[ptype
].name
,
169 TYPE_NAME (t
) = get_identifier (name
);
171 for (type
= 0, p
= st_parameter_field
; type
< IOPARM_field_num
; type
++, p
++)
172 if (p
->param_type
== ptype
)
175 case IOPARM_type_int4
:
176 case IOPARM_type_intio
:
177 case IOPARM_type_pint4
:
178 case IOPARM_type_pintio
:
179 case IOPARM_type_parray
:
180 case IOPARM_type_pchar
:
181 case IOPARM_type_pad
:
182 p
->field
= gfc_add_field_to_struct (&TYPE_FIELDS (t
), t
,
183 get_identifier (p
->name
),
186 case IOPARM_type_char1
:
187 p
->field
= gfc_add_field_to_struct (&TYPE_FIELDS (t
), t
,
188 get_identifier (p
->name
),
191 case IOPARM_type_char2
:
192 len
= strlen (p
->name
);
193 gcc_assert (len
<= sizeof (name
) - sizeof ("_len"));
194 memcpy (name
, p
->name
, len
);
195 memcpy (name
+ len
, "_len", sizeof ("_len"));
196 p
->field_len
= gfc_add_field_to_struct (&TYPE_FIELDS (t
), t
,
197 get_identifier (name
),
198 gfc_charlen_type_node
);
199 if (p
->type
== IOPARM_type_char2
)
200 p
->field
= gfc_add_field_to_struct (&TYPE_FIELDS (t
), t
,
201 get_identifier (p
->name
),
204 case IOPARM_type_common
:
206 = gfc_add_field_to_struct (&TYPE_FIELDS (t
), t
,
207 get_identifier (p
->name
),
208 st_parameter
[IOPARM_ptype_common
].type
);
210 case IOPARM_type_num
:
215 st_parameter
[ptype
].type
= t
;
219 /* Build code to test an error condition and call generate_error if needed.
220 Note: This builds calls to generate_error in the runtime library function.
221 The function generate_error is dependent on certain parameters in the
222 st_parameter_common flags to be set. (See libgfortran/runtime/error.c)
223 Therefore, the code to set these flags must be generated before
224 this function is used. */
227 gfc_trans_io_runtime_check (tree cond
, tree var
, int error_code
,
228 const char * msgid
, stmtblock_t
* pblock
)
233 tree arg1
, arg2
, arg3
;
236 if (integer_zerop (cond
))
239 /* The code to generate the error. */
240 gfc_start_block (&block
);
242 arg1
= build_fold_addr_expr (var
);
244 arg2
= build_int_cst (integer_type_node
, error_code
),
246 asprintf (&message
, "%s", _(msgid
));
247 arg3
= gfc_build_addr_expr (pchar_type_node
,
248 gfc_build_localized_cstring_const (message
));
251 tmp
= build_call_expr (gfor_fndecl_generate_error
, 3, arg1
, arg2
, arg3
);
253 gfc_add_expr_to_block (&block
, tmp
);
255 body
= gfc_finish_block (&block
);
257 if (integer_onep (cond
))
259 gfc_add_expr_to_block (pblock
, body
);
263 /* Tell the compiler that this isn't likely. */
264 cond
= fold_convert (long_integer_type_node
, cond
);
265 tmp
= build_int_cst (long_integer_type_node
, 0);
266 cond
= build_call_expr (built_in_decls
[BUILT_IN_EXPECT
], 2, cond
, tmp
);
267 cond
= fold_convert (boolean_type_node
, cond
);
269 tmp
= build3_v (COND_EXPR
, cond
, body
, build_empty_stmt ());
270 gfc_add_expr_to_block (pblock
, tmp
);
275 /* Create function decls for IO library functions. */
278 gfc_build_io_library_fndecls (void)
280 tree types
[IOPARM_type_num
], pad_idx
, gfc_int4_type_node
;
281 tree gfc_intio_type_node
;
282 tree parm_type
, dt_parm_type
;
283 HOST_WIDE_INT pad_size
;
284 enum ioparam_type ptype
;
286 types
[IOPARM_type_int4
] = gfc_int4_type_node
= gfc_get_int_type (4);
287 types
[IOPARM_type_intio
] = gfc_intio_type_node
288 = gfc_get_int_type (gfc_intio_kind
);
289 types
[IOPARM_type_pint4
] = build_pointer_type (gfc_int4_type_node
);
290 types
[IOPARM_type_pintio
]
291 = build_pointer_type (gfc_intio_type_node
);
292 types
[IOPARM_type_parray
] = pchar_type_node
;
293 types
[IOPARM_type_pchar
] = pchar_type_node
;
294 pad_size
= 32 * TREE_INT_CST_LOW (TYPE_SIZE_UNIT (pchar_type_node
));
295 pad_size
+= 32 * TREE_INT_CST_LOW (TYPE_SIZE_UNIT (integer_type_node
));
296 pad_idx
= build_index_type (build_int_cst (NULL_TREE
, pad_size
));
297 types
[IOPARM_type_pad
] = build_array_type (char_type_node
, pad_idx
);
299 /* pad actually contains pointers and integers so it needs to have an
300 alignment that is at least as large as the needed alignment for those
301 types. See the st_parameter_dt structure in libgfortran/io/io.h for
302 what really goes into this space. */
303 TYPE_ALIGN (types
[IOPARM_type_pad
]) = MAX (TYPE_ALIGN (pchar_type_node
),
304 TYPE_ALIGN (gfc_get_int_type (gfc_max_integer_kind
)));
306 for (ptype
= IOPARM_ptype_common
; ptype
< IOPARM_ptype_num
; ptype
++)
307 gfc_build_st_parameter (ptype
, types
);
309 /* Define the transfer functions. */
311 dt_parm_type
= build_pointer_type (st_parameter
[IOPARM_ptype_dt
].type
);
313 iocall
[IOCALL_X_INTEGER
] =
314 gfc_build_library_function_decl (get_identifier
315 (PREFIX("transfer_integer")),
316 void_type_node
, 3, dt_parm_type
,
317 pvoid_type_node
, gfc_int4_type_node
);
319 iocall
[IOCALL_X_LOGICAL
] =
320 gfc_build_library_function_decl (get_identifier
321 (PREFIX("transfer_logical")),
322 void_type_node
, 3, dt_parm_type
,
323 pvoid_type_node
, gfc_int4_type_node
);
325 iocall
[IOCALL_X_CHARACTER
] =
326 gfc_build_library_function_decl (get_identifier
327 (PREFIX("transfer_character")),
328 void_type_node
, 3, dt_parm_type
,
329 pvoid_type_node
, gfc_int4_type_node
);
331 iocall
[IOCALL_X_CHARACTER_WIDE
] =
332 gfc_build_library_function_decl (get_identifier
333 (PREFIX("transfer_character_wide")),
334 void_type_node
, 4, dt_parm_type
,
335 pvoid_type_node
, gfc_charlen_type_node
,
338 iocall
[IOCALL_X_REAL
] =
339 gfc_build_library_function_decl (get_identifier (PREFIX("transfer_real")),
340 void_type_node
, 3, dt_parm_type
,
341 pvoid_type_node
, gfc_int4_type_node
);
343 iocall
[IOCALL_X_COMPLEX
] =
344 gfc_build_library_function_decl (get_identifier
345 (PREFIX("transfer_complex")),
346 void_type_node
, 3, dt_parm_type
,
347 pvoid_type_node
, gfc_int4_type_node
);
349 iocall
[IOCALL_X_ARRAY
] =
350 gfc_build_library_function_decl (get_identifier
351 (PREFIX("transfer_array")),
352 void_type_node
, 4, dt_parm_type
,
353 pvoid_type_node
, integer_type_node
,
354 gfc_charlen_type_node
);
356 /* Library entry points */
358 iocall
[IOCALL_READ
] =
359 gfc_build_library_function_decl (get_identifier (PREFIX("st_read")),
360 void_type_node
, 1, dt_parm_type
);
362 iocall
[IOCALL_WRITE
] =
363 gfc_build_library_function_decl (get_identifier (PREFIX("st_write")),
364 void_type_node
, 1, dt_parm_type
);
366 parm_type
= build_pointer_type (st_parameter
[IOPARM_ptype_open
].type
);
367 iocall
[IOCALL_OPEN
] =
368 gfc_build_library_function_decl (get_identifier (PREFIX("st_open")),
369 void_type_node
, 1, parm_type
);
372 parm_type
= build_pointer_type (st_parameter
[IOPARM_ptype_close
].type
);
373 iocall
[IOCALL_CLOSE
] =
374 gfc_build_library_function_decl (get_identifier (PREFIX("st_close")),
375 void_type_node
, 1, parm_type
);
377 parm_type
= build_pointer_type (st_parameter
[IOPARM_ptype_inquire
].type
);
378 iocall
[IOCALL_INQUIRE
] =
379 gfc_build_library_function_decl (get_identifier (PREFIX("st_inquire")),
380 gfc_int4_type_node
, 1, parm_type
);
382 iocall
[IOCALL_IOLENGTH
] =
383 gfc_build_library_function_decl(get_identifier (PREFIX("st_iolength")),
384 void_type_node
, 1, dt_parm_type
);
386 parm_type
= build_pointer_type (st_parameter
[IOPARM_ptype_wait
].type
);
387 iocall
[IOCALL_WAIT
] =
388 gfc_build_library_function_decl (get_identifier (PREFIX("st_wait")),
389 gfc_int4_type_node
, 1, parm_type
);
391 parm_type
= build_pointer_type (st_parameter
[IOPARM_ptype_filepos
].type
);
392 iocall
[IOCALL_REWIND
] =
393 gfc_build_library_function_decl (get_identifier (PREFIX("st_rewind")),
394 gfc_int4_type_node
, 1, parm_type
);
396 iocall
[IOCALL_BACKSPACE
] =
397 gfc_build_library_function_decl (get_identifier (PREFIX("st_backspace")),
398 gfc_int4_type_node
, 1, parm_type
);
400 iocall
[IOCALL_ENDFILE
] =
401 gfc_build_library_function_decl (get_identifier (PREFIX("st_endfile")),
402 gfc_int4_type_node
, 1, parm_type
);
404 iocall
[IOCALL_FLUSH
] =
405 gfc_build_library_function_decl (get_identifier (PREFIX("st_flush")),
406 gfc_int4_type_node
, 1, parm_type
);
408 /* Library helpers */
410 iocall
[IOCALL_READ_DONE
] =
411 gfc_build_library_function_decl (get_identifier (PREFIX("st_read_done")),
412 gfc_int4_type_node
, 1, dt_parm_type
);
414 iocall
[IOCALL_WRITE_DONE
] =
415 gfc_build_library_function_decl (get_identifier (PREFIX("st_write_done")),
416 gfc_int4_type_node
, 1, dt_parm_type
);
418 iocall
[IOCALL_IOLENGTH_DONE
] =
419 gfc_build_library_function_decl (get_identifier (PREFIX("st_iolength_done")),
420 gfc_int4_type_node
, 1, dt_parm_type
);
423 iocall
[IOCALL_SET_NML_VAL
] =
424 gfc_build_library_function_decl (get_identifier (PREFIX("st_set_nml_var")),
425 void_type_node
, 6, dt_parm_type
,
426 pvoid_type_node
, pvoid_type_node
,
427 gfc_int4_type_node
, gfc_charlen_type_node
,
430 iocall
[IOCALL_SET_NML_VAL_DIM
] =
431 gfc_build_library_function_decl (get_identifier (PREFIX("st_set_nml_var_dim")),
432 void_type_node
, 5, dt_parm_type
,
433 gfc_int4_type_node
, gfc_array_index_type
,
434 gfc_array_index_type
, gfc_array_index_type
);
438 /* Generate code to store an integer constant into the
439 st_parameter_XXX structure. */
442 set_parameter_const (stmtblock_t
*block
, tree var
, enum iofield type
,
446 gfc_st_parameter_field
*p
= &st_parameter_field
[type
];
448 if (p
->param_type
== IOPARM_ptype_common
)
449 var
= fold_build3 (COMPONENT_REF
, st_parameter
[IOPARM_ptype_common
].type
,
450 var
, TYPE_FIELDS (TREE_TYPE (var
)), NULL_TREE
);
451 tmp
= fold_build3 (COMPONENT_REF
, TREE_TYPE (p
->field
), var
, p
->field
,
453 gfc_add_modify (block
, tmp
, build_int_cst (TREE_TYPE (p
->field
), val
));
458 /* Generate code to store a non-string I/O parameter into the
459 st_parameter_XXX structure. This is a pass by value. */
462 set_parameter_value (stmtblock_t
*block
, tree var
, enum iofield type
,
467 gfc_st_parameter_field
*p
= &st_parameter_field
[type
];
468 tree dest_type
= TREE_TYPE (p
->field
);
470 gfc_init_se (&se
, NULL
);
471 gfc_conv_expr_val (&se
, e
);
473 /* If we're storing a UNIT number, we need to check it first. */
474 if (type
== IOPARM_common_unit
&& e
->ts
.kind
!= 4)
479 /* Don't evaluate the UNIT number multiple times. */
480 se
.expr
= gfc_evaluate_now (se
.expr
, &se
.pre
);
482 /* UNIT numbers should be nonnegative. */
483 cond
= fold_build2 (LT_EXPR
, boolean_type_node
, se
.expr
,
484 build_int_cst (TREE_TYPE (se
.expr
),0));
485 gfc_trans_io_runtime_check (cond
, var
, LIBERROR_BAD_UNIT
,
486 "Negative unit number in I/O statement",
489 /* UNIT numbers should be less than the max. */
490 i
= gfc_validate_kind (BT_INTEGER
, 4, false);
491 max
= gfc_conv_mpz_to_tree (gfc_integer_kinds
[i
].huge
, 4);
492 cond
= fold_build2 (GT_EXPR
, boolean_type_node
, se
.expr
,
493 fold_convert (TREE_TYPE (se
.expr
), max
));
494 gfc_trans_io_runtime_check (cond
, var
, LIBERROR_BAD_UNIT
,
495 "Unit number in I/O statement too large",
500 se
.expr
= convert (dest_type
, se
.expr
);
501 gfc_add_block_to_block (block
, &se
.pre
);
503 if (p
->param_type
== IOPARM_ptype_common
)
504 var
= fold_build3 (COMPONENT_REF
, st_parameter
[IOPARM_ptype_common
].type
,
505 var
, TYPE_FIELDS (TREE_TYPE (var
)), NULL_TREE
);
507 tmp
= fold_build3 (COMPONENT_REF
, dest_type
, var
, p
->field
, NULL_TREE
);
508 gfc_add_modify (block
, tmp
, se
.expr
);
513 /* Generate code to store a non-string I/O parameter into the
514 st_parameter_XXX structure. This is pass by reference. */
517 set_parameter_ref (stmtblock_t
*block
, stmtblock_t
*postblock
,
518 tree var
, enum iofield type
, gfc_expr
*e
)
522 gfc_st_parameter_field
*p
= &st_parameter_field
[type
];
524 gcc_assert (e
->ts
.type
== BT_INTEGER
|| e
->ts
.type
== BT_LOGICAL
);
525 gfc_init_se (&se
, NULL
);
526 gfc_conv_expr_lhs (&se
, e
);
528 gfc_add_block_to_block (block
, &se
.pre
);
530 if (TYPE_MODE (TREE_TYPE (se
.expr
))
531 == TYPE_MODE (TREE_TYPE (TREE_TYPE (p
->field
))))
533 addr
= convert (TREE_TYPE (p
->field
), build_fold_addr_expr (se
.expr
));
535 /* If this is for the iostat variable initialize the
536 user variable to LIBERROR_OK which is zero. */
537 if (type
== IOPARM_common_iostat
)
538 gfc_add_modify (block
, se
.expr
,
539 build_int_cst (TREE_TYPE (se
.expr
), LIBERROR_OK
));
543 /* The type used by the library has different size
544 from the type of the variable supplied by the user.
545 Need to use a temporary. */
546 tree tmpvar
= gfc_create_var (TREE_TYPE (TREE_TYPE (p
->field
)),
547 st_parameter_field
[type
].name
);
549 /* If this is for the iostat variable, initialize the
550 user variable to LIBERROR_OK which is zero. */
551 if (type
== IOPARM_common_iostat
)
552 gfc_add_modify (block
, tmpvar
,
553 build_int_cst (TREE_TYPE (tmpvar
), LIBERROR_OK
));
555 addr
= build_fold_addr_expr (tmpvar
);
556 /* After the I/O operation, we set the variable from the temporary. */
557 tmp
= convert (TREE_TYPE (se
.expr
), tmpvar
);
558 gfc_add_modify (postblock
, se
.expr
, tmp
);
561 if (p
->param_type
== IOPARM_ptype_common
)
562 var
= fold_build3 (COMPONENT_REF
, st_parameter
[IOPARM_ptype_common
].type
,
563 var
, TYPE_FIELDS (TREE_TYPE (var
)), NULL_TREE
);
564 tmp
= fold_build3 (COMPONENT_REF
, TREE_TYPE (p
->field
),
565 var
, p
->field
, NULL_TREE
);
566 gfc_add_modify (block
, tmp
, addr
);
570 /* Given an array expr, find its address and length to get a string. If the
571 array is full, the string's address is the address of array's first element
572 and the length is the size of the whole array. If it is an element, the
573 string's address is the element's address and the length is the rest size of
578 gfc_convert_array_to_string (gfc_se
* se
, gfc_expr
* e
)
587 sym
= e
->symtree
->n
.sym
;
588 rank
= sym
->as
->rank
- 1;
590 if (e
->ref
->u
.ar
.type
== AR_FULL
)
592 se
->expr
= gfc_get_symbol_decl (sym
);
593 se
->expr
= gfc_conv_array_data (se
->expr
);
597 gfc_conv_expr (se
, e
);
600 array
= sym
->backend_decl
;
601 type
= TREE_TYPE (array
);
603 if (GFC_ARRAY_TYPE_P (type
))
604 size
= GFC_TYPE_ARRAY_SIZE (type
);
607 gcc_assert (GFC_DESCRIPTOR_TYPE_P (type
));
608 size
= gfc_conv_array_stride (array
, rank
);
609 tmp
= fold_build2 (MINUS_EXPR
, gfc_array_index_type
,
610 gfc_conv_array_ubound (array
, rank
),
611 gfc_conv_array_lbound (array
, rank
));
612 tmp
= fold_build2 (PLUS_EXPR
, gfc_array_index_type
, tmp
,
614 size
= fold_build2 (MULT_EXPR
, gfc_array_index_type
, tmp
, size
);
619 /* If it is an element, we need the its address and size of the rest. */
620 if (e
->ref
->u
.ar
.type
== AR_ELEMENT
)
622 size
= fold_build2 (MINUS_EXPR
, gfc_array_index_type
, size
,
623 TREE_OPERAND (se
->expr
, 1));
624 se
->expr
= build_fold_addr_expr (se
->expr
);
627 tmp
= TYPE_SIZE_UNIT (gfc_get_element_type (type
));
628 size
= fold_build2 (MULT_EXPR
, gfc_array_index_type
, size
,
629 fold_convert (gfc_array_index_type
, tmp
));
631 se
->string_length
= fold_convert (gfc_charlen_type_node
, size
);
635 /* Generate code to store a string and its length into the
636 st_parameter_XXX structure. */
639 set_string (stmtblock_t
* block
, stmtblock_t
* postblock
, tree var
,
640 enum iofield type
, gfc_expr
* e
)
646 gfc_st_parameter_field
*p
= &st_parameter_field
[type
];
648 gfc_init_se (&se
, NULL
);
650 if (p
->param_type
== IOPARM_ptype_common
)
651 var
= fold_build3 (COMPONENT_REF
, st_parameter
[IOPARM_ptype_common
].type
,
652 var
, TYPE_FIELDS (TREE_TYPE (var
)), NULL_TREE
);
653 io
= fold_build3 (COMPONENT_REF
, TREE_TYPE (p
->field
),
654 var
, p
->field
, NULL_TREE
);
655 len
= fold_build3 (COMPONENT_REF
, TREE_TYPE (p
->field_len
),
656 var
, p
->field_len
, NULL_TREE
);
658 /* Integer variable assigned a format label. */
659 if (e
->ts
.type
== BT_INTEGER
&& e
->symtree
->n
.sym
->attr
.assign
== 1)
664 gfc_conv_label_variable (&se
, e
);
665 tmp
= GFC_DECL_STRING_LEN (se
.expr
);
666 cond
= fold_build2 (LT_EXPR
, boolean_type_node
,
667 tmp
, build_int_cst (TREE_TYPE (tmp
), 0));
669 asprintf(&msg
, "Label assigned to variable '%s' (%%ld) is not a format "
670 "label", e
->symtree
->name
);
671 gfc_trans_runtime_check (true, false, cond
, &se
.pre
, &e
->where
, msg
,
672 fold_convert (long_integer_type_node
, tmp
));
675 gfc_add_modify (&se
.pre
, io
,
676 fold_convert (TREE_TYPE (io
), GFC_DECL_ASSIGN_ADDR (se
.expr
)));
677 gfc_add_modify (&se
.pre
, len
, GFC_DECL_STRING_LEN (se
.expr
));
681 /* General character. */
682 if (e
->ts
.type
== BT_CHARACTER
&& e
->rank
== 0)
683 gfc_conv_expr (&se
, e
);
684 /* Array assigned Hollerith constant or character array. */
685 else if (e
->symtree
&& (e
->symtree
->n
.sym
->as
->rank
> 0))
686 gfc_convert_array_to_string (&se
, e
);
690 gfc_conv_string_parameter (&se
);
691 gfc_add_modify (&se
.pre
, io
, fold_convert (TREE_TYPE (io
), se
.expr
));
692 gfc_add_modify (&se
.pre
, len
, se
.string_length
);
695 gfc_add_block_to_block (block
, &se
.pre
);
696 gfc_add_block_to_block (postblock
, &se
.post
);
701 /* Generate code to store the character (array) and the character length
702 for an internal unit. */
705 set_internal_unit (stmtblock_t
* block
, stmtblock_t
* post_block
,
706 tree var
, gfc_expr
* e
)
713 gfc_st_parameter_field
*p
;
716 gfc_init_se (&se
, NULL
);
718 p
= &st_parameter_field
[IOPARM_dt_internal_unit
];
720 io
= fold_build3 (COMPONENT_REF
, TREE_TYPE (p
->field
),
721 var
, p
->field
, NULL_TREE
);
722 len
= fold_build3 (COMPONENT_REF
, TREE_TYPE (p
->field_len
),
723 var
, p
->field_len
, NULL_TREE
);
724 p
= &st_parameter_field
[IOPARM_dt_internal_unit_desc
];
725 desc
= fold_build3 (COMPONENT_REF
, TREE_TYPE (p
->field
),
726 var
, p
->field
, NULL_TREE
);
728 gcc_assert (e
->ts
.type
== BT_CHARACTER
);
730 /* Character scalars. */
733 gfc_conv_expr (&se
, e
);
734 gfc_conv_string_parameter (&se
);
736 se
.expr
= build_int_cst (pchar_type_node
, 0);
739 /* Character array. */
740 else if (e
->rank
> 0)
742 se
.ss
= gfc_walk_expr (e
);
744 if (is_subref_array (e
))
746 /* Use a temporary for components of arrays of derived types
747 or substring array references. */
748 gfc_conv_subref_array_arg (&se
, e
, 0,
749 last_dt
== READ
? INTENT_IN
: INTENT_OUT
);
750 tmp
= build_fold_indirect_ref (se
.expr
);
751 se
.expr
= gfc_build_addr_expr (pchar_type_node
, tmp
);
752 tmp
= gfc_conv_descriptor_data_get (tmp
);
756 /* Return the data pointer and rank from the descriptor. */
757 gfc_conv_expr_descriptor (&se
, e
, se
.ss
);
758 tmp
= gfc_conv_descriptor_data_get (se
.expr
);
759 se
.expr
= gfc_build_addr_expr (pchar_type_node
, se
.expr
);
765 /* The cast is needed for character substrings and the descriptor
767 gfc_add_modify (&se
.pre
, io
, fold_convert (TREE_TYPE (io
), tmp
));
768 gfc_add_modify (&se
.pre
, len
,
769 fold_convert (TREE_TYPE (len
), se
.string_length
));
770 gfc_add_modify (&se
.pre
, desc
, se
.expr
);
772 gfc_add_block_to_block (block
, &se
.pre
);
773 gfc_add_block_to_block (post_block
, &se
.post
);
777 /* Add a case to a IO-result switch. */
780 add_case (int label_value
, gfc_st_label
* label
, stmtblock_t
* body
)
785 return; /* No label, no case */
787 value
= build_int_cst (NULL_TREE
, label_value
);
789 /* Make a backend label for this case. */
790 tmp
= gfc_build_label_decl (NULL_TREE
);
792 /* And the case itself. */
793 tmp
= build3_v (CASE_LABEL_EXPR
, value
, NULL_TREE
, tmp
);
794 gfc_add_expr_to_block (body
, tmp
);
796 /* Jump to the label. */
797 tmp
= build1_v (GOTO_EXPR
, gfc_get_label_decl (label
));
798 gfc_add_expr_to_block (body
, tmp
);
802 /* Generate a switch statement that branches to the correct I/O
803 result label. The last statement of an I/O call stores the
804 result into a variable because there is often cleanup that
805 must be done before the switch, so a temporary would have to
806 be created anyway. */
809 io_result (stmtblock_t
* block
, tree var
, gfc_st_label
* err_label
,
810 gfc_st_label
* end_label
, gfc_st_label
* eor_label
)
814 gfc_st_parameter_field
*p
= &st_parameter_field
[IOPARM_common_flags
];
816 /* If no labels are specified, ignore the result instead
817 of building an empty switch. */
818 if (err_label
== NULL
820 && eor_label
== NULL
)
823 /* Build a switch statement. */
824 gfc_start_block (&body
);
826 /* The label values here must be the same as the values
827 in the library_return enum in the runtime library */
828 add_case (1, err_label
, &body
);
829 add_case (2, end_label
, &body
);
830 add_case (3, eor_label
, &body
);
832 tmp
= gfc_finish_block (&body
);
834 var
= fold_build3 (COMPONENT_REF
, st_parameter
[IOPARM_ptype_common
].type
,
835 var
, TYPE_FIELDS (TREE_TYPE (var
)), NULL_TREE
);
836 rc
= fold_build3 (COMPONENT_REF
, TREE_TYPE (p
->field
),
837 var
, p
->field
, NULL_TREE
);
838 rc
= fold_build2 (BIT_AND_EXPR
, TREE_TYPE (rc
),
839 rc
, build_int_cst (TREE_TYPE (rc
),
840 IOPARM_common_libreturn_mask
));
842 tmp
= build3_v (SWITCH_EXPR
, rc
, tmp
, NULL_TREE
);
844 gfc_add_expr_to_block (block
, tmp
);
848 /* Store the current file and line number to variables so that if a
849 library call goes awry, we can tell the user where the problem is. */
852 set_error_locus (stmtblock_t
* block
, tree var
, locus
* where
)
855 tree str
, locus_file
;
857 gfc_st_parameter_field
*p
= &st_parameter_field
[IOPARM_common_filename
];
859 locus_file
= fold_build3 (COMPONENT_REF
,
860 st_parameter
[IOPARM_ptype_common
].type
,
861 var
, TYPE_FIELDS (TREE_TYPE (var
)), NULL_TREE
);
862 locus_file
= fold_build3 (COMPONENT_REF
, TREE_TYPE (p
->field
),
863 locus_file
, p
->field
, NULL_TREE
);
865 str
= gfc_build_cstring_const (f
->filename
);
867 str
= gfc_build_addr_expr (pchar_type_node
, str
);
868 gfc_add_modify (block
, locus_file
, str
);
870 line
= LOCATION_LINE (where
->lb
->location
);
871 set_parameter_const (block
, var
, IOPARM_common_line
, line
);
875 /* Translate an OPEN statement. */
878 gfc_trans_open (gfc_code
* code
)
880 stmtblock_t block
, post_block
;
883 unsigned int mask
= 0;
885 gfc_start_block (&block
);
886 gfc_init_block (&post_block
);
888 var
= gfc_create_var (st_parameter
[IOPARM_ptype_open
].type
, "open_parm");
890 set_error_locus (&block
, var
, &code
->loc
);
894 mask
|= set_string (&block
, &post_block
, var
, IOPARM_common_iomsg
,
898 mask
|= set_parameter_ref (&block
, &post_block
, var
, IOPARM_common_iostat
,
902 mask
|= IOPARM_common_err
;
905 mask
|= set_string (&block
, &post_block
, var
, IOPARM_open_file
, p
->file
);
908 mask
|= set_string (&block
, &post_block
, var
, IOPARM_open_status
,
912 mask
|= set_string (&block
, &post_block
, var
, IOPARM_open_access
,
916 mask
|= set_string (&block
, &post_block
, var
, IOPARM_open_form
, p
->form
);
919 mask
|= set_parameter_value (&block
, var
, IOPARM_open_recl_in
, p
->recl
);
922 mask
|= set_string (&block
, &post_block
, var
, IOPARM_open_blank
,
926 mask
|= set_string (&block
, &post_block
, var
, IOPARM_open_position
,
930 mask
|= set_string (&block
, &post_block
, var
, IOPARM_open_action
,
934 mask
|= set_string (&block
, &post_block
, var
, IOPARM_open_delim
,
938 mask
|= set_string (&block
, &post_block
, var
, IOPARM_open_pad
, p
->pad
);
941 mask
|= set_string (&block
, &post_block
, var
, IOPARM_open_decimal
,
945 mask
|= set_string (&block
, &post_block
, var
, IOPARM_open_encoding
,
949 mask
|= set_string (&block
, &post_block
, var
, IOPARM_open_round
, p
->round
);
952 mask
|= set_string (&block
, &post_block
, var
, IOPARM_open_sign
, p
->sign
);
955 mask
|= set_string (&block
, &post_block
, var
, IOPARM_open_asynchronous
,
959 mask
|= set_string (&block
, &post_block
, var
, IOPARM_open_convert
,
962 set_parameter_const (&block
, var
, IOPARM_common_flags
, mask
);
965 set_parameter_value (&block
, var
, IOPARM_common_unit
, p
->unit
);
967 set_parameter_const (&block
, var
, IOPARM_common_unit
, 0);
969 tmp
= build_fold_addr_expr (var
);
970 tmp
= build_call_expr (iocall
[IOCALL_OPEN
], 1, tmp
);
971 gfc_add_expr_to_block (&block
, tmp
);
973 gfc_add_block_to_block (&block
, &post_block
);
975 io_result (&block
, var
, p
->err
, NULL
, NULL
);
977 return gfc_finish_block (&block
);
981 /* Translate a CLOSE statement. */
984 gfc_trans_close (gfc_code
* code
)
986 stmtblock_t block
, post_block
;
989 unsigned int mask
= 0;
991 gfc_start_block (&block
);
992 gfc_init_block (&post_block
);
994 var
= gfc_create_var (st_parameter
[IOPARM_ptype_close
].type
, "close_parm");
996 set_error_locus (&block
, var
, &code
->loc
);
1000 mask
|= set_string (&block
, &post_block
, var
, IOPARM_common_iomsg
,
1004 mask
|= set_parameter_ref (&block
, &post_block
, var
, IOPARM_common_iostat
,
1008 mask
|= IOPARM_common_err
;
1011 mask
|= set_string (&block
, &post_block
, var
, IOPARM_close_status
,
1014 set_parameter_const (&block
, var
, IOPARM_common_flags
, mask
);
1017 set_parameter_value (&block
, var
, IOPARM_common_unit
, p
->unit
);
1019 set_parameter_const (&block
, var
, IOPARM_common_unit
, 0);
1021 tmp
= build_fold_addr_expr (var
);
1022 tmp
= build_call_expr (iocall
[IOCALL_CLOSE
], 1, tmp
);
1023 gfc_add_expr_to_block (&block
, tmp
);
1025 gfc_add_block_to_block (&block
, &post_block
);
1027 io_result (&block
, var
, p
->err
, NULL
, NULL
);
1029 return gfc_finish_block (&block
);
1033 /* Common subroutine for building a file positioning statement. */
1036 build_filepos (tree function
, gfc_code
* code
)
1038 stmtblock_t block
, post_block
;
1041 unsigned int mask
= 0;
1043 p
= code
->ext
.filepos
;
1045 gfc_start_block (&block
);
1046 gfc_init_block (&post_block
);
1048 var
= gfc_create_var (st_parameter
[IOPARM_ptype_filepos
].type
,
1051 set_error_locus (&block
, var
, &code
->loc
);
1054 mask
|= set_string (&block
, &post_block
, var
, IOPARM_common_iomsg
,
1058 mask
|= set_parameter_ref (&block
, &post_block
, var
, IOPARM_common_iostat
,
1062 mask
|= IOPARM_common_err
;
1064 set_parameter_const (&block
, var
, IOPARM_common_flags
, mask
);
1067 set_parameter_value (&block
, var
, IOPARM_common_unit
, p
->unit
);
1069 set_parameter_const (&block
, var
, IOPARM_common_unit
, 0);
1071 tmp
= build_fold_addr_expr (var
);
1072 tmp
= build_call_expr (function
, 1, tmp
);
1073 gfc_add_expr_to_block (&block
, tmp
);
1075 gfc_add_block_to_block (&block
, &post_block
);
1077 io_result (&block
, var
, p
->err
, NULL
, NULL
);
1079 return gfc_finish_block (&block
);
1083 /* Translate a BACKSPACE statement. */
1086 gfc_trans_backspace (gfc_code
* code
)
1088 return build_filepos (iocall
[IOCALL_BACKSPACE
], code
);
1092 /* Translate an ENDFILE statement. */
1095 gfc_trans_endfile (gfc_code
* code
)
1097 return build_filepos (iocall
[IOCALL_ENDFILE
], code
);
1101 /* Translate a REWIND statement. */
1104 gfc_trans_rewind (gfc_code
* code
)
1106 return build_filepos (iocall
[IOCALL_REWIND
], code
);
1110 /* Translate a FLUSH statement. */
1113 gfc_trans_flush (gfc_code
* code
)
1115 return build_filepos (iocall
[IOCALL_FLUSH
], code
);
1119 /* Create a dummy iostat variable to catch any error due to bad unit. */
1122 create_dummy_iostat (void)
1127 gfc_get_ha_sym_tree ("@iostat", &st
);
1128 st
->n
.sym
->ts
.type
= BT_INTEGER
;
1129 st
->n
.sym
->ts
.kind
= gfc_default_integer_kind
;
1130 gfc_set_sym_referenced (st
->n
.sym
);
1131 gfc_commit_symbol (st
->n
.sym
);
1132 st
->n
.sym
->backend_decl
1133 = gfc_create_var (gfc_get_int_type (st
->n
.sym
->ts
.kind
),
1136 e
= gfc_get_expr ();
1137 e
->expr_type
= EXPR_VARIABLE
;
1139 e
->ts
.type
= BT_INTEGER
;
1140 e
->ts
.kind
= st
->n
.sym
->ts
.kind
;
1146 /* Translate the non-IOLENGTH form of an INQUIRE statement. */
1149 gfc_trans_inquire (gfc_code
* code
)
1151 stmtblock_t block
, post_block
;
1154 unsigned int mask
= 0, mask2
= 0;
1156 gfc_start_block (&block
);
1157 gfc_init_block (&post_block
);
1159 var
= gfc_create_var (st_parameter
[IOPARM_ptype_inquire
].type
,
1162 set_error_locus (&block
, var
, &code
->loc
);
1163 p
= code
->ext
.inquire
;
1166 mask
|= set_string (&block
, &post_block
, var
, IOPARM_common_iomsg
,
1170 mask
|= set_parameter_ref (&block
, &post_block
, var
, IOPARM_common_iostat
,
1174 mask
|= IOPARM_common_err
;
1177 if (p
->unit
&& p
->file
)
1178 gfc_error ("INQUIRE statement at %L cannot contain both FILE and UNIT specifiers", &code
->loc
);
1181 mask
|= set_string (&block
, &post_block
, var
, IOPARM_inquire_file
,
1186 mask
|= set_parameter_ref (&block
, &post_block
, var
, IOPARM_inquire_exist
,
1189 if (p
->unit
&& !p
->iostat
)
1191 p
->iostat
= create_dummy_iostat ();
1192 mask
|= set_parameter_ref (&block
, &post_block
, var
,
1193 IOPARM_common_iostat
, p
->iostat
);
1198 mask
|= set_parameter_ref (&block
, &post_block
, var
, IOPARM_inquire_opened
,
1202 mask
|= set_parameter_ref (&block
, &post_block
, var
, IOPARM_inquire_number
,
1206 mask
|= set_parameter_ref (&block
, &post_block
, var
, IOPARM_inquire_named
,
1210 mask
|= set_string (&block
, &post_block
, var
, IOPARM_inquire_name
,
1214 mask
|= set_string (&block
, &post_block
, var
, IOPARM_inquire_access
,
1218 mask
|= set_string (&block
, &post_block
, var
, IOPARM_inquire_sequential
,
1222 mask
|= set_string (&block
, &post_block
, var
, IOPARM_inquire_direct
,
1226 mask
|= set_string (&block
, &post_block
, var
, IOPARM_inquire_form
,
1230 mask
|= set_string (&block
, &post_block
, var
, IOPARM_inquire_formatted
,
1234 mask
|= set_string (&block
, &post_block
, var
, IOPARM_inquire_unformatted
,
1238 mask
|= set_parameter_ref (&block
, &post_block
, var
,
1239 IOPARM_inquire_recl_out
, p
->recl
);
1242 mask
|= set_parameter_ref (&block
, &post_block
, var
,
1243 IOPARM_inquire_nextrec
, p
->nextrec
);
1246 mask
|= set_string (&block
, &post_block
, var
, IOPARM_inquire_blank
,
1250 mask
|= set_string (&block
, &post_block
, var
, IOPARM_inquire_delim
,
1254 mask
|= set_string (&block
, &post_block
, var
, IOPARM_inquire_position
,
1258 mask
|= set_string (&block
, &post_block
, var
, IOPARM_inquire_action
,
1262 mask
|= set_string (&block
, &post_block
, var
, IOPARM_inquire_read
,
1266 mask
|= set_string (&block
, &post_block
, var
, IOPARM_inquire_write
,
1270 mask
|= set_string (&block
, &post_block
, var
, IOPARM_inquire_readwrite
,
1274 mask
|= set_string (&block
, &post_block
, var
, IOPARM_inquire_pad
,
1278 mask
|= set_string (&block
, &post_block
, var
, IOPARM_inquire_convert
,
1282 mask
|= set_parameter_ref (&block
, &post_block
, var
,
1283 IOPARM_inquire_strm_pos_out
, p
->strm_pos
);
1285 /* The second series of flags. */
1286 if (p
->asynchronous
)
1287 mask2
|= set_string (&block
, &post_block
, var
, IOPARM_inquire_asynchronous
,
1291 mask2
|= set_string (&block
, &post_block
, var
, IOPARM_inquire_decimal
,
1295 mask2
|= set_string (&block
, &post_block
, var
, IOPARM_inquire_encoding
,
1299 mask2
|= set_string (&block
, &post_block
, var
, IOPARM_inquire_round
,
1303 mask2
|= set_string (&block
, &post_block
, var
, IOPARM_inquire_sign
,
1307 mask2
|= set_parameter_ref (&block
, &post_block
, var
,
1308 IOPARM_inquire_pending
, p
->pending
);
1311 mask2
|= set_parameter_ref (&block
, &post_block
, var
, IOPARM_inquire_size
,
1315 mask2
|= set_parameter_ref (&block
, &post_block
,var
, IOPARM_inquire_id
,
1318 set_parameter_const (&block
, var
, IOPARM_inquire_flags2
, mask2
);
1321 mask
|= IOPARM_inquire_flags2
;
1323 set_parameter_const (&block
, var
, IOPARM_common_flags
, mask
);
1326 set_parameter_value (&block
, var
, IOPARM_common_unit
, p
->unit
);
1328 set_parameter_const (&block
, var
, IOPARM_common_unit
, 0);
1330 tmp
= build_fold_addr_expr (var
);
1331 tmp
= build_call_expr (iocall
[IOCALL_INQUIRE
], 1, tmp
);
1332 gfc_add_expr_to_block (&block
, tmp
);
1334 gfc_add_block_to_block (&block
, &post_block
);
1336 io_result (&block
, var
, p
->err
, NULL
, NULL
);
1338 return gfc_finish_block (&block
);
1343 gfc_trans_wait (gfc_code
* code
)
1345 stmtblock_t block
, post_block
;
1348 unsigned int mask
= 0;
1350 gfc_start_block (&block
);
1351 gfc_init_block (&post_block
);
1353 var
= gfc_create_var (st_parameter
[IOPARM_ptype_wait
].type
,
1356 set_error_locus (&block
, var
, &code
->loc
);
1359 /* Set parameters here. */
1361 mask
|= set_string (&block
, &post_block
, var
, IOPARM_common_iomsg
,
1365 mask
|= set_parameter_ref (&block
, &post_block
, var
, IOPARM_common_iostat
,
1369 mask
|= IOPARM_common_err
;
1372 mask
|= set_parameter_value (&block
, var
, IOPARM_wait_id
, p
->id
);
1374 set_parameter_const (&block
, var
, IOPARM_common_flags
, mask
);
1377 set_parameter_value (&block
, var
, IOPARM_common_unit
, p
->unit
);
1379 tmp
= build_fold_addr_expr (var
);
1380 tmp
= build_call_expr (iocall
[IOCALL_WAIT
], 1, tmp
);
1381 gfc_add_expr_to_block (&block
, tmp
);
1383 gfc_add_block_to_block (&block
, &post_block
);
1385 io_result (&block
, var
, p
->err
, NULL
, NULL
);
1387 return gfc_finish_block (&block
);
1392 gfc_new_nml_name_expr (const char * name
)
1394 gfc_expr
* nml_name
;
1396 nml_name
= gfc_get_expr();
1397 nml_name
->ref
= NULL
;
1398 nml_name
->expr_type
= EXPR_CONSTANT
;
1399 nml_name
->ts
.kind
= gfc_default_character_kind
;
1400 nml_name
->ts
.type
= BT_CHARACTER
;
1401 nml_name
->value
.character
.length
= strlen(name
);
1402 nml_name
->value
.character
.string
= gfc_char_to_widechar (name
);
1407 /* nml_full_name builds up the fully qualified name of a
1408 derived type component. */
1411 nml_full_name (const char* var_name
, const char* cmp_name
)
1413 int full_name_length
;
1416 full_name_length
= strlen (var_name
) + strlen (cmp_name
) + 1;
1417 full_name
= (char*)gfc_getmem (full_name_length
+ 1);
1418 strcpy (full_name
, var_name
);
1419 full_name
= strcat (full_name
, "%");
1420 full_name
= strcat (full_name
, cmp_name
);
1424 /* nml_get_addr_expr builds an address expression from the
1425 gfc_symbol or gfc_component backend_decl's. An offset is
1426 provided so that the address of an element of an array of
1427 derived types is returned. This is used in the runtime to
1428 determine that span of the derived type. */
1431 nml_get_addr_expr (gfc_symbol
* sym
, gfc_component
* c
,
1434 tree decl
= NULL_TREE
;
1438 int dummy_arg_flagged
;
1442 sym
->attr
.referenced
= 1;
1443 decl
= gfc_get_symbol_decl (sym
);
1445 /* If this is the enclosing function declaration, use
1446 the fake result instead. */
1447 if (decl
== current_function_decl
)
1448 decl
= gfc_get_fake_result_decl (sym
, 0);
1449 else if (decl
== DECL_CONTEXT (current_function_decl
))
1450 decl
= gfc_get_fake_result_decl (sym
, 1);
1453 decl
= c
->backend_decl
;
1455 gcc_assert (decl
&& ((TREE_CODE (decl
) == FIELD_DECL
1456 || TREE_CODE (decl
) == VAR_DECL
1457 || TREE_CODE (decl
) == PARM_DECL
)
1458 || TREE_CODE (decl
) == COMPONENT_REF
));
1462 /* Build indirect reference, if dummy argument. */
1464 dummy_arg_flagged
= POINTER_TYPE_P (TREE_TYPE(tmp
));
1466 itmp
= (dummy_arg_flagged
) ? build_fold_indirect_ref (tmp
) : tmp
;
1468 /* If an array, set flag and use indirect ref. if built. */
1470 array_flagged
= (TREE_CODE (TREE_TYPE (itmp
)) == ARRAY_TYPE
1471 && !TYPE_STRING_FLAG (TREE_TYPE (itmp
)));
1476 /* Treat the component of a derived type, using base_addr for
1477 the derived type. */
1479 if (TREE_CODE (decl
) == FIELD_DECL
)
1480 tmp
= fold_build3 (COMPONENT_REF
, TREE_TYPE (tmp
),
1481 base_addr
, tmp
, NULL_TREE
);
1483 /* If we have a derived type component, a reference to the first
1484 element of the array is built. This is done so that base_addr,
1485 used in the build of the component reference, always points to
1489 tmp
= gfc_build_array_ref (tmp
, gfc_index_zero_node
, NULL
);
1491 /* Now build the address expression. */
1493 tmp
= build_fold_addr_expr (tmp
);
1495 /* If scalar dummy, resolve indirect reference now. */
1497 if (dummy_arg_flagged
&& !array_flagged
)
1498 tmp
= build_fold_indirect_ref (tmp
);
1500 gcc_assert (tmp
&& POINTER_TYPE_P (TREE_TYPE (tmp
)));
1505 /* For an object VAR_NAME whose base address is BASE_ADDR, generate a
1506 call to iocall[IOCALL_SET_NML_VAL]. For derived type variable, recursively
1507 generate calls to iocall[IOCALL_SET_NML_VAL] for each component. */
1509 #define IARG(i) build_int_cst (gfc_array_index_type, i)
1512 transfer_namelist_element (stmtblock_t
* block
, const char * var_name
,
1513 gfc_symbol
* sym
, gfc_component
* c
,
1516 gfc_typespec
* ts
= NULL
;
1517 gfc_array_spec
* as
= NULL
;
1518 tree addr_expr
= NULL
;
1528 gcc_assert (sym
|| c
);
1530 /* Build the namelist object name. */
1532 string
= gfc_build_cstring_const (var_name
);
1533 string
= gfc_build_addr_expr (pchar_type_node
, string
);
1535 /* Build ts, as and data address using symbol or component. */
1537 ts
= (sym
) ? &sym
->ts
: &c
->ts
;
1538 as
= (sym
) ? sym
->as
: c
->as
;
1540 addr_expr
= nml_get_addr_expr (sym
, c
, base_addr
);
1547 dt
= TREE_TYPE ((sym
) ? sym
->backend_decl
: c
->backend_decl
);
1548 dtype
= gfc_get_dtype (dt
);
1552 itype
= GFC_DTYPE_UNKNOWN
;
1558 itype
= GFC_DTYPE_INTEGER
;
1561 itype
= GFC_DTYPE_LOGICAL
;
1564 itype
= GFC_DTYPE_REAL
;
1567 itype
= GFC_DTYPE_COMPLEX
;
1570 itype
= GFC_DTYPE_DERIVED
;
1573 itype
= GFC_DTYPE_CHARACTER
;
1579 dtype
= IARG (itype
<< GFC_DTYPE_TYPE_SHIFT
);
1582 /* Build up the arguments for the transfer call.
1583 The call for the scalar part transfers:
1584 (address, name, type, kind or string_length, dtype) */
1586 dt_parm_addr
= build_fold_addr_expr (dt_parm
);
1588 if (ts
->type
== BT_CHARACTER
)
1589 tmp
= ts
->cl
->backend_decl
;
1591 tmp
= build_int_cst (gfc_charlen_type_node
, 0);
1592 tmp
= build_call_expr (iocall
[IOCALL_SET_NML_VAL
], 6,
1593 dt_parm_addr
, addr_expr
, string
,
1594 IARG (ts
->kind
), tmp
, dtype
);
1595 gfc_add_expr_to_block (block
, tmp
);
1597 /* If the object is an array, transfer rank times:
1598 (null pointer, name, stride, lbound, ubound) */
1600 for ( n_dim
= 0 ; n_dim
< rank
; n_dim
++ )
1602 tmp
= build_call_expr (iocall
[IOCALL_SET_NML_VAL_DIM
], 5,
1605 GFC_TYPE_ARRAY_STRIDE (dt
, n_dim
),
1606 GFC_TYPE_ARRAY_LBOUND (dt
, n_dim
),
1607 GFC_TYPE_ARRAY_UBOUND (dt
, n_dim
));
1608 gfc_add_expr_to_block (block
, tmp
);
1611 if (ts
->type
== BT_DERIVED
)
1615 /* Provide the RECORD_TYPE to build component references. */
1617 tree expr
= build_fold_indirect_ref (addr_expr
);
1619 for (cmp
= ts
->derived
->components
; cmp
; cmp
= cmp
->next
)
1621 char *full_name
= nml_full_name (var_name
, cmp
->name
);
1622 transfer_namelist_element (block
,
1625 gfc_free (full_name
);
1632 /* Create a data transfer statement. Not all of the fields are valid
1633 for both reading and writing, but improper use has been filtered
1637 build_dt (tree function
, gfc_code
* code
)
1639 stmtblock_t block
, post_block
, post_end_block
, post_iu_block
;
1644 unsigned int mask
= 0;
1646 gfc_start_block (&block
);
1647 gfc_init_block (&post_block
);
1648 gfc_init_block (&post_end_block
);
1649 gfc_init_block (&post_iu_block
);
1651 var
= gfc_create_var (st_parameter
[IOPARM_ptype_dt
].type
, "dt_parm");
1653 set_error_locus (&block
, var
, &code
->loc
);
1655 if (last_dt
== IOLENGTH
)
1659 inq
= code
->ext
.inquire
;
1661 /* First check that preconditions are met. */
1662 gcc_assert (inq
!= NULL
);
1663 gcc_assert (inq
->iolength
!= NULL
);
1665 /* Connect to the iolength variable. */
1666 mask
|= set_parameter_ref (&block
, &post_end_block
, var
,
1667 IOPARM_dt_iolength
, inq
->iolength
);
1673 gcc_assert (dt
!= NULL
);
1676 if (dt
&& dt
->io_unit
)
1678 if (dt
->io_unit
->ts
.type
== BT_CHARACTER
)
1680 mask
|= set_internal_unit (&block
, &post_iu_block
,
1682 set_parameter_const (&block
, var
, IOPARM_common_unit
, 0);
1686 set_parameter_const (&block
, var
, IOPARM_common_unit
, 0);
1691 mask
|= set_string (&block
, &post_block
, var
, IOPARM_common_iomsg
,
1695 mask
|= set_parameter_ref (&block
, &post_end_block
, var
,
1696 IOPARM_common_iostat
, dt
->iostat
);
1699 mask
|= IOPARM_common_err
;
1702 mask
|= IOPARM_common_eor
;
1705 mask
|= IOPARM_common_end
;
1708 mask
|= set_parameter_ref (&block
, &post_end_block
, var
,
1709 IOPARM_dt_id
, dt
->id
);
1712 mask
|= set_parameter_value (&block
, var
, IOPARM_dt_pos
, dt
->pos
);
1714 if (dt
->asynchronous
)
1715 mask
|= set_string (&block
, &post_block
, var
, IOPARM_dt_asynchronous
,
1719 mask
|= set_string (&block
, &post_block
, var
, IOPARM_dt_blank
,
1723 mask
|= set_string (&block
, &post_block
, var
, IOPARM_dt_decimal
,
1727 mask
|= set_string (&block
, &post_block
, var
, IOPARM_dt_delim
,
1731 mask
|= set_string (&block
, &post_block
, var
, IOPARM_dt_pad
,
1735 mask
|= set_string (&block
, &post_block
, var
, IOPARM_dt_round
,
1739 mask
|= set_string (&block
, &post_block
, var
, IOPARM_dt_sign
,
1743 mask
|= set_parameter_value (&block
, var
, IOPARM_dt_rec
, dt
->rec
);
1746 mask
|= set_string (&block
, &post_block
, var
, IOPARM_dt_advance
,
1749 if (dt
->format_expr
)
1750 mask
|= set_string (&block
, &post_end_block
, var
, IOPARM_dt_format
,
1753 if (dt
->format_label
)
1755 if (dt
->format_label
== &format_asterisk
)
1756 mask
|= IOPARM_dt_list_format
;
1758 mask
|= set_string (&block
, &post_block
, var
, IOPARM_dt_format
,
1759 dt
->format_label
->format
);
1763 mask
|= set_parameter_ref (&block
, &post_end_block
, var
,
1764 IOPARM_dt_size
, dt
->size
);
1768 if (dt
->format_expr
|| dt
->format_label
)
1769 gfc_internal_error ("build_dt: format with namelist");
1771 nmlname
= gfc_new_nml_name_expr (dt
->namelist
->name
);
1773 mask
|= set_string (&block
, &post_block
, var
, IOPARM_dt_namelist_name
,
1776 if (last_dt
== READ
)
1777 mask
|= IOPARM_dt_namelist_read_mode
;
1779 set_parameter_const (&block
, var
, IOPARM_common_flags
, mask
);
1783 for (nml
= dt
->namelist
->namelist
; nml
; nml
= nml
->next
)
1784 transfer_namelist_element (&block
, nml
->sym
->name
, nml
->sym
,
1788 set_parameter_const (&block
, var
, IOPARM_common_flags
, mask
);
1790 if (dt
->io_unit
&& dt
->io_unit
->ts
.type
== BT_INTEGER
)
1791 set_parameter_value (&block
, var
, IOPARM_common_unit
, dt
->io_unit
);
1794 set_parameter_const (&block
, var
, IOPARM_common_flags
, mask
);
1796 tmp
= build_fold_addr_expr (var
);
1797 tmp
= build_call_expr (function
, 1, tmp
);
1798 gfc_add_expr_to_block (&block
, tmp
);
1800 gfc_add_block_to_block (&block
, &post_block
);
1803 dt_post_end_block
= &post_end_block
;
1805 gfc_add_expr_to_block (&block
, gfc_trans_code (code
->block
->next
));
1807 gfc_add_block_to_block (&block
, &post_iu_block
);
1810 dt_post_end_block
= NULL
;
1812 return gfc_finish_block (&block
);
1816 /* Translate the IOLENGTH form of an INQUIRE statement. We treat
1817 this as a third sort of data transfer statement, except that
1818 lengths are summed instead of actually transferring any data. */
1821 gfc_trans_iolength (gfc_code
* code
)
1824 return build_dt (iocall
[IOCALL_IOLENGTH
], code
);
1828 /* Translate a READ statement. */
1831 gfc_trans_read (gfc_code
* code
)
1834 return build_dt (iocall
[IOCALL_READ
], code
);
1838 /* Translate a WRITE statement */
1841 gfc_trans_write (gfc_code
* code
)
1844 return build_dt (iocall
[IOCALL_WRITE
], code
);
1848 /* Finish a data transfer statement. */
1851 gfc_trans_dt_end (gfc_code
* code
)
1856 gfc_init_block (&block
);
1861 function
= iocall
[IOCALL_READ_DONE
];
1865 function
= iocall
[IOCALL_WRITE_DONE
];
1869 function
= iocall
[IOCALL_IOLENGTH_DONE
];
1876 tmp
= build_fold_addr_expr (dt_parm
);
1877 tmp
= build_call_expr (function
, 1, tmp
);
1878 gfc_add_expr_to_block (&block
, tmp
);
1879 gfc_add_block_to_block (&block
, dt_post_end_block
);
1880 gfc_init_block (dt_post_end_block
);
1882 if (last_dt
!= IOLENGTH
)
1884 gcc_assert (code
->ext
.dt
!= NULL
);
1885 io_result (&block
, dt_parm
, code
->ext
.dt
->err
,
1886 code
->ext
.dt
->end
, code
->ext
.dt
->eor
);
1889 return gfc_finish_block (&block
);
1893 transfer_expr (gfc_se
* se
, gfc_typespec
* ts
, tree addr_expr
, gfc_code
* code
);
1895 /* Given an array field in a derived type variable, generate the code
1896 for the loop that iterates over array elements, and the code that
1897 accesses those array elements. Use transfer_expr to generate code
1898 for transferring that element. Because elements may also be
1899 derived types, transfer_expr and transfer_array_component are mutually
1903 transfer_array_component (tree expr
, gfc_component
* cm
, locus
* where
)
1913 gfc_start_block (&block
);
1914 gfc_init_se (&se
, NULL
);
1916 /* Create and initialize Scalarization Status. Unlike in
1917 gfc_trans_transfer, we can't simply use gfc_walk_expr to take
1918 care of this task, because we don't have a gfc_expr at hand.
1919 Build one manually, as in gfc_trans_subarray_assign. */
1922 ss
->type
= GFC_SS_COMPONENT
;
1924 ss
->shape
= gfc_get_shape (cm
->as
->rank
);
1925 ss
->next
= gfc_ss_terminator
;
1926 ss
->data
.info
.dimen
= cm
->as
->rank
;
1927 ss
->data
.info
.descriptor
= expr
;
1928 ss
->data
.info
.data
= gfc_conv_array_data (expr
);
1929 ss
->data
.info
.offset
= gfc_conv_array_offset (expr
);
1930 for (n
= 0; n
< cm
->as
->rank
; n
++)
1932 ss
->data
.info
.dim
[n
] = n
;
1933 ss
->data
.info
.start
[n
] = gfc_conv_array_lbound (expr
, n
);
1934 ss
->data
.info
.stride
[n
] = gfc_index_one_node
;
1936 mpz_init (ss
->shape
[n
]);
1937 mpz_sub (ss
->shape
[n
], cm
->as
->upper
[n
]->value
.integer
,
1938 cm
->as
->lower
[n
]->value
.integer
);
1939 mpz_add_ui (ss
->shape
[n
], ss
->shape
[n
], 1);
1942 /* Once we got ss, we use scalarizer to create the loop. */
1944 gfc_init_loopinfo (&loop
);
1945 gfc_add_ss_to_loop (&loop
, ss
);
1946 gfc_conv_ss_startstride (&loop
);
1947 gfc_conv_loop_setup (&loop
, where
);
1948 gfc_mark_ss_chain_used (ss
, 1);
1949 gfc_start_scalarized_body (&loop
, &body
);
1951 gfc_copy_loopinfo_to_se (&se
, &loop
);
1954 /* gfc_conv_tmp_array_ref assumes that se.expr contains the array. */
1956 gfc_conv_tmp_array_ref (&se
);
1958 /* Now se.expr contains an element of the array. Take the address and pass
1959 it to the IO routines. */
1960 tmp
= build_fold_addr_expr (se
.expr
);
1961 transfer_expr (&se
, &cm
->ts
, tmp
, NULL
);
1963 /* We are done now with the loop body. Wrap up the scalarizer and
1966 gfc_add_block_to_block (&body
, &se
.pre
);
1967 gfc_add_block_to_block (&body
, &se
.post
);
1969 gfc_trans_scalarizing_loops (&loop
, &body
);
1971 gfc_add_block_to_block (&block
, &loop
.pre
);
1972 gfc_add_block_to_block (&block
, &loop
.post
);
1974 for (n
= 0; n
< cm
->as
->rank
; n
++)
1975 mpz_clear (ss
->shape
[n
]);
1976 gfc_free (ss
->shape
);
1978 gfc_cleanup_loop (&loop
);
1980 return gfc_finish_block (&block
);
1983 /* Generate the call for a scalar transfer node. */
1986 transfer_expr (gfc_se
* se
, gfc_typespec
* ts
, tree addr_expr
, gfc_code
* code
)
1988 tree tmp
, function
, arg2
, arg3
, field
, expr
;
1992 /* It is possible to get a C_NULL_PTR or C_NULL_FUNPTR expression here if
1993 the user says something like: print *, 'c_null_ptr: ', c_null_ptr
1994 We need to translate the expression to a constant if it's either
1995 C_NULL_PTR or C_NULL_FUNPTR. We could also get a user variable of
1996 type C_PTR or C_FUNPTR, in which case the ts->type may no longer be
1997 BT_DERIVED (could have been changed by gfc_conv_expr). */
1998 if ((ts
->type
== BT_DERIVED
&& ts
->is_iso_c
== 1 && ts
->derived
!= NULL
)
1999 || (ts
->derived
!= NULL
&& ts
->derived
->ts
.is_iso_c
== 1))
2001 /* C_PTR and C_FUNPTR have private components which means they can not
2002 be printed. However, if -std=gnu and not -pedantic, allow
2003 the component to be printed to help debugging. */
2004 if (gfc_notification_std (GFC_STD_GNU
) != SILENT
)
2006 gfc_error_now ("Derived type '%s' at %L has PRIVATE components",
2007 ts
->derived
->name
, code
!= NULL
? &(code
->loc
) :
2008 &gfc_current_locus
);
2012 ts
->type
= ts
->derived
->ts
.type
;
2013 ts
->kind
= ts
->derived
->ts
.kind
;
2014 ts
->f90_type
= ts
->derived
->ts
.f90_type
;
2025 arg2
= build_int_cst (NULL_TREE
, kind
);
2026 function
= iocall
[IOCALL_X_INTEGER
];
2030 arg2
= build_int_cst (NULL_TREE
, kind
);
2031 function
= iocall
[IOCALL_X_REAL
];
2035 arg2
= build_int_cst (NULL_TREE
, kind
);
2036 function
= iocall
[IOCALL_X_COMPLEX
];
2040 arg2
= build_int_cst (NULL_TREE
, kind
);
2041 function
= iocall
[IOCALL_X_LOGICAL
];
2047 if (se
->string_length
)
2048 arg2
= se
->string_length
;
2051 tmp
= build_fold_indirect_ref (addr_expr
);
2052 gcc_assert (TREE_CODE (TREE_TYPE (tmp
)) == ARRAY_TYPE
);
2053 arg2
= TYPE_MAX_VALUE (TYPE_DOMAIN (TREE_TYPE (tmp
)));
2054 arg2
= fold_convert (gfc_charlen_type_node
, arg2
);
2056 arg3
= build_int_cst (NULL_TREE
, kind
);
2057 function
= iocall
[IOCALL_X_CHARACTER_WIDE
];
2058 tmp
= build_fold_addr_expr (dt_parm
);
2059 tmp
= build_call_expr (function
, 4, tmp
, addr_expr
, arg2
, arg3
);
2060 gfc_add_expr_to_block (&se
->pre
, tmp
);
2061 gfc_add_block_to_block (&se
->pre
, &se
->post
);
2066 if (se
->string_length
)
2067 arg2
= se
->string_length
;
2070 tmp
= build_fold_indirect_ref (addr_expr
);
2071 gcc_assert (TREE_CODE (TREE_TYPE (tmp
)) == ARRAY_TYPE
);
2072 arg2
= TYPE_MAX_VALUE (TYPE_DOMAIN (TREE_TYPE (tmp
)));
2074 function
= iocall
[IOCALL_X_CHARACTER
];
2078 /* Recurse into the elements of the derived type. */
2079 expr
= gfc_evaluate_now (addr_expr
, &se
->pre
);
2080 expr
= build_fold_indirect_ref (expr
);
2082 for (c
= ts
->derived
->components
; c
; c
= c
->next
)
2084 field
= c
->backend_decl
;
2085 gcc_assert (field
&& TREE_CODE (field
) == FIELD_DECL
);
2087 tmp
= fold_build3 (COMPONENT_REF
, TREE_TYPE (field
),
2088 expr
, field
, NULL_TREE
);
2090 if (c
->attr
.dimension
)
2092 tmp
= transfer_array_component (tmp
, c
, & code
->loc
);
2093 gfc_add_expr_to_block (&se
->pre
, tmp
);
2097 if (!c
->attr
.pointer
)
2098 tmp
= build_fold_addr_expr (tmp
);
2099 transfer_expr (se
, &c
->ts
, tmp
, code
);
2105 internal_error ("Bad IO basetype (%d)", ts
->type
);
2108 tmp
= build_fold_addr_expr (dt_parm
);
2109 tmp
= build_call_expr (function
, 3, tmp
, addr_expr
, arg2
);
2110 gfc_add_expr_to_block (&se
->pre
, tmp
);
2111 gfc_add_block_to_block (&se
->pre
, &se
->post
);
2116 /* Generate a call to pass an array descriptor to the IO library. The
2117 array should be of one of the intrinsic types. */
2120 transfer_array_desc (gfc_se
* se
, gfc_typespec
* ts
, tree addr_expr
)
2122 tree tmp
, charlen_arg
, kind_arg
;
2124 if (ts
->type
== BT_CHARACTER
)
2125 charlen_arg
= se
->string_length
;
2127 charlen_arg
= build_int_cst (NULL_TREE
, 0);
2129 kind_arg
= build_int_cst (NULL_TREE
, ts
->kind
);
2131 tmp
= build_fold_addr_expr (dt_parm
);
2132 tmp
= build_call_expr (iocall
[IOCALL_X_ARRAY
], 4,
2133 tmp
, addr_expr
, kind_arg
, charlen_arg
);
2134 gfc_add_expr_to_block (&se
->pre
, tmp
);
2135 gfc_add_block_to_block (&se
->pre
, &se
->post
);
2139 /* gfc_trans_transfer()-- Translate a TRANSFER code node */
2142 gfc_trans_transfer (gfc_code
* code
)
2144 stmtblock_t block
, body
;
2153 gfc_start_block (&block
);
2154 gfc_init_block (&body
);
2157 ss
= gfc_walk_expr (expr
);
2160 gfc_init_se (&se
, NULL
);
2162 if (ss
== gfc_ss_terminator
)
2164 /* Transfer a scalar value. */
2165 gfc_conv_expr_reference (&se
, expr
);
2166 transfer_expr (&se
, &expr
->ts
, se
.expr
, code
);
2170 /* Transfer an array. If it is an array of an intrinsic
2171 type, pass the descriptor to the library. Otherwise
2172 scalarize the transfer. */
2175 for (ref
= expr
->ref
; ref
&& ref
->type
!= REF_ARRAY
;
2177 gcc_assert (ref
->type
== REF_ARRAY
);
2180 if (expr
->ts
.type
!= BT_DERIVED
2181 && ref
&& ref
->next
== NULL
2182 && !is_subref_array (expr
))
2184 bool seen_vector
= false;
2186 if (ref
&& ref
->u
.ar
.type
== AR_SECTION
)
2188 for (n
= 0; n
< ref
->u
.ar
.dimen
; n
++)
2189 if (ref
->u
.ar
.dimen_type
[n
] == DIMEN_VECTOR
)
2193 if (seen_vector
&& last_dt
== READ
)
2195 /* Create a temp, read to that and copy it back. */
2196 gfc_conv_subref_array_arg (&se
, expr
, 0, INTENT_OUT
);
2201 /* Get the descriptor. */
2202 gfc_conv_expr_descriptor (&se
, expr
, ss
);
2203 tmp
= build_fold_addr_expr (se
.expr
);
2206 transfer_array_desc (&se
, &expr
->ts
, tmp
);
2207 goto finish_block_label
;
2210 /* Initialize the scalarizer. */
2211 gfc_init_loopinfo (&loop
);
2212 gfc_add_ss_to_loop (&loop
, ss
);
2214 /* Initialize the loop. */
2215 gfc_conv_ss_startstride (&loop
);
2216 gfc_conv_loop_setup (&loop
, &code
->expr
->where
);
2218 /* The main loop body. */
2219 gfc_mark_ss_chain_used (ss
, 1);
2220 gfc_start_scalarized_body (&loop
, &body
);
2222 gfc_copy_loopinfo_to_se (&se
, &loop
);
2225 gfc_conv_expr_reference (&se
, expr
);
2226 transfer_expr (&se
, &expr
->ts
, se
.expr
, code
);
2231 gfc_add_block_to_block (&body
, &se
.pre
);
2232 gfc_add_block_to_block (&body
, &se
.post
);
2235 tmp
= gfc_finish_block (&body
);
2238 gcc_assert (se
.ss
== gfc_ss_terminator
);
2239 gfc_trans_scalarizing_loops (&loop
, &body
);
2241 gfc_add_block_to_block (&loop
.pre
, &loop
.post
);
2242 tmp
= gfc_finish_block (&loop
.pre
);
2243 gfc_cleanup_loop (&loop
);
2246 gfc_add_expr_to_block (&block
, tmp
);
2248 return gfc_finish_block (&block
);
2251 #include "gt-fortran-trans-io.h"