annotate gcc/fortran/trans-io.c @ 111:04ced10e8804

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