2005-06-28 Paul Brook <paul@codesourcery.com>
[official-gcc.git] / gcc / fortran / trans-io.c
blob6680449285192315266a783f00dd3b0272872678
1 /* IO Code translation/library interface
2 Copyright (C) 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
3 Contributed by Paul Brook
5 This file is part of GCC.
7 GCC is free software; you can redistribute it and/or modify it under
8 the terms of the GNU General Public License as published by the Free
9 Software Foundation; either version 2, or (at your option) any later
10 version.
12 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
13 WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15 for more details.
17 You should have received a copy of the GNU General Public License
18 along with GCC; see the file COPYING. If not, write to the Free
19 Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
20 02110-1301, USA. */
23 #include "config.h"
24 #include "system.h"
25 #include "coretypes.h"
26 #include "tree.h"
27 #include "tree-gimple.h"
28 #include "ggc.h"
29 #include "toplev.h"
30 #include "real.h"
31 #include "gfortran.h"
32 #include "trans.h"
33 #include "trans-stmt.h"
34 #include "trans-array.h"
35 #include "trans-types.h"
36 #include "trans-const.h"
39 /* Members of the ioparm structure. */
41 static GTY(()) tree ioparm_unit;
42 static GTY(()) tree ioparm_err;
43 static GTY(()) tree ioparm_end;
44 static GTY(()) tree ioparm_eor;
45 static GTY(()) tree ioparm_list_format;
46 static GTY(()) tree ioparm_library_return;
47 static GTY(()) tree ioparm_iostat;
48 static GTY(()) tree ioparm_exist;
49 static GTY(()) tree ioparm_opened;
50 static GTY(()) tree ioparm_number;
51 static GTY(()) tree ioparm_named;
52 static GTY(()) tree ioparm_rec;
53 static GTY(()) tree ioparm_nextrec;
54 static GTY(()) tree ioparm_size;
55 static GTY(()) tree ioparm_recl_in;
56 static GTY(()) tree ioparm_recl_out;
57 static GTY(()) tree ioparm_iolength;
58 static GTY(()) tree ioparm_file;
59 static GTY(()) tree ioparm_file_len;
60 static GTY(()) tree ioparm_status;
61 static GTY(()) tree ioparm_status_len;
62 static GTY(()) tree ioparm_access;
63 static GTY(()) tree ioparm_access_len;
64 static GTY(()) tree ioparm_form;
65 static GTY(()) tree ioparm_form_len;
66 static GTY(()) tree ioparm_blank;
67 static GTY(()) tree ioparm_blank_len;
68 static GTY(()) tree ioparm_position;
69 static GTY(()) tree ioparm_position_len;
70 static GTY(()) tree ioparm_action;
71 static GTY(()) tree ioparm_action_len;
72 static GTY(()) tree ioparm_delim;
73 static GTY(()) tree ioparm_delim_len;
74 static GTY(()) tree ioparm_pad;
75 static GTY(()) tree ioparm_pad_len;
76 static GTY(()) tree ioparm_format;
77 static GTY(()) tree ioparm_format_len;
78 static GTY(()) tree ioparm_advance;
79 static GTY(()) tree ioparm_advance_len;
80 static GTY(()) tree ioparm_name;
81 static GTY(()) tree ioparm_name_len;
82 static GTY(()) tree ioparm_internal_unit;
83 static GTY(()) tree ioparm_internal_unit_len;
84 static GTY(()) tree ioparm_sequential;
85 static GTY(()) tree ioparm_sequential_len;
86 static GTY(()) tree ioparm_direct;
87 static GTY(()) tree ioparm_direct_len;
88 static GTY(()) tree ioparm_formatted;
89 static GTY(()) tree ioparm_formatted_len;
90 static GTY(()) tree ioparm_unformatted;
91 static GTY(()) tree ioparm_unformatted_len;
92 static GTY(()) tree ioparm_read;
93 static GTY(()) tree ioparm_read_len;
94 static GTY(()) tree ioparm_write;
95 static GTY(()) tree ioparm_write_len;
96 static GTY(()) tree ioparm_readwrite;
97 static GTY(()) tree ioparm_readwrite_len;
98 static GTY(()) tree ioparm_namelist_name;
99 static GTY(()) tree ioparm_namelist_name_len;
100 static GTY(()) tree ioparm_namelist_read_mode;
102 /* The global I/O variables */
104 static GTY(()) tree ioparm_var;
105 static GTY(()) tree locus_file;
106 static GTY(()) tree locus_line;
109 /* Library I/O subroutines */
111 static GTY(()) tree iocall_read;
112 static GTY(()) tree iocall_read_done;
113 static GTY(()) tree iocall_write;
114 static GTY(()) tree iocall_write_done;
115 static GTY(()) tree iocall_x_integer;
116 static GTY(()) tree iocall_x_logical;
117 static GTY(()) tree iocall_x_character;
118 static GTY(()) tree iocall_x_real;
119 static GTY(()) tree iocall_x_complex;
120 static GTY(()) tree iocall_open;
121 static GTY(()) tree iocall_close;
122 static GTY(()) tree iocall_inquire;
123 static GTY(()) tree iocall_iolength;
124 static GTY(()) tree iocall_iolength_done;
125 static GTY(()) tree iocall_rewind;
126 static GTY(()) tree iocall_backspace;
127 static GTY(()) tree iocall_endfile;
128 static GTY(()) tree iocall_set_nml_val;
129 static GTY(()) tree iocall_set_nml_val_dim;
131 /* Variable for keeping track of what the last data transfer statement
132 was. Used for deciding which subroutine to call when the data
133 transfer is complete. */
134 static enum { READ, WRITE, IOLENGTH } last_dt;
136 #define ADD_FIELD(name, type) \
137 ioparm_ ## name = gfc_add_field_to_struct \
138 (&(TYPE_FIELDS (ioparm_type)), ioparm_type, \
139 get_identifier (stringize(name)), type)
141 #define ADD_STRING(name) \
142 ioparm_ ## name = gfc_add_field_to_struct \
143 (&(TYPE_FIELDS (ioparm_type)), ioparm_type, \
144 get_identifier (stringize(name)), pchar_type_node); \
145 ioparm_ ## name ## _len = gfc_add_field_to_struct \
146 (&(TYPE_FIELDS (ioparm_type)), ioparm_type, \
147 get_identifier (stringize(name) "_len"), gfc_charlen_type_node)
150 /* Create function decls for IO library functions. */
152 void
153 gfc_build_io_library_fndecls (void)
155 tree gfc_int4_type_node;
156 tree gfc_pint4_type_node;
157 tree ioparm_type;
159 gfc_int4_type_node = gfc_get_int_type (4);
160 gfc_pint4_type_node = build_pointer_type (gfc_int4_type_node);
162 /* Build the st_parameter structure. Information associated with I/O
163 calls are transferred here. This must match the one defined in the
164 library exactly. */
166 ioparm_type = make_node (RECORD_TYPE);
167 TYPE_NAME (ioparm_type) = get_identifier ("_gfc_ioparm");
169 ADD_FIELD (unit, gfc_int4_type_node);
170 ADD_FIELD (err, gfc_int4_type_node);
171 ADD_FIELD (end, gfc_int4_type_node);
172 ADD_FIELD (eor, gfc_int4_type_node);
173 ADD_FIELD (list_format, gfc_int4_type_node);
174 ADD_FIELD (library_return, gfc_int4_type_node);
176 ADD_FIELD (iostat, gfc_pint4_type_node);
177 ADD_FIELD (exist, gfc_pint4_type_node);
178 ADD_FIELD (opened, gfc_pint4_type_node);
179 ADD_FIELD (number, gfc_pint4_type_node);
180 ADD_FIELD (named, gfc_pint4_type_node);
181 ADD_FIELD (rec, gfc_int4_type_node);
182 ADD_FIELD (nextrec, gfc_pint4_type_node);
183 ADD_FIELD (size, gfc_pint4_type_node);
185 ADD_FIELD (recl_in, gfc_int4_type_node);
186 ADD_FIELD (recl_out, gfc_pint4_type_node);
188 ADD_FIELD (iolength, gfc_pint4_type_node);
190 ADD_STRING (file);
191 ADD_STRING (status);
193 ADD_STRING (access);
194 ADD_STRING (form);
195 ADD_STRING (blank);
196 ADD_STRING (position);
197 ADD_STRING (action);
198 ADD_STRING (delim);
199 ADD_STRING (pad);
200 ADD_STRING (format);
201 ADD_STRING (advance);
202 ADD_STRING (name);
203 ADD_STRING (internal_unit);
204 ADD_STRING (sequential);
206 ADD_STRING (direct);
207 ADD_STRING (formatted);
208 ADD_STRING (unformatted);
209 ADD_STRING (read);
210 ADD_STRING (write);
211 ADD_STRING (readwrite);
213 ADD_STRING (namelist_name);
214 ADD_FIELD (namelist_read_mode, gfc_int4_type_node);
216 gfc_finish_type (ioparm_type);
218 ioparm_var = build_decl (VAR_DECL, get_identifier (PREFIX("ioparm")),
219 ioparm_type);
220 DECL_EXTERNAL (ioparm_var) = 1;
221 TREE_PUBLIC (ioparm_var) = 1;
223 locus_line = build_decl (VAR_DECL, get_identifier (PREFIX("line")),
224 gfc_int4_type_node);
225 DECL_EXTERNAL (locus_line) = 1;
226 TREE_PUBLIC (locus_line) = 1;
228 locus_file = build_decl (VAR_DECL, get_identifier (PREFIX("filename")),
229 pchar_type_node);
230 DECL_EXTERNAL (locus_file) = 1;
231 TREE_PUBLIC (locus_file) = 1;
233 /* Define the transfer functions. */
235 iocall_x_integer =
236 gfc_build_library_function_decl (get_identifier
237 (PREFIX("transfer_integer")),
238 void_type_node, 2, pvoid_type_node,
239 gfc_int4_type_node);
241 iocall_x_logical =
242 gfc_build_library_function_decl (get_identifier
243 (PREFIX("transfer_logical")),
244 void_type_node, 2, pvoid_type_node,
245 gfc_int4_type_node);
247 iocall_x_character =
248 gfc_build_library_function_decl (get_identifier
249 (PREFIX("transfer_character")),
250 void_type_node, 2, pvoid_type_node,
251 gfc_int4_type_node);
253 iocall_x_real =
254 gfc_build_library_function_decl (get_identifier (PREFIX("transfer_real")),
255 void_type_node, 2,
256 pvoid_type_node, gfc_int4_type_node);
258 iocall_x_complex =
259 gfc_build_library_function_decl (get_identifier
260 (PREFIX("transfer_complex")),
261 void_type_node, 2, pvoid_type_node,
262 gfc_int4_type_node);
264 /* Library entry points */
266 iocall_read =
267 gfc_build_library_function_decl (get_identifier (PREFIX("st_read")),
268 void_type_node, 0);
270 iocall_write =
271 gfc_build_library_function_decl (get_identifier (PREFIX("st_write")),
272 void_type_node, 0);
273 iocall_open =
274 gfc_build_library_function_decl (get_identifier (PREFIX("st_open")),
275 void_type_node, 0);
277 iocall_close =
278 gfc_build_library_function_decl (get_identifier (PREFIX("st_close")),
279 void_type_node, 0);
281 iocall_inquire =
282 gfc_build_library_function_decl (get_identifier (PREFIX("st_inquire")),
283 gfc_int4_type_node, 0);
285 iocall_iolength =
286 gfc_build_library_function_decl(get_identifier (PREFIX("st_iolength")),
287 void_type_node, 0);
289 iocall_rewind =
290 gfc_build_library_function_decl (get_identifier (PREFIX("st_rewind")),
291 gfc_int4_type_node, 0);
293 iocall_backspace =
294 gfc_build_library_function_decl (get_identifier (PREFIX("st_backspace")),
295 gfc_int4_type_node, 0);
297 iocall_endfile =
298 gfc_build_library_function_decl (get_identifier (PREFIX("st_endfile")),
299 gfc_int4_type_node, 0);
300 /* Library helpers */
302 iocall_read_done =
303 gfc_build_library_function_decl (get_identifier (PREFIX("st_read_done")),
304 gfc_int4_type_node, 0);
306 iocall_write_done =
307 gfc_build_library_function_decl (get_identifier (PREFIX("st_write_done")),
308 gfc_int4_type_node, 0);
310 iocall_iolength_done =
311 gfc_build_library_function_decl (get_identifier (PREFIX("st_iolength_done")),
312 gfc_int4_type_node, 0);
315 iocall_set_nml_val =
316 gfc_build_library_function_decl (get_identifier (PREFIX("st_set_nml_var")),
317 void_type_node, 5,
318 pvoid_type_node, pvoid_type_node,
319 gfc_int4_type_node, gfc_charlen_type_node,
320 gfc_int4_type_node);
322 iocall_set_nml_val_dim =
323 gfc_build_library_function_decl (get_identifier (PREFIX("st_set_nml_var_dim")),
324 void_type_node, 4,
325 gfc_int4_type_node, gfc_int4_type_node,
326 gfc_int4_type_node, gfc_int4_type_node);
330 /* Generate code to store an non-string I/O parameter into the
331 ioparm structure. This is a pass by value. */
333 static void
334 set_parameter_value (stmtblock_t * block, tree var, gfc_expr * e)
336 gfc_se se;
337 tree tmp;
339 gfc_init_se (&se, NULL);
340 gfc_conv_expr_type (&se, e, TREE_TYPE (var));
341 gfc_add_block_to_block (block, &se.pre);
343 tmp = build3 (COMPONENT_REF, TREE_TYPE (var), ioparm_var, var, NULL_TREE);
344 gfc_add_modify_expr (block, tmp, se.expr);
348 /* Generate code to store an non-string I/O parameter into the
349 ioparm structure. This is pass by reference. */
351 static void
352 set_parameter_ref (stmtblock_t * block, tree var, gfc_expr * e)
354 gfc_se se;
355 tree tmp;
357 gfc_init_se (&se, NULL);
358 se.want_pointer = 1;
360 gfc_conv_expr_type (&se, e, TREE_TYPE (var));
361 gfc_add_block_to_block (block, &se.pre);
363 tmp = build3 (COMPONENT_REF, TREE_TYPE (var), ioparm_var, var, NULL_TREE);
364 gfc_add_modify_expr (block, tmp, se.expr);
368 /* Generate code to store a string and its length into the
369 ioparm structure. */
371 static void
372 set_string (stmtblock_t * block, stmtblock_t * postblock, tree var,
373 tree var_len, gfc_expr * e)
375 gfc_se se;
376 tree tmp;
377 tree msg;
378 tree io;
379 tree len;
381 gfc_init_se (&se, NULL);
383 io = build3 (COMPONENT_REF, TREE_TYPE (var), ioparm_var, var, NULL_TREE);
384 len = build3 (COMPONENT_REF, TREE_TYPE (var_len), ioparm_var, var_len,
385 NULL_TREE);
387 /* Integer variable assigned a format label. */
388 if (e->ts.type == BT_INTEGER && e->symtree->n.sym->attr.assign == 1)
390 gfc_conv_label_variable (&se, e);
391 msg =
392 gfc_build_cstring_const ("Assigned label is not a format label");
393 tmp = GFC_DECL_STRING_LEN (se.expr);
394 tmp = build2 (LE_EXPR, boolean_type_node,
395 tmp, convert (TREE_TYPE (tmp), integer_minus_one_node));
396 gfc_trans_runtime_check (tmp, msg, &se.pre);
397 gfc_add_modify_expr (&se.pre, io,
398 fold_convert (TREE_TYPE (io), GFC_DECL_ASSIGN_ADDR (se.expr)));
399 gfc_add_modify_expr (&se.pre, len, GFC_DECL_STRING_LEN (se.expr));
401 else
403 gfc_conv_expr (&se, e);
404 gfc_conv_string_parameter (&se);
405 gfc_add_modify_expr (&se.pre, io, fold_convert (TREE_TYPE (io), se.expr));
406 gfc_add_modify_expr (&se.pre, len, se.string_length);
409 gfc_add_block_to_block (block, &se.pre);
410 gfc_add_block_to_block (postblock, &se.post);
415 /* Set a member of the ioparm structure to one. */
416 static void
417 set_flag (stmtblock_t *block, tree var)
419 tree tmp, type = TREE_TYPE (var);
421 tmp = build3 (COMPONENT_REF, type, ioparm_var, var, NULL_TREE);
422 gfc_add_modify_expr (block, tmp, convert (type, integer_one_node));
426 /* Add a case to a IO-result switch. */
428 static void
429 add_case (int label_value, gfc_st_label * label, stmtblock_t * body)
431 tree tmp, value;
433 if (label == NULL)
434 return; /* No label, no case */
436 value = build_int_cst (NULL_TREE, label_value);
438 /* Make a backend label for this case. */
439 tmp = gfc_build_label_decl (NULL_TREE);
441 /* And the case itself. */
442 tmp = build3_v (CASE_LABEL_EXPR, value, NULL_TREE, tmp);
443 gfc_add_expr_to_block (body, tmp);
445 /* Jump to the label. */
446 tmp = build1_v (GOTO_EXPR, gfc_get_label_decl (label));
447 gfc_add_expr_to_block (body, tmp);
451 /* Generate a switch statement that branches to the correct I/O
452 result label. The last statement of an I/O call stores the
453 result into a variable because there is often cleanup that
454 must be done before the switch, so a temporary would have to
455 be created anyway. */
457 static void
458 io_result (stmtblock_t * block, gfc_st_label * err_label,
459 gfc_st_label * end_label, gfc_st_label * eor_label)
461 stmtblock_t body;
462 tree tmp, rc;
464 /* If no labels are specified, ignore the result instead
465 of building an empty switch. */
466 if (err_label == NULL
467 && end_label == NULL
468 && eor_label == NULL)
469 return;
471 /* Build a switch statement. */
472 gfc_start_block (&body);
474 /* The label values here must be the same as the values
475 in the library_return enum in the runtime library */
476 add_case (1, err_label, &body);
477 add_case (2, end_label, &body);
478 add_case (3, eor_label, &body);
480 tmp = gfc_finish_block (&body);
482 rc = build3 (COMPONENT_REF, TREE_TYPE (ioparm_library_return), ioparm_var,
483 ioparm_library_return, NULL_TREE);
485 tmp = build3_v (SWITCH_EXPR, rc, tmp, NULL_TREE);
487 gfc_add_expr_to_block (block, tmp);
491 /* Store the current file and line number to variables so that if a
492 library call goes awry, we can tell the user where the problem is. */
494 static void
495 set_error_locus (stmtblock_t * block, locus * where)
497 gfc_file *f;
498 tree tmp;
499 int line;
501 f = where->lb->file;
502 tmp = gfc_build_cstring_const (f->filename);
504 tmp = gfc_build_addr_expr (pchar_type_node, tmp);
505 gfc_add_modify_expr (block, locus_file, tmp);
507 #ifdef USE_MAPPED_LOCATION
508 line = LOCATION_LINE (where->lb->location);
509 #else
510 line = where->lb->linenum;
511 #endif
512 gfc_add_modify_expr (block, locus_line, build_int_cst (NULL_TREE, line));
516 /* Translate an OPEN statement. */
518 tree
519 gfc_trans_open (gfc_code * code)
521 stmtblock_t block, post_block;
522 gfc_open *p;
523 tree tmp;
525 gfc_init_block (&block);
526 gfc_init_block (&post_block);
528 set_error_locus (&block, &code->loc);
529 p = code->ext.open;
531 if (p->unit)
532 set_parameter_value (&block, ioparm_unit, p->unit);
534 if (p->file)
535 set_string (&block, &post_block, ioparm_file, ioparm_file_len, p->file);
537 if (p->status)
538 set_string (&block, &post_block, ioparm_status,
539 ioparm_status_len, p->status);
541 if (p->access)
542 set_string (&block, &post_block, ioparm_access,
543 ioparm_access_len, p->access);
545 if (p->form)
546 set_string (&block, &post_block, ioparm_form, ioparm_form_len, p->form);
548 if (p->recl)
549 set_parameter_value (&block, ioparm_recl_in, p->recl);
551 if (p->blank)
552 set_string (&block, &post_block, ioparm_blank, ioparm_blank_len,
553 p->blank);
555 if (p->position)
556 set_string (&block, &post_block, ioparm_position,
557 ioparm_position_len, p->position);
559 if (p->action)
560 set_string (&block, &post_block, ioparm_action,
561 ioparm_action_len, p->action);
563 if (p->delim)
564 set_string (&block, &post_block, ioparm_delim, ioparm_delim_len,
565 p->delim);
567 if (p->pad)
568 set_string (&block, &post_block, ioparm_pad, ioparm_pad_len, p->pad);
570 if (p->iostat)
571 set_parameter_ref (&block, ioparm_iostat, p->iostat);
573 if (p->err)
574 set_flag (&block, ioparm_err);
576 tmp = gfc_build_function_call (iocall_open, NULL_TREE);
577 gfc_add_expr_to_block (&block, tmp);
579 gfc_add_block_to_block (&block, &post_block);
581 io_result (&block, p->err, NULL, NULL);
583 return gfc_finish_block (&block);
587 /* Translate a CLOSE statement. */
589 tree
590 gfc_trans_close (gfc_code * code)
592 stmtblock_t block, post_block;
593 gfc_close *p;
594 tree tmp;
596 gfc_init_block (&block);
597 gfc_init_block (&post_block);
599 set_error_locus (&block, &code->loc);
600 p = code->ext.close;
602 if (p->unit)
603 set_parameter_value (&block, ioparm_unit, p->unit);
605 if (p->status)
606 set_string (&block, &post_block, ioparm_status,
607 ioparm_status_len, p->status);
609 if (p->iostat)
610 set_parameter_ref (&block, ioparm_iostat, p->iostat);
612 if (p->err)
613 set_flag (&block, ioparm_err);
615 tmp = gfc_build_function_call (iocall_close, NULL_TREE);
616 gfc_add_expr_to_block (&block, tmp);
618 gfc_add_block_to_block (&block, &post_block);
620 io_result (&block, p->err, NULL, NULL);
622 return gfc_finish_block (&block);
626 /* Common subroutine for building a file positioning statement. */
628 static tree
629 build_filepos (tree function, gfc_code * code)
631 stmtblock_t block;
632 gfc_filepos *p;
633 tree tmp;
635 p = code->ext.filepos;
637 gfc_init_block (&block);
639 set_error_locus (&block, &code->loc);
641 if (p->unit)
642 set_parameter_value (&block, ioparm_unit, p->unit);
644 if (p->iostat)
645 set_parameter_ref (&block, ioparm_iostat, p->iostat);
647 if (p->err)
648 set_flag (&block, ioparm_err);
650 tmp = gfc_build_function_call (function, NULL);
651 gfc_add_expr_to_block (&block, tmp);
653 io_result (&block, p->err, NULL, NULL);
655 return gfc_finish_block (&block);
659 /* Translate a BACKSPACE statement. */
661 tree
662 gfc_trans_backspace (gfc_code * code)
665 return build_filepos (iocall_backspace, code);
669 /* Translate an ENDFILE statement. */
671 tree
672 gfc_trans_endfile (gfc_code * code)
675 return build_filepos (iocall_endfile, code);
679 /* Translate a REWIND statement. */
681 tree
682 gfc_trans_rewind (gfc_code * code)
685 return build_filepos (iocall_rewind, code);
689 /* Translate the non-IOLENGTH form of an INQUIRE statement. */
691 tree
692 gfc_trans_inquire (gfc_code * code)
694 stmtblock_t block, post_block;
695 gfc_inquire *p;
696 tree tmp;
698 gfc_init_block (&block);
699 gfc_init_block (&post_block);
701 set_error_locus (&block, &code->loc);
702 p = code->ext.inquire;
704 if (p->unit)
705 set_parameter_value (&block, ioparm_unit, p->unit);
707 if (p->file)
708 set_string (&block, &post_block, ioparm_file, ioparm_file_len, p->file);
710 if (p->iostat)
711 set_parameter_ref (&block, ioparm_iostat, p->iostat);
713 if (p->exist)
714 set_parameter_ref (&block, ioparm_exist, p->exist);
716 if (p->opened)
717 set_parameter_ref (&block, ioparm_opened, p->opened);
719 if (p->number)
720 set_parameter_ref (&block, ioparm_number, p->number);
722 if (p->named)
723 set_parameter_ref (&block, ioparm_named, p->named);
725 if (p->name)
726 set_string (&block, &post_block, ioparm_name, ioparm_name_len, p->name);
728 if (p->access)
729 set_string (&block, &post_block, ioparm_access,
730 ioparm_access_len, p->access);
732 if (p->sequential)
733 set_string (&block, &post_block, ioparm_sequential,
734 ioparm_sequential_len, p->sequential);
736 if (p->direct)
737 set_string (&block, &post_block, ioparm_direct,
738 ioparm_direct_len, p->direct);
740 if (p->form)
741 set_string (&block, &post_block, ioparm_form, ioparm_form_len, p->form);
743 if (p->formatted)
744 set_string (&block, &post_block, ioparm_formatted,
745 ioparm_formatted_len, p->formatted);
747 if (p->unformatted)
748 set_string (&block, &post_block, ioparm_unformatted,
749 ioparm_unformatted_len, p->unformatted);
751 if (p->recl)
752 set_parameter_ref (&block, ioparm_recl_out, p->recl);
754 if (p->nextrec)
755 set_parameter_ref (&block, ioparm_nextrec, p->nextrec);
757 if (p->blank)
758 set_string (&block, &post_block, ioparm_blank, ioparm_blank_len,
759 p->blank);
761 if (p->position)
762 set_string (&block, &post_block, ioparm_position,
763 ioparm_position_len, p->position);
765 if (p->action)
766 set_string (&block, &post_block, ioparm_action,
767 ioparm_action_len, p->action);
769 if (p->read)
770 set_string (&block, &post_block, ioparm_read, ioparm_read_len, p->read);
772 if (p->write)
773 set_string (&block, &post_block, ioparm_write,
774 ioparm_write_len, p->write);
776 if (p->readwrite)
777 set_string (&block, &post_block, ioparm_readwrite,
778 ioparm_readwrite_len, p->readwrite);
780 if (p->delim)
781 set_string (&block, &post_block, ioparm_delim, ioparm_delim_len,
782 p->delim);
784 if (p->pad)
785 set_string (&block, &post_block, ioparm_pad, ioparm_pad_len,
786 p->pad);
788 if (p->err)
789 set_flag (&block, ioparm_err);
791 tmp = gfc_build_function_call (iocall_inquire, NULL);
792 gfc_add_expr_to_block (&block, tmp);
794 gfc_add_block_to_block (&block, &post_block);
796 io_result (&block, p->err, NULL, NULL);
798 return gfc_finish_block (&block);
801 static gfc_expr *
802 gfc_new_nml_name_expr (const char * name)
804 gfc_expr * nml_name;
806 nml_name = gfc_get_expr();
807 nml_name->ref = NULL;
808 nml_name->expr_type = EXPR_CONSTANT;
809 nml_name->ts.kind = gfc_default_character_kind;
810 nml_name->ts.type = BT_CHARACTER;
811 nml_name->value.character.length = strlen(name);
812 nml_name->value.character.string = gfc_getmem (strlen (name) + 1);
813 strcpy (nml_name->value.character.string, name);
815 return nml_name;
818 /* nml_full_name builds up the fully qualified name of a
819 derived type component. */
821 static char*
822 nml_full_name (const char* var_name, const char* cmp_name)
824 int full_name_length;
825 char * full_name;
827 full_name_length = strlen (var_name) + strlen (cmp_name) + 1;
828 full_name = (char*)gfc_getmem (full_name_length + 1);
829 strcpy (full_name, var_name);
830 full_name = strcat (full_name, "%");
831 full_name = strcat (full_name, cmp_name);
832 return full_name;
835 /* nml_get_addr_expr builds an address expression from the
836 gfc_symbol or gfc_component backend_decl's. An offset is
837 provided so that the address of an element of an array of
838 derived types is returned. This is used in the runtime to
839 determine that span of the derived type. */
841 static tree
842 nml_get_addr_expr (gfc_symbol * sym, gfc_component * c,
843 tree base_addr)
845 tree decl = NULL_TREE;
846 tree tmp;
847 tree itmp;
848 int array_flagged;
849 int dummy_arg_flagged;
851 if (sym)
853 sym->attr.referenced = 1;
854 decl = gfc_get_symbol_decl (sym);
856 else
857 decl = c->backend_decl;
859 gcc_assert (decl && ((TREE_CODE (decl) == FIELD_DECL
860 || TREE_CODE (decl) == VAR_DECL
861 || TREE_CODE (decl) == PARM_DECL)
862 || TREE_CODE (decl) == COMPONENT_REF));
864 tmp = decl;
866 /* Build indirect reference, if dummy argument. */
868 dummy_arg_flagged = POINTER_TYPE_P (TREE_TYPE(tmp));
870 itmp = (dummy_arg_flagged) ? gfc_build_indirect_ref (tmp) : tmp;
872 /* If an array, set flag and use indirect ref. if built. */
874 array_flagged = (TREE_CODE (TREE_TYPE (itmp)) == ARRAY_TYPE
875 && !TYPE_STRING_FLAG (TREE_TYPE (itmp)));
877 if (array_flagged)
878 tmp = itmp;
880 /* Treat the component of a derived type, using base_addr for
881 the derived type. */
883 if (TREE_CODE (decl) == FIELD_DECL)
884 tmp = build3 (COMPONENT_REF, TREE_TYPE (tmp),
885 base_addr, tmp, NULL_TREE);
887 /* If we have a derived type component, a reference to the first
888 element of the array is built. This is done so that base_addr,
889 used in the build of the component reference, always points to
890 a RECORD_TYPE. */
892 if (array_flagged)
893 tmp = gfc_build_array_ref (tmp, gfc_index_zero_node);
895 /* Now build the address expression. */
897 tmp = gfc_build_addr_expr (NULL, tmp);
899 /* If scalar dummy, resolve indirect reference now. */
901 if (dummy_arg_flagged && !array_flagged)
902 tmp = gfc_build_indirect_ref (tmp);
904 gcc_assert (tmp && POINTER_TYPE_P (TREE_TYPE (tmp)));
906 return tmp;
909 /* For an object VAR_NAME whose base address is BASE_ADDR, generate a
910 call to iocall_set_nml_val. For derived type variable, recursively
911 generate calls to iocall_set_nml_val for each component. */
913 #define NML_FIRST_ARG(a) args = gfc_chainon_list (NULL_TREE, a)
914 #define NML_ADD_ARG(a) args = gfc_chainon_list (args, a)
915 #define IARG(i) build_int_cst (gfc_array_index_type, i)
917 static void
918 transfer_namelist_element (stmtblock_t * block, const char * var_name,
919 gfc_symbol * sym, gfc_component * c,
920 tree base_addr)
922 gfc_typespec * ts = NULL;
923 gfc_array_spec * as = NULL;
924 tree addr_expr = NULL;
925 tree dt = NULL;
926 tree string;
927 tree tmp;
928 tree args;
929 tree dtype;
930 int n_dim;
931 int itype;
932 int rank = 0;
934 gcc_assert (sym || c);
936 /* Build the namelist object name. */
938 string = gfc_build_cstring_const (var_name);
939 string = gfc_build_addr_expr (pchar_type_node, string);
941 /* Build ts, as and data address using symbol or component. */
943 ts = (sym) ? &sym->ts : &c->ts;
944 as = (sym) ? sym->as : c->as;
946 addr_expr = nml_get_addr_expr (sym, c, base_addr);
948 if (as)
949 rank = as->rank;
951 if (rank)
953 dt = TREE_TYPE ((sym) ? sym->backend_decl : c->backend_decl);
954 dtype = gfc_get_dtype (dt);
956 else
958 itype = GFC_DTYPE_UNKNOWN;
960 switch (ts->type)
963 case BT_INTEGER:
964 itype = GFC_DTYPE_INTEGER;
965 break;
966 case BT_LOGICAL:
967 itype = GFC_DTYPE_LOGICAL;
968 break;
969 case BT_REAL:
970 itype = GFC_DTYPE_REAL;
971 break;
972 case BT_COMPLEX:
973 itype = GFC_DTYPE_COMPLEX;
974 break;
975 case BT_DERIVED:
976 itype = GFC_DTYPE_DERIVED;
977 break;
978 case BT_CHARACTER:
979 itype = GFC_DTYPE_CHARACTER;
980 break;
981 default:
982 gcc_unreachable ();
985 dtype = IARG (itype << GFC_DTYPE_TYPE_SHIFT);
988 /* Build up the arguments for the transfer call.
989 The call for the scalar part transfers:
990 (address, name, type, kind or string_length, dtype) */
992 NML_FIRST_ARG (addr_expr);
993 NML_ADD_ARG (string);
994 NML_ADD_ARG (IARG (ts->kind));
996 if (ts->type == BT_CHARACTER)
997 NML_ADD_ARG (ts->cl->backend_decl);
998 else
999 NML_ADD_ARG (convert (gfc_charlen_type_node, integer_zero_node));
1001 NML_ADD_ARG (dtype);
1002 tmp = gfc_build_function_call (iocall_set_nml_val, args);
1003 gfc_add_expr_to_block (block, tmp);
1005 /* If the object is an array, transfer rank times:
1006 (null pointer, name, stride, lbound, ubound) */
1008 for ( n_dim = 0 ; n_dim < rank ; n_dim++ )
1010 NML_FIRST_ARG (IARG (n_dim));
1011 NML_ADD_ARG (GFC_TYPE_ARRAY_STRIDE (dt, n_dim));
1012 NML_ADD_ARG (GFC_TYPE_ARRAY_LBOUND (dt, n_dim));
1013 NML_ADD_ARG (GFC_TYPE_ARRAY_UBOUND (dt, n_dim));
1014 tmp = gfc_build_function_call (iocall_set_nml_val_dim, args);
1015 gfc_add_expr_to_block (block, tmp);
1018 if (ts->type == BT_DERIVED)
1020 gfc_component *cmp;
1022 /* Provide the RECORD_TYPE to build component references. */
1024 tree expr = gfc_build_indirect_ref (addr_expr);
1026 for (cmp = ts->derived->components; cmp; cmp = cmp->next)
1028 char *full_name = nml_full_name (var_name, cmp->name);
1029 transfer_namelist_element (block,
1030 full_name,
1031 NULL, cmp, expr);
1032 gfc_free (full_name);
1037 #undef IARG
1038 #undef NML_ADD_ARG
1039 #undef NML_FIRST_ARG
1041 /* Create a data transfer statement. Not all of the fields are valid
1042 for both reading and writing, but improper use has been filtered
1043 out by now. */
1045 static tree
1046 build_dt (tree * function, gfc_code * code)
1048 stmtblock_t block, post_block;
1049 gfc_dt *dt;
1050 tree tmp;
1051 gfc_expr *nmlname;
1052 gfc_namelist *nml;
1054 gfc_init_block (&block);
1055 gfc_init_block (&post_block);
1057 set_error_locus (&block, &code->loc);
1058 dt = code->ext.dt;
1060 gcc_assert (dt != NULL);
1062 if (dt->io_unit)
1064 if (dt->io_unit->ts.type == BT_CHARACTER)
1066 set_string (&block, &post_block, ioparm_internal_unit,
1067 ioparm_internal_unit_len, dt->io_unit);
1069 else
1070 set_parameter_value (&block, ioparm_unit, dt->io_unit);
1073 if (dt->rec)
1074 set_parameter_value (&block, ioparm_rec, dt->rec);
1076 if (dt->advance)
1077 set_string (&block, &post_block, ioparm_advance, ioparm_advance_len,
1078 dt->advance);
1080 if (dt->format_expr)
1081 set_string (&block, &post_block, ioparm_format, ioparm_format_len,
1082 dt->format_expr);
1084 if (dt->format_label)
1086 if (dt->format_label == &format_asterisk)
1087 set_flag (&block, ioparm_list_format);
1088 else
1089 set_string (&block, &post_block, ioparm_format,
1090 ioparm_format_len, dt->format_label->format);
1093 if (dt->iostat)
1094 set_parameter_ref (&block, ioparm_iostat, dt->iostat);
1096 if (dt->size)
1097 set_parameter_ref (&block, ioparm_size, dt->size);
1099 if (dt->err)
1100 set_flag (&block, ioparm_err);
1102 if (dt->eor)
1103 set_flag(&block, ioparm_eor);
1105 if (dt->end)
1106 set_flag(&block, ioparm_end);
1108 if (dt->namelist)
1110 if (dt->format_expr || dt->format_label)
1111 gfc_internal_error ("build_dt: format with namelist");
1113 nmlname = gfc_new_nml_name_expr(dt->namelist->name);
1115 set_string (&block, &post_block, ioparm_namelist_name,
1116 ioparm_namelist_name_len, nmlname);
1118 if (last_dt == READ)
1119 set_flag (&block, ioparm_namelist_read_mode);
1121 for (nml = dt->namelist->namelist; nml; nml = nml->next)
1122 transfer_namelist_element (&block, nml->sym->name, nml->sym,
1123 NULL, NULL);
1126 tmp = gfc_build_function_call (*function, NULL_TREE);
1127 gfc_add_expr_to_block (&block, tmp);
1129 gfc_add_block_to_block (&block, &post_block);
1131 return gfc_finish_block (&block);
1135 /* Translate the IOLENGTH form of an INQUIRE statement. We treat
1136 this as a third sort of data transfer statement, except that
1137 lengths are summed instead of actually transferring any data. */
1139 tree
1140 gfc_trans_iolength (gfc_code * code)
1142 stmtblock_t block;
1143 gfc_inquire *inq;
1144 tree dt;
1146 gfc_init_block (&block);
1148 set_error_locus (&block, &code->loc);
1150 inq = code->ext.inquire;
1152 /* First check that preconditions are met. */
1153 gcc_assert (inq != NULL);
1154 gcc_assert (inq->iolength != NULL);
1156 /* Connect to the iolength variable. */
1157 if (inq->iolength)
1158 set_parameter_ref (&block, ioparm_iolength, inq->iolength);
1160 /* Actual logic. */
1161 last_dt = IOLENGTH;
1162 dt = build_dt(&iocall_iolength, code);
1164 gfc_add_expr_to_block (&block, dt);
1166 return gfc_finish_block (&block);
1170 /* Translate a READ statement. */
1172 tree
1173 gfc_trans_read (gfc_code * code)
1176 last_dt = READ;
1177 return build_dt (&iocall_read, code);
1181 /* Translate a WRITE statement */
1183 tree
1184 gfc_trans_write (gfc_code * code)
1187 last_dt = WRITE;
1188 return build_dt (&iocall_write, code);
1192 /* Finish a data transfer statement. */
1194 tree
1195 gfc_trans_dt_end (gfc_code * code)
1197 tree function, tmp;
1198 stmtblock_t block;
1200 gfc_init_block (&block);
1202 switch (last_dt)
1204 case READ:
1205 function = iocall_read_done;
1206 break;
1208 case WRITE:
1209 function = iocall_write_done;
1210 break;
1212 case IOLENGTH:
1213 function = iocall_iolength_done;
1214 break;
1216 default:
1217 gcc_unreachable ();
1220 tmp = gfc_build_function_call (function, NULL);
1221 gfc_add_expr_to_block (&block, tmp);
1223 if (last_dt != IOLENGTH)
1225 gcc_assert (code->ext.dt != NULL);
1226 io_result (&block, code->ext.dt->err,
1227 code->ext.dt->end, code->ext.dt->eor);
1230 return gfc_finish_block (&block);
1233 static void
1234 transfer_expr (gfc_se * se, gfc_typespec * ts, tree addr_expr);
1236 /* Given an array field in a derived type variable, generate the code
1237 for the loop that iterates over array elements, and the code that
1238 accesses those array elements. Use transfer_expr to generate code
1239 for transferring that element. Because elements may also be
1240 derived types, transfer_expr and transfer_array_component are mutually
1241 recursive. */
1243 static tree
1244 transfer_array_component (tree expr, gfc_component * cm)
1246 tree tmp;
1247 stmtblock_t body;
1248 stmtblock_t block;
1249 gfc_loopinfo loop;
1250 int n;
1251 gfc_ss *ss;
1252 gfc_se se;
1254 gfc_start_block (&block);
1255 gfc_init_se (&se, NULL);
1257 /* Create and initialize Scalarization Status. Unlike in
1258 gfc_trans_transfer, we can't simply use gfc_walk_expr to take
1259 care of this task, because we don't have a gfc_expr at hand.
1260 Build one manually, as in gfc_trans_subarray_assign. */
1262 ss = gfc_get_ss ();
1263 ss->type = GFC_SS_COMPONENT;
1264 ss->expr = NULL;
1265 ss->shape = gfc_get_shape (cm->as->rank);
1266 ss->next = gfc_ss_terminator;
1267 ss->data.info.dimen = cm->as->rank;
1268 ss->data.info.descriptor = expr;
1269 ss->data.info.data = gfc_conv_array_data (expr);
1270 ss->data.info.offset = gfc_conv_array_offset (expr);
1271 for (n = 0; n < cm->as->rank; n++)
1273 ss->data.info.dim[n] = n;
1274 ss->data.info.start[n] = gfc_conv_array_lbound (expr, n);
1275 ss->data.info.stride[n] = gfc_index_one_node;
1277 mpz_init (ss->shape[n]);
1278 mpz_sub (ss->shape[n], cm->as->upper[n]->value.integer,
1279 cm->as->lower[n]->value.integer);
1280 mpz_add_ui (ss->shape[n], ss->shape[n], 1);
1283 /* Once we got ss, we use scalarizer to create the loop. */
1285 gfc_init_loopinfo (&loop);
1286 gfc_add_ss_to_loop (&loop, ss);
1287 gfc_conv_ss_startstride (&loop);
1288 gfc_conv_loop_setup (&loop);
1289 gfc_mark_ss_chain_used (ss, 1);
1290 gfc_start_scalarized_body (&loop, &body);
1292 gfc_copy_loopinfo_to_se (&se, &loop);
1293 se.ss = ss;
1295 /* gfc_conv_tmp_array_ref assumes that se.expr contains the array. */
1296 se.expr = expr;
1297 gfc_conv_tmp_array_ref (&se);
1299 /* Now se.expr contains an element of the array. Take the address and pass
1300 it to the IO routines. */
1301 tmp = gfc_build_addr_expr (NULL, se.expr);
1302 transfer_expr (&se, &cm->ts, tmp);
1304 /* We are done now with the loop body. Wrap up the scalarizer and
1305 return. */
1307 gfc_add_block_to_block (&body, &se.pre);
1308 gfc_add_block_to_block (&body, &se.post);
1310 gfc_trans_scalarizing_loops (&loop, &body);
1312 gfc_add_block_to_block (&block, &loop.pre);
1313 gfc_add_block_to_block (&block, &loop.post);
1315 for (n = 0; n < cm->as->rank; n++)
1316 mpz_clear (ss->shape[n]);
1317 gfc_free (ss->shape);
1319 gfc_cleanup_loop (&loop);
1321 return gfc_finish_block (&block);
1324 /* Generate the call for a scalar transfer node. */
1326 static void
1327 transfer_expr (gfc_se * se, gfc_typespec * ts, tree addr_expr)
1329 tree args, tmp, function, arg2, field, expr;
1330 gfc_component *c;
1331 int kind;
1333 kind = ts->kind;
1334 function = NULL;
1335 arg2 = NULL;
1337 switch (ts->type)
1339 case BT_INTEGER:
1340 arg2 = build_int_cst (NULL_TREE, kind);
1341 function = iocall_x_integer;
1342 break;
1344 case BT_REAL:
1345 arg2 = build_int_cst (NULL_TREE, kind);
1346 function = iocall_x_real;
1347 break;
1349 case BT_COMPLEX:
1350 arg2 = build_int_cst (NULL_TREE, kind);
1351 function = iocall_x_complex;
1352 break;
1354 case BT_LOGICAL:
1355 arg2 = build_int_cst (NULL_TREE, kind);
1356 function = iocall_x_logical;
1357 break;
1359 case BT_CHARACTER:
1360 if (se->string_length)
1361 arg2 = se->string_length;
1362 else
1364 tmp = gfc_build_indirect_ref (addr_expr);
1365 gcc_assert (TREE_CODE (TREE_TYPE (tmp)) == ARRAY_TYPE);
1366 arg2 = TYPE_MAX_VALUE (TYPE_DOMAIN (TREE_TYPE (tmp)));
1368 function = iocall_x_character;
1369 break;
1371 case BT_DERIVED:
1372 /* Recurse into the elements of the derived type. */
1373 expr = gfc_evaluate_now (addr_expr, &se->pre);
1374 expr = gfc_build_indirect_ref (expr);
1376 for (c = ts->derived->components; c; c = c->next)
1378 field = c->backend_decl;
1379 gcc_assert (field && TREE_CODE (field) == FIELD_DECL);
1381 tmp = build3 (COMPONENT_REF, TREE_TYPE (field), expr, field,
1382 NULL_TREE);
1384 if (c->dimension)
1386 tmp = transfer_array_component (tmp, c);
1387 gfc_add_expr_to_block (&se->pre, tmp);
1389 else
1391 if (!c->pointer)
1392 tmp = gfc_build_addr_expr (NULL, tmp);
1393 transfer_expr (se, &c->ts, tmp);
1396 return;
1398 default:
1399 internal_error ("Bad IO basetype (%d)", ts->type);
1402 args = gfc_chainon_list (NULL_TREE, addr_expr);
1403 args = gfc_chainon_list (args, arg2);
1405 tmp = gfc_build_function_call (function, args);
1406 gfc_add_expr_to_block (&se->pre, tmp);
1407 gfc_add_block_to_block (&se->pre, &se->post);
1412 /* gfc_trans_transfer()-- Translate a TRANSFER code node */
1414 tree
1415 gfc_trans_transfer (gfc_code * code)
1417 stmtblock_t block, body;
1418 gfc_loopinfo loop;
1419 gfc_expr *expr;
1420 gfc_ss *ss;
1421 gfc_se se;
1422 tree tmp;
1424 gfc_start_block (&block);
1426 expr = code->expr;
1427 ss = gfc_walk_expr (expr);
1429 gfc_init_se (&se, NULL);
1431 if (ss == gfc_ss_terminator)
1432 gfc_init_block (&body);
1433 else
1435 /* Initialize the scalarizer. */
1436 gfc_init_loopinfo (&loop);
1437 gfc_add_ss_to_loop (&loop, ss);
1439 /* Initialize the loop. */
1440 gfc_conv_ss_startstride (&loop);
1441 gfc_conv_loop_setup (&loop);
1443 /* The main loop body. */
1444 gfc_mark_ss_chain_used (ss, 1);
1445 gfc_start_scalarized_body (&loop, &body);
1447 gfc_copy_loopinfo_to_se (&se, &loop);
1448 se.ss = ss;
1451 gfc_conv_expr_reference (&se, expr);
1453 transfer_expr (&se, &expr->ts, se.expr);
1455 gfc_add_block_to_block (&body, &se.pre);
1456 gfc_add_block_to_block (&body, &se.post);
1458 if (se.ss == NULL)
1459 tmp = gfc_finish_block (&body);
1460 else
1462 gcc_assert (se.ss == gfc_ss_terminator);
1463 gfc_trans_scalarizing_loops (&loop, &body);
1465 gfc_add_block_to_block (&loop.pre, &loop.post);
1466 tmp = gfc_finish_block (&loop.pre);
1467 gfc_cleanup_loop (&loop);
1470 gfc_add_expr_to_block (&block, tmp);
1472 return gfc_finish_block (&block);
1475 #include "gt-fortran-trans-io.h"