OpenCores
URL https://opencores.org/ocsvn/scarts/scarts/trunk

Subversion Repositories scarts

[/] [scarts/] [trunk/] [toolchain/] [scarts-gcc/] [gcc-4.1.1/] [gcc/] [fortran/] [trans-io.c] - Blame information for rev 12

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 12 jlechner
/* IO Code translation/library interface
2
   Copyright (C) 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
3
   Contributed by Paul Brook
4
 
5
This file is part of GCC.
6
 
7
GCC is free software; you can redistribute it and/or modify it under
8
the terms of the GNU General Public License as published by the Free
9
Software Foundation; either version 2, or (at your option) any later
10
version.
11
 
12
GCC is distributed in the hope that it will be useful, but WITHOUT ANY
13
WARRANTY; without even the implied warranty of MERCHANTABILITY or
14
FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
15
for more details.
16
 
17
You should have received a copy of the GNU General Public License
18
along with GCC; see the file COPYING.  If not, write to the Free
19
Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
20
02110-1301, USA.  */
21
 
22
 
23
#include "config.h"
24
#include "system.h"
25
#include "coretypes.h"
26
#include "tree.h"
27
#include "tree-gimple.h"
28
#include "ggc.h"
29
#include "toplev.h"
30
#include "real.h"
31
#include "gfortran.h"
32
#include "trans.h"
33
#include "trans-stmt.h"
34
#include "trans-array.h"
35
#include "trans-types.h"
36
#include "trans-const.h"
37
 
38
 
39
/* Members of the ioparm structure.  */
40
 
41
enum ioparam_type
42
{
43
  IOPARM_ptype_common,
44
  IOPARM_ptype_open,
45
  IOPARM_ptype_close,
46
  IOPARM_ptype_filepos,
47
  IOPARM_ptype_inquire,
48
  IOPARM_ptype_dt,
49
  IOPARM_ptype_num
50
};
51
 
52
enum iofield_type
53
{
54
  IOPARM_type_int4,
55
  IOPARM_type_pint4,
56
  IOPARM_type_pchar,
57
  IOPARM_type_parray,
58
  IOPARM_type_pad,
59
  IOPARM_type_char1,
60
  IOPARM_type_char2,
61
  IOPARM_type_common,
62
  IOPARM_type_num
63
};
64
 
65
typedef struct gfc_st_parameter_field GTY(())
66
{
67
  const char *name;
68
  unsigned int mask;
69
  enum ioparam_type param_type;
70
  enum iofield_type type;
71
  tree field;
72
  tree field_len;
73
}
74
gfc_st_parameter_field;
75
 
76
typedef struct gfc_st_parameter GTY(())
77
{
78
  const char *name;
79
  tree type;
80
}
81
gfc_st_parameter;
82
 
83
enum iofield
84
{
85
#define IOPARM(param_type, name, mask, type) IOPARM_##param_type##_##name,
86
#include "ioparm.def"
87
#undef IOPARM
88
  IOPARM_field_num
89
};
90
 
91
static GTY(()) gfc_st_parameter st_parameter[] =
92
{
93
  { "common", NULL },
94
  { "open", NULL },
95
  { "close", NULL },
96
  { "filepos", NULL },
97
  { "inquire", NULL },
98
  { "dt", NULL }
99
};
100
 
101
static GTY(()) gfc_st_parameter_field st_parameter_field[] =
102
{
103
#define IOPARM(param_type, name, mask, type) \
104
  { #name, mask, IOPARM_ptype_##param_type, IOPARM_type_##type, NULL, NULL },
105
#include "ioparm.def"
106
#undef IOPARM
107
  { NULL, 0, 0, 0, NULL, NULL }
108
};
109
 
110
/* Library I/O subroutines */
111
 
112
enum iocall
113
{
114
  IOCALL_READ,
115
  IOCALL_READ_DONE,
116
  IOCALL_WRITE,
117
  IOCALL_WRITE_DONE,
118
  IOCALL_X_INTEGER,
119
  IOCALL_X_LOGICAL,
120
  IOCALL_X_CHARACTER,
121
  IOCALL_X_REAL,
122
  IOCALL_X_COMPLEX,
123
  IOCALL_X_ARRAY,
124
  IOCALL_OPEN,
125
  IOCALL_CLOSE,
126
  IOCALL_INQUIRE,
127
  IOCALL_IOLENGTH,
128
  IOCALL_IOLENGTH_DONE,
129
  IOCALL_REWIND,
130
  IOCALL_BACKSPACE,
131
  IOCALL_ENDFILE,
132
  IOCALL_FLUSH,
133
  IOCALL_SET_NML_VAL,
134
  IOCALL_SET_NML_VAL_DIM,
135
  IOCALL_NUM
136
};
137
 
138
static GTY(()) tree iocall[IOCALL_NUM];
139
 
140
/* Variable for keeping track of what the last data transfer statement
141
   was.  Used for deciding which subroutine to call when the data
142
   transfer is complete.  */
143
static enum { READ, WRITE, IOLENGTH } last_dt;
144
 
145
/* The data transfer parameter block that should be shared by all
146
   data transfer calls belonging to the same read/write/iolength.  */
147
static GTY(()) tree dt_parm;
148
static stmtblock_t *dt_post_end_block;
149
 
150
static void
151
gfc_build_st_parameter (enum ioparam_type ptype, tree *types)
152
{
153
  enum iofield type;
154
  gfc_st_parameter_field *p;
155
  char name[64];
156
  size_t len;
157
  tree t = make_node (RECORD_TYPE);
158
 
159
  len = strlen (st_parameter[ptype].name);
160
  gcc_assert (len <= sizeof (name) - sizeof ("__st_parameter_"));
161
  memcpy (name, "__st_parameter_", sizeof ("__st_parameter_"));
162
  memcpy (name + sizeof ("__st_parameter_") - 1, st_parameter[ptype].name,
163
          len + 1);
164
  TYPE_NAME (t) = get_identifier (name);
165
 
166
  for (type = 0, p = st_parameter_field; type < IOPARM_field_num; type++, p++)
167
    if (p->param_type == ptype)
168
      switch (p->type)
169
        {
170
        case IOPARM_type_int4:
171
        case IOPARM_type_pint4:
172
        case IOPARM_type_parray:
173
        case IOPARM_type_pchar:
174
        case IOPARM_type_pad:
175
          p->field = gfc_add_field_to_struct (&TYPE_FIELDS (t), t,
176
                                              get_identifier (p->name),
177
                                              types[p->type]);
178
          break;
179
        case IOPARM_type_char1:
180
          p->field = gfc_add_field_to_struct (&TYPE_FIELDS (t), t,
181
                                              get_identifier (p->name),
182
                                              pchar_type_node);
183
          /* FALLTHROUGH */
184
        case IOPARM_type_char2:
185
          len = strlen (p->name);
186
          gcc_assert (len <= sizeof (name) - sizeof ("_len"));
187
          memcpy (name, p->name, len);
188
          memcpy (name + len, "_len", sizeof ("_len"));
189
          p->field_len = gfc_add_field_to_struct (&TYPE_FIELDS (t), t,
190
                                                  get_identifier (name),
191
                                                  gfc_charlen_type_node);
192
          if (p->type == IOPARM_type_char2)
193
            p->field = gfc_add_field_to_struct (&TYPE_FIELDS (t), t,
194
                                                get_identifier (p->name),
195
                                                pchar_type_node);
196
          break;
197
        case IOPARM_type_common:
198
          p->field
199
            = gfc_add_field_to_struct (&TYPE_FIELDS (t), t,
200
                                       get_identifier (p->name),
201
                                       st_parameter[IOPARM_ptype_common].type);
202
          break;
203
        case IOPARM_type_num:
204
          gcc_unreachable ();
205
        }
206
 
207
  gfc_finish_type (t);
208
  st_parameter[ptype].type = t;
209
}
210
 
211
/* Create function decls for IO library functions.  */
212
 
213
void
214
gfc_build_io_library_fndecls (void)
215
{
216
  tree types[IOPARM_type_num], pad_idx, gfc_int4_type_node;
217
  tree parm_type, dt_parm_type;
218
  tree gfc_c_int_type_node;
219
  HOST_WIDE_INT pad_size;
220
  enum ioparam_type ptype;
221
 
222
  types[IOPARM_type_int4] = gfc_int4_type_node = gfc_get_int_type (4);
223
  types[IOPARM_type_pint4] = build_pointer_type (gfc_int4_type_node);
224
  types[IOPARM_type_parray] = pchar_type_node;
225
  types[IOPARM_type_pchar] = pchar_type_node;
226
  pad_size = 16 * TREE_INT_CST_LOW (TYPE_SIZE_UNIT (pchar_type_node));
227
  pad_size += 32 * TREE_INT_CST_LOW (TYPE_SIZE_UNIT (integer_type_node));
228
  pad_idx = build_index_type (build_int_cst (NULL_TREE, pad_size));
229
  types[IOPARM_type_pad] = build_array_type (char_type_node, pad_idx);
230
 
231
  /* pad actually contains pointers and integers so it needs to have an
232
     alignment that is at least as large as the needed alignment for those
233
     types.  See the st_parameter_dt structure in libgfortran/io/io.h for
234
     what really goes into this space.  */
235
  TYPE_ALIGN (types[IOPARM_type_pad]) = MAX (TYPE_ALIGN (pchar_type_node),
236
                     TYPE_ALIGN (gfc_get_int_type (gfc_max_integer_kind)));
237
 
238
  gfc_c_int_type_node = gfc_get_int_type (gfc_c_int_kind);
239
 
240
  for (ptype = IOPARM_ptype_common; ptype < IOPARM_ptype_num; ptype++)
241
    gfc_build_st_parameter (ptype, types);
242
 
243
  /* Define the transfer functions.  */
244
 
245
  dt_parm_type = build_pointer_type (st_parameter[IOPARM_ptype_dt].type);
246
 
247
  iocall[IOCALL_X_INTEGER] =
248
    gfc_build_library_function_decl (get_identifier
249
                                     (PREFIX("transfer_integer")),
250
                                     void_type_node, 3, dt_parm_type,
251
                                     pvoid_type_node, gfc_int4_type_node);
252
 
253
  iocall[IOCALL_X_LOGICAL] =
254
    gfc_build_library_function_decl (get_identifier
255
                                     (PREFIX("transfer_logical")),
256
                                     void_type_node, 3, dt_parm_type,
257
                                     pvoid_type_node, gfc_int4_type_node);
258
 
259
  iocall[IOCALL_X_CHARACTER] =
260
    gfc_build_library_function_decl (get_identifier
261
                                     (PREFIX("transfer_character")),
262
                                     void_type_node, 3, dt_parm_type,
263
                                     pvoid_type_node, gfc_int4_type_node);
264
 
265
  iocall[IOCALL_X_REAL] =
266
    gfc_build_library_function_decl (get_identifier (PREFIX("transfer_real")),
267
                                     void_type_node, 3, dt_parm_type,
268
                                     pvoid_type_node, gfc_int4_type_node);
269
 
270
  iocall[IOCALL_X_COMPLEX] =
271
    gfc_build_library_function_decl (get_identifier
272
                                     (PREFIX("transfer_complex")),
273
                                     void_type_node, 3, dt_parm_type,
274
                                     pvoid_type_node, gfc_int4_type_node);
275
 
276
  iocall[IOCALL_X_ARRAY] =
277
    gfc_build_library_function_decl (get_identifier
278
                                     (PREFIX("transfer_array")),
279
                                     void_type_node, 4, dt_parm_type,
280
                                     pvoid_type_node, gfc_c_int_type_node,
281
                                     gfc_charlen_type_node);
282
 
283
  /* Library entry points */
284
 
285
  iocall[IOCALL_READ] =
286
    gfc_build_library_function_decl (get_identifier (PREFIX("st_read")),
287
                                     void_type_node, 1, dt_parm_type);
288
 
289
  iocall[IOCALL_WRITE] =
290
    gfc_build_library_function_decl (get_identifier (PREFIX("st_write")),
291
                                     void_type_node, 1, dt_parm_type);
292
 
293
  parm_type = build_pointer_type (st_parameter[IOPARM_ptype_open].type);
294
  iocall[IOCALL_OPEN] =
295
    gfc_build_library_function_decl (get_identifier (PREFIX("st_open")),
296
                                     void_type_node, 1, parm_type);
297
 
298
 
299
  parm_type = build_pointer_type (st_parameter[IOPARM_ptype_close].type);
300
  iocall[IOCALL_CLOSE] =
301
    gfc_build_library_function_decl (get_identifier (PREFIX("st_close")),
302
                                     void_type_node, 1, parm_type);
303
 
304
  parm_type = build_pointer_type (st_parameter[IOPARM_ptype_inquire].type);
305
  iocall[IOCALL_INQUIRE] =
306
    gfc_build_library_function_decl (get_identifier (PREFIX("st_inquire")),
307
                                     gfc_int4_type_node, 1, parm_type);
308
 
309
  iocall[IOCALL_IOLENGTH] =
310
    gfc_build_library_function_decl(get_identifier (PREFIX("st_iolength")),
311
                                    void_type_node, 1, dt_parm_type);
312
 
313
  parm_type = build_pointer_type (st_parameter[IOPARM_ptype_filepos].type);
314
  iocall[IOCALL_REWIND] =
315
    gfc_build_library_function_decl (get_identifier (PREFIX("st_rewind")),
316
                                     gfc_int4_type_node, 1, parm_type);
317
 
318
  iocall[IOCALL_BACKSPACE] =
319
    gfc_build_library_function_decl (get_identifier (PREFIX("st_backspace")),
320
                                     gfc_int4_type_node, 1, parm_type);
321
 
322
  iocall[IOCALL_ENDFILE] =
323
    gfc_build_library_function_decl (get_identifier (PREFIX("st_endfile")),
324
                                     gfc_int4_type_node, 1, parm_type);
325
 
326
  iocall[IOCALL_FLUSH] =
327
    gfc_build_library_function_decl (get_identifier (PREFIX("st_flush")),
328
                                     gfc_int4_type_node, 1, parm_type);
329
 
330
  /* Library helpers */
331
 
332
  iocall[IOCALL_READ_DONE] =
333
    gfc_build_library_function_decl (get_identifier (PREFIX("st_read_done")),
334
                                     gfc_int4_type_node, 1, dt_parm_type);
335
 
336
  iocall[IOCALL_WRITE_DONE] =
337
    gfc_build_library_function_decl (get_identifier (PREFIX("st_write_done")),
338
                                     gfc_int4_type_node, 1, dt_parm_type);
339
 
340
  iocall[IOCALL_IOLENGTH_DONE] =
341
    gfc_build_library_function_decl (get_identifier (PREFIX("st_iolength_done")),
342
                                     gfc_int4_type_node, 1, dt_parm_type);
343
 
344
 
345
  iocall[IOCALL_SET_NML_VAL] =
346
    gfc_build_library_function_decl (get_identifier (PREFIX("st_set_nml_var")),
347
                                     void_type_node, 6, dt_parm_type,
348
                                     pvoid_type_node, pvoid_type_node,
349
                                     gfc_int4_type_node, gfc_charlen_type_node,
350
                                     gfc_int4_type_node);
351
 
352
  iocall[IOCALL_SET_NML_VAL_DIM] =
353
    gfc_build_library_function_decl (get_identifier (PREFIX("st_set_nml_var_dim")),
354
                                     void_type_node, 5, dt_parm_type,
355
                                     gfc_int4_type_node, gfc_int4_type_node,
356
                                     gfc_int4_type_node, gfc_int4_type_node);
357
}
358
 
359
 
360
/* Generate code to store an integer constant into the
361
   st_parameter_XXX structure.  */
362
 
363
static unsigned int
364
set_parameter_const (stmtblock_t *block, tree var, enum iofield type,
365
                     unsigned int val)
366
{
367
  tree tmp;
368
  gfc_st_parameter_field *p = &st_parameter_field[type];
369
 
370
  if (p->param_type == IOPARM_ptype_common)
371
    var = build3 (COMPONENT_REF, st_parameter[IOPARM_ptype_common].type,
372
                  var, TYPE_FIELDS (TREE_TYPE (var)), NULL_TREE);
373
  tmp = build3 (COMPONENT_REF, TREE_TYPE (p->field), var, p->field,
374
                NULL_TREE);
375
  gfc_add_modify_expr (block, tmp, build_int_cst (TREE_TYPE (p->field), val));
376
  return p->mask;
377
}
378
 
379
 
380
/* Generate code to store a non-string I/O parameter into the
381
   st_parameter_XXX structure.  This is a pass by value.  */
382
 
383
static unsigned int
384
set_parameter_value (stmtblock_t *block, tree var, enum iofield type,
385
                     gfc_expr *e)
386
{
387
  gfc_se se;
388
  tree tmp;
389
  gfc_st_parameter_field *p = &st_parameter_field[type];
390
 
391
  gfc_init_se (&se, NULL);
392
  gfc_conv_expr_type (&se, e, TREE_TYPE (p->field));
393
  gfc_add_block_to_block (block, &se.pre);
394
 
395
  if (p->param_type == IOPARM_ptype_common)
396
    var = build3 (COMPONENT_REF, st_parameter[IOPARM_ptype_common].type,
397
                  var, TYPE_FIELDS (TREE_TYPE (var)), NULL_TREE);
398
  tmp = build3 (COMPONENT_REF, TREE_TYPE (p->field), var, p->field,
399
                NULL_TREE);
400
  gfc_add_modify_expr (block, tmp, se.expr);
401
  return p->mask;
402
}
403
 
404
 
405
/* Generate code to store a non-string I/O parameter into the
406
   st_parameter_XXX structure.  This is pass by reference.  */
407
 
408
static unsigned int
409
set_parameter_ref (stmtblock_t *block, stmtblock_t *postblock,
410
                   tree var, enum iofield type, gfc_expr *e)
411
{
412
  gfc_se se;
413
  tree tmp, addr;
414
  gfc_st_parameter_field *p = &st_parameter_field[type];
415
 
416
  gcc_assert (e->ts.type == BT_INTEGER || e->ts.type == BT_LOGICAL);
417
  gfc_init_se (&se, NULL);
418
  gfc_conv_expr_lhs (&se, e);
419
 
420
  gfc_add_block_to_block (block, &se.pre);
421
 
422
  if (TYPE_MODE (TREE_TYPE (se.expr))
423
      == TYPE_MODE (TREE_TYPE (TREE_TYPE (p->field))))
424
    addr = convert (TREE_TYPE (p->field),
425
                    gfc_build_addr_expr (NULL, se.expr));
426
  else
427
    {
428
      /* The type used by the library has different size
429
         from the type of the variable supplied by the user.
430
         Need to use a temporary.  */
431
      tree tmpvar
432
        = gfc_create_var (TREE_TYPE (TREE_TYPE (p->field)),
433
                          st_parameter_field[type].name);
434
      addr = gfc_build_addr_expr (NULL, tmpvar);
435
      tmp = convert (TREE_TYPE (se.expr), tmpvar);
436
      gfc_add_modify_expr (postblock, se.expr, tmp);
437
    }
438
 
439
  if (p->param_type == IOPARM_ptype_common)
440
    var = build3 (COMPONENT_REF, st_parameter[IOPARM_ptype_common].type,
441
                  var, TYPE_FIELDS (TREE_TYPE (var)), NULL_TREE);
442
  tmp = build3 (COMPONENT_REF, TREE_TYPE (p->field), var, p->field,
443
                NULL_TREE);
444
  gfc_add_modify_expr (block, tmp, addr);
445
  return p->mask;
446
}
447
 
448
/* Given an array expr, find its address and length to get a string. If the
449
   array is full, the string's address is the address of array's first element
450
   and the length is the size of the whole array. If it is an element, the
451
   string's address is the element's address and the length is the rest size of
452
   the array.
453
*/
454
 
455
static void
456
gfc_convert_array_to_string (gfc_se * se, gfc_expr * e)
457
{
458
  tree tmp;
459
  tree array;
460
  tree type;
461
  tree size;
462
  int rank;
463
  gfc_symbol *sym;
464
 
465
  sym = e->symtree->n.sym;
466
  rank = sym->as->rank - 1;
467
 
468
  if (e->ref->u.ar.type == AR_FULL)
469
    {
470
      se->expr = gfc_get_symbol_decl (sym);
471
      se->expr = gfc_conv_array_data (se->expr);
472
    }
473
  else
474
    {
475
      gfc_conv_expr (se, e);
476
    }
477
 
478
  array = sym->backend_decl;
479
  type = TREE_TYPE (array);
480
 
481
  if (GFC_ARRAY_TYPE_P (type))
482
    size = GFC_TYPE_ARRAY_SIZE (type);
483
  else
484
    {
485
      gcc_assert (GFC_DESCRIPTOR_TYPE_P (type));
486
      size = gfc_conv_array_stride (array, rank);
487
      tmp = fold_build2 (MINUS_EXPR, gfc_array_index_type,
488
                gfc_conv_array_ubound (array, rank),
489
                gfc_conv_array_lbound (array, rank));
490
      tmp = fold_build2 (PLUS_EXPR, gfc_array_index_type, tmp,
491
                gfc_index_one_node);
492
      size = fold_build2 (MULT_EXPR, gfc_array_index_type, tmp, size);
493
    }
494
 
495
  gcc_assert (size);
496
 
497
  /* If it is an element, we need the its address and size of the rest.  */
498
  if (e->ref->u.ar.type == AR_ELEMENT)
499
    {
500
      size = fold_build2 (MINUS_EXPR, gfc_array_index_type, size,
501
                TREE_OPERAND (se->expr, 1));
502
      se->expr = gfc_build_addr_expr (NULL, se->expr);
503
    }
504
 
505
  tmp = TYPE_SIZE_UNIT (gfc_get_element_type (type));
506
  size = fold_build2 (MULT_EXPR, gfc_array_index_type, size, tmp);
507
 
508
  se->string_length = fold_convert (gfc_charlen_type_node, size);
509
}
510
 
511
 
512
/* Generate code to store a string and its length into the
513
   st_parameter_XXX structure.  */
514
 
515
static unsigned int
516
set_string (stmtblock_t * block, stmtblock_t * postblock, tree var,
517
            enum iofield type, gfc_expr * e)
518
{
519
  gfc_se se;
520
  tree tmp;
521
  tree msg;
522
  tree io;
523
  tree len;
524
  gfc_st_parameter_field *p = &st_parameter_field[type];
525
 
526
  gfc_init_se (&se, NULL);
527
 
528
  if (p->param_type == IOPARM_ptype_common)
529
    var = build3 (COMPONENT_REF, st_parameter[IOPARM_ptype_common].type,
530
                  var, TYPE_FIELDS (TREE_TYPE (var)), NULL_TREE);
531
  io = build3 (COMPONENT_REF, TREE_TYPE (p->field), var, p->field,
532
               NULL_TREE);
533
  len = build3 (COMPONENT_REF, TREE_TYPE (p->field_len), var, p->field_len,
534
                NULL_TREE);
535
 
536
  /* Integer variable assigned a format label.  */
537
  if (e->ts.type == BT_INTEGER && e->symtree->n.sym->attr.assign == 1)
538
    {
539
      gfc_conv_label_variable (&se, e);
540
      msg =
541
        gfc_build_cstring_const ("Assigned label is not a format label");
542
      tmp = GFC_DECL_STRING_LEN (se.expr);
543
      tmp = build2 (LE_EXPR, boolean_type_node,
544
                    tmp, convert (TREE_TYPE (tmp), integer_minus_one_node));
545
      gfc_trans_runtime_check (tmp, msg, &se.pre);
546
      gfc_add_modify_expr (&se.pre, io,
547
                 fold_convert (TREE_TYPE (io), GFC_DECL_ASSIGN_ADDR (se.expr)));
548
      gfc_add_modify_expr (&se.pre, len, GFC_DECL_STRING_LEN (se.expr));
549
    }
550
  else
551
    {
552
      /* General character.  */
553
      if (e->ts.type == BT_CHARACTER && e->rank == 0)
554
        gfc_conv_expr (&se, e);
555
      /* Array assigned Hollerith constant or character array.  */
556
      else if (e->symtree && (e->symtree->n.sym->as->rank > 0))
557
        gfc_convert_array_to_string (&se, e);
558
      else
559
        gcc_unreachable ();
560
 
561
      gfc_conv_string_parameter (&se);
562
      gfc_add_modify_expr (&se.pre, io, fold_convert (TREE_TYPE (io), se.expr));
563
      gfc_add_modify_expr (&se.pre, len, se.string_length);
564
    }
565
 
566
  gfc_add_block_to_block (block, &se.pre);
567
  gfc_add_block_to_block (postblock, &se.post);
568
  return p->mask;
569
}
570
 
571
 
572
/* Generate code to store the character (array) and the character length
573
   for an internal unit.  */
574
 
575
static unsigned int
576
set_internal_unit (stmtblock_t * block, tree var, gfc_expr * e)
577
{
578
  gfc_se se;
579
  tree io;
580
  tree len;
581
  tree desc;
582
  tree tmp;
583
  gfc_st_parameter_field *p;
584
  unsigned int mask;
585
 
586
  gfc_init_se (&se, NULL);
587
 
588
  p = &st_parameter_field[IOPARM_dt_internal_unit];
589
  mask = p->mask;
590
  io = build3 (COMPONENT_REF, TREE_TYPE (p->field), var, p->field,
591
               NULL_TREE);
592
  len = build3 (COMPONENT_REF, TREE_TYPE (p->field_len), var, p->field_len,
593
                NULL_TREE);
594
  p = &st_parameter_field[IOPARM_dt_internal_unit_desc];
595
  desc = build3 (COMPONENT_REF, TREE_TYPE (p->field), var, p->field,
596
                 NULL_TREE);
597
 
598
  gcc_assert (e->ts.type == BT_CHARACTER);
599
 
600
  /* Character scalars.  */
601
  if (e->rank == 0)
602
    {
603
      gfc_conv_expr (&se, e);
604
      gfc_conv_string_parameter (&se);
605
      tmp = se.expr;
606
      se.expr = fold_convert (pchar_type_node, integer_zero_node);
607
    }
608
 
609
  /* Character array.  */
610
  else if (e->rank > 0)
611
    {
612
      se.ss = gfc_walk_expr (e);
613
 
614
      /* Return the data pointer and rank from the descriptor.  */
615
      gfc_conv_expr_descriptor (&se, e, se.ss);
616
      tmp = gfc_conv_descriptor_data_get (se.expr);
617
      se.expr = gfc_build_addr_expr (pchar_type_node, se.expr);
618
    }
619
  else
620
    gcc_unreachable ();
621
 
622
  /* The cast is needed for character substrings and the descriptor
623
     data.  */
624
  gfc_add_modify_expr (&se.pre, io, fold_convert (TREE_TYPE (io), tmp));
625
  gfc_add_modify_expr (&se.pre, len, se.string_length);
626
  gfc_add_modify_expr (&se.pre, desc, se.expr);
627
 
628
  gfc_add_block_to_block (block, &se.pre);
629
  return mask;
630
}
631
 
632
/* Add a case to a IO-result switch.  */
633
 
634
static void
635
add_case (int label_value, gfc_st_label * label, stmtblock_t * body)
636
{
637
  tree tmp, value;
638
 
639
  if (label == NULL)
640
    return;                     /* No label, no case */
641
 
642
  value = build_int_cst (NULL_TREE, label_value);
643
 
644
  /* Make a backend label for this case.  */
645
  tmp = gfc_build_label_decl (NULL_TREE);
646
 
647
  /* And the case itself.  */
648
  tmp = build3_v (CASE_LABEL_EXPR, value, NULL_TREE, tmp);
649
  gfc_add_expr_to_block (body, tmp);
650
 
651
  /* Jump to the label.  */
652
  tmp = build1_v (GOTO_EXPR, gfc_get_label_decl (label));
653
  gfc_add_expr_to_block (body, tmp);
654
}
655
 
656
 
657
/* Generate a switch statement that branches to the correct I/O
658
   result label.  The last statement of an I/O call stores the
659
   result into a variable because there is often cleanup that
660
   must be done before the switch, so a temporary would have to
661
   be created anyway.  */
662
 
663
static void
664
io_result (stmtblock_t * block, tree var, gfc_st_label * err_label,
665
           gfc_st_label * end_label, gfc_st_label * eor_label)
666
{
667
  stmtblock_t body;
668
  tree tmp, rc;
669
  gfc_st_parameter_field *p = &st_parameter_field[IOPARM_common_flags];
670
 
671
  /* If no labels are specified, ignore the result instead
672
     of building an empty switch.  */
673
  if (err_label == NULL
674
      && end_label == NULL
675
      && eor_label == NULL)
676
    return;
677
 
678
  /* Build a switch statement.  */
679
  gfc_start_block (&body);
680
 
681
  /* The label values here must be the same as the values
682
     in the library_return enum in the runtime library */
683
  add_case (1, err_label, &body);
684
  add_case (2, end_label, &body);
685
  add_case (3, eor_label, &body);
686
 
687
  tmp = gfc_finish_block (&body);
688
 
689
  var = build3 (COMPONENT_REF, st_parameter[IOPARM_ptype_common].type,
690
                var, TYPE_FIELDS (TREE_TYPE (var)), NULL_TREE);
691
  rc = build3 (COMPONENT_REF, TREE_TYPE (p->field), var, p->field,
692
               NULL_TREE);
693
  rc = build2 (BIT_AND_EXPR, TREE_TYPE (rc), rc,
694
               build_int_cst (TREE_TYPE (rc), IOPARM_common_libreturn_mask));
695
 
696
  tmp = build3_v (SWITCH_EXPR, rc, tmp, NULL_TREE);
697
 
698
  gfc_add_expr_to_block (block, tmp);
699
}
700
 
701
 
702
/* Store the current file and line number to variables so that if a
703
   library call goes awry, we can tell the user where the problem is.  */
704
 
705
static void
706
set_error_locus (stmtblock_t * block, tree var, locus * where)
707
{
708
  gfc_file *f;
709
  tree str, locus_file;
710
  int line;
711
  gfc_st_parameter_field *p = &st_parameter_field[IOPARM_common_filename];
712
 
713
  locus_file = build3 (COMPONENT_REF, st_parameter[IOPARM_ptype_common].type,
714
                       var, TYPE_FIELDS (TREE_TYPE (var)), NULL_TREE);
715
  locus_file = build3 (COMPONENT_REF, TREE_TYPE (p->field), locus_file,
716
                       p->field, NULL_TREE);
717
  f = where->lb->file;
718
  str = gfc_build_cstring_const (f->filename);
719
 
720
  str = gfc_build_addr_expr (pchar_type_node, str);
721
  gfc_add_modify_expr (block, locus_file, str);
722
 
723
#ifdef USE_MAPPED_LOCATION
724
  line = LOCATION_LINE (where->lb->location);
725
#else
726
  line = where->lb->linenum;
727
#endif
728
  set_parameter_const (block, var, IOPARM_common_line, line);
729
}
730
 
731
 
732
/* Translate an OPEN statement.  */
733
 
734
tree
735
gfc_trans_open (gfc_code * code)
736
{
737
  stmtblock_t block, post_block;
738
  gfc_open *p;
739
  tree tmp, var;
740
  unsigned int mask = 0;
741
 
742
  gfc_start_block (&block);
743
  gfc_init_block (&post_block);
744
 
745
  var = gfc_create_var (st_parameter[IOPARM_ptype_open].type, "open_parm");
746
 
747
  set_error_locus (&block, var, &code->loc);
748
  p = code->ext.open;
749
 
750
  if (p->unit)
751
    set_parameter_value (&block, var, IOPARM_common_unit, p->unit);
752
  else
753
    set_parameter_const (&block, var, IOPARM_common_unit, 0);
754
 
755
  if (p->file)
756
    mask |= set_string (&block, &post_block, var, IOPARM_open_file, p->file);
757
 
758
  if (p->status)
759
    mask |= set_string (&block, &post_block, var, IOPARM_open_status,
760
                        p->status);
761
 
762
  if (p->access)
763
    mask |= set_string (&block, &post_block, var, IOPARM_open_access,
764
                        p->access);
765
 
766
  if (p->form)
767
    mask |= set_string (&block, &post_block, var, IOPARM_open_form, p->form);
768
 
769
  if (p->recl)
770
    mask |= set_parameter_value (&block, var, IOPARM_open_recl_in, p->recl);
771
 
772
  if (p->blank)
773
    mask |= set_string (&block, &post_block, var, IOPARM_open_blank,
774
                        p->blank);
775
 
776
  if (p->position)
777
    mask |= set_string (&block, &post_block, var, IOPARM_open_position,
778
                        p->position);
779
 
780
  if (p->action)
781
    mask |= set_string (&block, &post_block, var, IOPARM_open_action,
782
                        p->action);
783
 
784
  if (p->delim)
785
    mask |= set_string (&block, &post_block, var, IOPARM_open_delim,
786
                        p->delim);
787
 
788
  if (p->pad)
789
    mask |= set_string (&block, &post_block, var, IOPARM_open_pad, p->pad);
790
 
791
  if (p->iomsg)
792
    mask |= set_string (&block, &post_block, var, IOPARM_common_iomsg,
793
                        p->iomsg);
794
 
795
  if (p->iostat)
796
    mask |= set_parameter_ref (&block, &post_block, var, IOPARM_common_iostat,
797
                               p->iostat);
798
 
799
  if (p->err)
800
    mask |= IOPARM_common_err;
801
 
802
  if (p->convert)
803
    mask |= set_string (&block, &post_block, var, IOPARM_open_convert,
804
                        p->convert);
805
 
806
  set_parameter_const (&block, var, IOPARM_common_flags, mask);
807
 
808
  tmp = gfc_build_addr_expr (NULL_TREE, var);
809
  tmp = gfc_chainon_list (NULL_TREE, tmp);
810
  tmp = gfc_build_function_call (iocall[IOCALL_OPEN], tmp);
811
  gfc_add_expr_to_block (&block, tmp);
812
 
813
  gfc_add_block_to_block (&block, &post_block);
814
 
815
  io_result (&block, var, p->err, NULL, NULL);
816
 
817
  return gfc_finish_block (&block);
818
}
819
 
820
 
821
/* Translate a CLOSE statement.  */
822
 
823
tree
824
gfc_trans_close (gfc_code * code)
825
{
826
  stmtblock_t block, post_block;
827
  gfc_close *p;
828
  tree tmp, var;
829
  unsigned int mask = 0;
830
 
831
  gfc_start_block (&block);
832
  gfc_init_block (&post_block);
833
 
834
  var = gfc_create_var (st_parameter[IOPARM_ptype_close].type, "close_parm");
835
 
836
  set_error_locus (&block, var, &code->loc);
837
  p = code->ext.close;
838
 
839
  if (p->unit)
840
    set_parameter_value (&block, var, IOPARM_common_unit, p->unit);
841
  else
842
    set_parameter_const (&block, var, IOPARM_common_unit, 0);
843
 
844
  if (p->status)
845
    mask |= set_string (&block, &post_block, var, IOPARM_close_status,
846
                        p->status);
847
 
848
  if (p->iomsg)
849
    mask |= set_string (&block, &post_block, var, IOPARM_common_iomsg,
850
                        p->iomsg);
851
 
852
  if (p->iostat)
853
    mask |= set_parameter_ref (&block, &post_block, var, IOPARM_common_iostat,
854
                               p->iostat);
855
 
856
  if (p->err)
857
    mask |= IOPARM_common_err;
858
 
859
  set_parameter_const (&block, var, IOPARM_common_flags, mask);
860
 
861
  tmp = gfc_build_addr_expr (NULL_TREE, var);
862
  tmp = gfc_chainon_list (NULL_TREE, tmp);
863
  tmp = gfc_build_function_call (iocall[IOCALL_CLOSE], tmp);
864
  gfc_add_expr_to_block (&block, tmp);
865
 
866
  gfc_add_block_to_block (&block, &post_block);
867
 
868
  io_result (&block, var, p->err, NULL, NULL);
869
 
870
  return gfc_finish_block (&block);
871
}
872
 
873
 
874
/* Common subroutine for building a file positioning statement.  */
875
 
876
static tree
877
build_filepos (tree function, gfc_code * code)
878
{
879
  stmtblock_t block, post_block;
880
  gfc_filepos *p;
881
  tree tmp, var;
882
  unsigned int mask = 0;
883
 
884
  p = code->ext.filepos;
885
 
886
  gfc_start_block (&block);
887
  gfc_init_block (&post_block);
888
 
889
  var = gfc_create_var (st_parameter[IOPARM_ptype_filepos].type,
890
                        "filepos_parm");
891
 
892
  set_error_locus (&block, var, &code->loc);
893
 
894
  if (p->unit)
895
    set_parameter_value (&block, var, IOPARM_common_unit, p->unit);
896
  else
897
    set_parameter_const (&block, var, IOPARM_common_unit, 0);
898
 
899
  if (p->iomsg)
900
    mask |= set_string (&block, &post_block, var, IOPARM_common_iomsg,
901
                        p->iomsg);
902
 
903
  if (p->iostat)
904
    mask |= set_parameter_ref (&block, &post_block, var, IOPARM_common_iostat,
905
                               p->iostat);
906
 
907
  if (p->err)
908
    mask |= IOPARM_common_err;
909
 
910
  set_parameter_const (&block, var, IOPARM_common_flags, mask);
911
 
912
  tmp = gfc_build_addr_expr (NULL_TREE, var);
913
  tmp = gfc_chainon_list (NULL_TREE, tmp);
914
  tmp = gfc_build_function_call (function, tmp);
915
  gfc_add_expr_to_block (&block, tmp);
916
 
917
  gfc_add_block_to_block (&block, &post_block);
918
 
919
  io_result (&block, var, p->err, NULL, NULL);
920
 
921
  return gfc_finish_block (&block);
922
}
923
 
924
 
925
/* Translate a BACKSPACE statement.  */
926
 
927
tree
928
gfc_trans_backspace (gfc_code * code)
929
{
930
  return build_filepos (iocall[IOCALL_BACKSPACE], code);
931
}
932
 
933
 
934
/* Translate an ENDFILE statement.  */
935
 
936
tree
937
gfc_trans_endfile (gfc_code * code)
938
{
939
  return build_filepos (iocall[IOCALL_ENDFILE], code);
940
}
941
 
942
 
943
/* Translate a REWIND statement.  */
944
 
945
tree
946
gfc_trans_rewind (gfc_code * code)
947
{
948
  return build_filepos (iocall[IOCALL_REWIND], code);
949
}
950
 
951
 
952
/* Translate a FLUSH statement.  */
953
 
954
tree
955
gfc_trans_flush (gfc_code * code)
956
{
957
  return build_filepos (iocall[IOCALL_FLUSH], code);
958
}
959
 
960
 
961
/* Translate the non-IOLENGTH form of an INQUIRE statement.  */
962
 
963
tree
964
gfc_trans_inquire (gfc_code * code)
965
{
966
  stmtblock_t block, post_block;
967
  gfc_inquire *p;
968
  tree tmp, var;
969
  unsigned int mask = 0;
970
 
971
  gfc_start_block (&block);
972
  gfc_init_block (&post_block);
973
 
974
  var = gfc_create_var (st_parameter[IOPARM_ptype_inquire].type,
975
                        "inquire_parm");
976
 
977
  set_error_locus (&block, var, &code->loc);
978
  p = code->ext.inquire;
979
 
980
  /* Sanity check.  */
981
  if (p->unit && p->file)
982
    gfc_error ("INQUIRE statement at %L cannot contain both FILE and UNIT specifiers.", &code->loc);
983
 
984
  if (p->unit)
985
    set_parameter_value (&block, var, IOPARM_common_unit, p->unit);
986
  else
987
    set_parameter_const (&block, var, IOPARM_common_unit, 0);
988
 
989
  if (p->file)
990
    mask |= set_string (&block, &post_block, var, IOPARM_inquire_file,
991
                        p->file);
992
 
993
  if (p->iomsg)
994
    mask |= set_string (&block, &post_block, var, IOPARM_common_iomsg,
995
                        p->iomsg);
996
 
997
  if (p->iostat)
998
    mask |= set_parameter_ref (&block, &post_block, var, IOPARM_common_iostat,
999
                               p->iostat);
1000
 
1001
  if (p->exist)
1002
    mask |= set_parameter_ref (&block, &post_block, var, IOPARM_inquire_exist,
1003
                               p->exist);
1004
 
1005
  if (p->opened)
1006
    mask |= set_parameter_ref (&block, &post_block, var, IOPARM_inquire_opened,
1007
                               p->opened);
1008
 
1009
  if (p->number)
1010
    mask |= set_parameter_ref (&block, &post_block, var, IOPARM_inquire_number,
1011
                               p->number);
1012
 
1013
  if (p->named)
1014
    mask |= set_parameter_ref (&block, &post_block, var, IOPARM_inquire_named,
1015
                               p->named);
1016
 
1017
  if (p->name)
1018
    mask |= set_string (&block, &post_block, var, IOPARM_inquire_name,
1019
                        p->name);
1020
 
1021
  if (p->access)
1022
    mask |= set_string (&block, &post_block, var, IOPARM_inquire_access,
1023
                        p->access);
1024
 
1025
  if (p->sequential)
1026
    mask |= set_string (&block, &post_block, var, IOPARM_inquire_sequential,
1027
                        p->sequential);
1028
 
1029
  if (p->direct)
1030
    mask |= set_string (&block, &post_block, var, IOPARM_inquire_direct,
1031
                        p->direct);
1032
 
1033
  if (p->form)
1034
    mask |= set_string (&block, &post_block, var, IOPARM_inquire_form,
1035
                        p->form);
1036
 
1037
  if (p->formatted)
1038
    mask |= set_string (&block, &post_block, var, IOPARM_inquire_formatted,
1039
                        p->formatted);
1040
 
1041
  if (p->unformatted)
1042
    mask |= set_string (&block, &post_block, var, IOPARM_inquire_unformatted,
1043
                        p->unformatted);
1044
 
1045
  if (p->recl)
1046
    mask |= set_parameter_ref (&block, &post_block, var,
1047
                               IOPARM_inquire_recl_out, p->recl);
1048
 
1049
  if (p->nextrec)
1050
    mask |= set_parameter_ref (&block, &post_block, var,
1051
                               IOPARM_inquire_nextrec, p->nextrec);
1052
 
1053
  if (p->blank)
1054
    mask |= set_string (&block, &post_block, var, IOPARM_inquire_blank,
1055
                        p->blank);
1056
 
1057
  if (p->position)
1058
    mask |= set_string (&block, &post_block, var, IOPARM_inquire_position,
1059
                        p->position);
1060
 
1061
  if (p->action)
1062
    mask |= set_string (&block, &post_block, var, IOPARM_inquire_action,
1063
                        p->action);
1064
 
1065
  if (p->read)
1066
    mask |= set_string (&block, &post_block, var, IOPARM_inquire_read,
1067
                        p->read);
1068
 
1069
  if (p->write)
1070
    mask |= set_string (&block, &post_block, var, IOPARM_inquire_write,
1071
                        p->write);
1072
 
1073
  if (p->readwrite)
1074
    mask |= set_string (&block, &post_block, var, IOPARM_inquire_readwrite,
1075
                        p->readwrite);
1076
 
1077
  if (p->delim)
1078
    mask |= set_string (&block, &post_block, var, IOPARM_inquire_delim,
1079
                        p->delim);
1080
 
1081
  if (p->pad)
1082
    mask |= set_string (&block, &post_block, var, IOPARM_inquire_pad,
1083
                        p->pad);
1084
 
1085
  if (p->err)
1086
    mask |= IOPARM_common_err;
1087
 
1088
  if (p->convert)
1089
    mask |= set_string (&block, &post_block, var, IOPARM_inquire_convert,
1090
                        p->convert);
1091
 
1092
  set_parameter_const (&block, var, IOPARM_common_flags, mask);
1093
 
1094
  tmp = gfc_build_addr_expr (NULL_TREE, var);
1095
  tmp = gfc_chainon_list (NULL_TREE, tmp);
1096
  tmp = gfc_build_function_call (iocall[IOCALL_INQUIRE], tmp);
1097
  gfc_add_expr_to_block (&block, tmp);
1098
 
1099
  gfc_add_block_to_block (&block, &post_block);
1100
 
1101
  io_result (&block, var, p->err, NULL, NULL);
1102
 
1103
  return gfc_finish_block (&block);
1104
}
1105
 
1106
static gfc_expr *
1107
gfc_new_nml_name_expr (const char * name)
1108
{
1109
   gfc_expr * nml_name;
1110
 
1111
   nml_name = gfc_get_expr();
1112
   nml_name->ref = NULL;
1113
   nml_name->expr_type = EXPR_CONSTANT;
1114
   nml_name->ts.kind = gfc_default_character_kind;
1115
   nml_name->ts.type = BT_CHARACTER;
1116
   nml_name->value.character.length = strlen(name);
1117
   nml_name->value.character.string = gfc_getmem (strlen (name) + 1);
1118
   strcpy (nml_name->value.character.string, name);
1119
 
1120
   return nml_name;
1121
}
1122
 
1123
/* nml_full_name builds up the fully qualified name of a
1124
   derived type component. */
1125
 
1126
static char*
1127
nml_full_name (const char* var_name, const char* cmp_name)
1128
{
1129
  int full_name_length;
1130
  char * full_name;
1131
 
1132
  full_name_length = strlen (var_name) + strlen (cmp_name) + 1;
1133
  full_name = (char*)gfc_getmem (full_name_length + 1);
1134
  strcpy (full_name, var_name);
1135
  full_name = strcat (full_name, "%");
1136
  full_name = strcat (full_name, cmp_name);
1137
  return full_name;
1138
}
1139
 
1140
/* nml_get_addr_expr builds an address expression from the
1141
   gfc_symbol or gfc_component backend_decl's. An offset is
1142
   provided so that the address of an element of an array of
1143
   derived types is returned. This is used in the runtime to
1144
   determine that span of the derived type. */
1145
 
1146
static tree
1147
nml_get_addr_expr (gfc_symbol * sym, gfc_component * c,
1148
                   tree base_addr)
1149
{
1150
  tree decl = NULL_TREE;
1151
  tree tmp;
1152
  tree itmp;
1153
  int array_flagged;
1154
  int dummy_arg_flagged;
1155
 
1156
  if (sym)
1157
    {
1158
      sym->attr.referenced = 1;
1159
      decl = gfc_get_symbol_decl (sym);
1160
    }
1161
  else
1162
    decl = c->backend_decl;
1163
 
1164
  gcc_assert (decl && ((TREE_CODE (decl) == FIELD_DECL
1165
                     || TREE_CODE (decl) == VAR_DECL
1166
                     || TREE_CODE (decl) == PARM_DECL)
1167
                     || TREE_CODE (decl) == COMPONENT_REF));
1168
 
1169
  tmp = decl;
1170
 
1171
  /* Build indirect reference, if dummy argument.  */
1172
 
1173
  dummy_arg_flagged = POINTER_TYPE_P (TREE_TYPE(tmp));
1174
 
1175
  itmp = (dummy_arg_flagged) ? gfc_build_indirect_ref (tmp) : tmp;
1176
 
1177
  /* If an array, set flag and use indirect ref. if built.  */
1178
 
1179
  array_flagged = (TREE_CODE (TREE_TYPE (itmp)) == ARRAY_TYPE
1180
                   && !TYPE_STRING_FLAG (TREE_TYPE (itmp)));
1181
 
1182
  if (array_flagged)
1183
    tmp = itmp;
1184
 
1185
  /* Treat the component of a derived type, using base_addr for
1186
     the derived type.  */
1187
 
1188
  if (TREE_CODE (decl) == FIELD_DECL)
1189
    tmp = build3 (COMPONENT_REF, TREE_TYPE (tmp),
1190
                  base_addr, tmp, NULL_TREE);
1191
 
1192
  /* If we have a derived type component, a reference to the first
1193
     element of the array is built.  This is done so that base_addr,
1194
     used in the build of the component reference, always points to
1195
     a RECORD_TYPE.  */
1196
 
1197
  if (array_flagged)
1198
    tmp = gfc_build_array_ref (tmp, gfc_index_zero_node);
1199
 
1200
  /* Now build the address expression.  */
1201
 
1202
  tmp = gfc_build_addr_expr (NULL, tmp);
1203
 
1204
  /* If scalar dummy, resolve indirect reference now.  */
1205
 
1206
  if (dummy_arg_flagged && !array_flagged)
1207
    tmp = gfc_build_indirect_ref (tmp);
1208
 
1209
  gcc_assert (tmp && POINTER_TYPE_P (TREE_TYPE (tmp)));
1210
 
1211
  return tmp;
1212
}
1213
 
1214
/* For an object VAR_NAME whose base address is BASE_ADDR, generate a
1215
   call to iocall[IOCALL_SET_NML_VAL].  For derived type variable, recursively
1216
   generate calls to iocall[IOCALL_SET_NML_VAL] for each component.  */
1217
 
1218
#define NML_FIRST_ARG(a) args = gfc_chainon_list (NULL_TREE, a)
1219
#define NML_ADD_ARG(a) args = gfc_chainon_list (args, a)
1220
#define IARG(i) build_int_cst (gfc_array_index_type, i)
1221
 
1222
static void
1223
transfer_namelist_element (stmtblock_t * block, const char * var_name,
1224
                           gfc_symbol * sym, gfc_component * c,
1225
                           tree base_addr)
1226
{
1227
  gfc_typespec * ts = NULL;
1228
  gfc_array_spec * as = NULL;
1229
  tree addr_expr = NULL;
1230
  tree dt = NULL;
1231
  tree string;
1232
  tree tmp;
1233
  tree args;
1234
  tree dtype;
1235
  tree dt_parm_addr;
1236
  int n_dim;
1237
  int itype;
1238
  int rank = 0;
1239
 
1240
  gcc_assert (sym || c);
1241
 
1242
  /* Build the namelist object name.  */
1243
 
1244
  string = gfc_build_cstring_const (var_name);
1245
  string = gfc_build_addr_expr (pchar_type_node, string);
1246
 
1247
  /* Build ts, as and data address using symbol or component.  */
1248
 
1249
  ts = (sym) ? &sym->ts : &c->ts;
1250
  as = (sym) ? sym->as : c->as;
1251
 
1252
  addr_expr = nml_get_addr_expr (sym, c, base_addr);
1253
 
1254
  if (as)
1255
    rank = as->rank;
1256
 
1257
  if (rank)
1258
    {
1259
      dt =  TREE_TYPE ((sym) ? sym->backend_decl : c->backend_decl);
1260
      dtype = gfc_get_dtype (dt);
1261
    }
1262
  else
1263
    {
1264
      itype = GFC_DTYPE_UNKNOWN;
1265
 
1266
      switch (ts->type)
1267
 
1268
        {
1269
        case BT_INTEGER:
1270
          itype = GFC_DTYPE_INTEGER;
1271
          break;
1272
        case BT_LOGICAL:
1273
          itype = GFC_DTYPE_LOGICAL;
1274
          break;
1275
        case BT_REAL:
1276
          itype = GFC_DTYPE_REAL;
1277
          break;
1278
        case BT_COMPLEX:
1279
          itype = GFC_DTYPE_COMPLEX;
1280
        break;
1281
        case BT_DERIVED:
1282
          itype = GFC_DTYPE_DERIVED;
1283
          break;
1284
        case BT_CHARACTER:
1285
          itype = GFC_DTYPE_CHARACTER;
1286
          break;
1287
        default:
1288
          gcc_unreachable ();
1289
        }
1290
 
1291
      dtype = IARG (itype << GFC_DTYPE_TYPE_SHIFT);
1292
    }
1293
 
1294
  /* Build up the arguments for the transfer call.
1295
     The call for the scalar part transfers:
1296
     (address, name, type, kind or string_length, dtype)  */
1297
 
1298
  dt_parm_addr = gfc_build_addr_expr (NULL_TREE, dt_parm);
1299
  NML_FIRST_ARG (dt_parm_addr);
1300
  NML_ADD_ARG (addr_expr);
1301
  NML_ADD_ARG (string);
1302
  NML_ADD_ARG (IARG (ts->kind));
1303
 
1304
  if (ts->type == BT_CHARACTER)
1305
    NML_ADD_ARG (ts->cl->backend_decl);
1306
  else
1307
    NML_ADD_ARG (convert (gfc_charlen_type_node, integer_zero_node));
1308
 
1309
  NML_ADD_ARG (dtype);
1310
  tmp = gfc_build_function_call (iocall[IOCALL_SET_NML_VAL], args);
1311
  gfc_add_expr_to_block (block, tmp);
1312
 
1313
  /* If the object is an array, transfer rank times:
1314
     (null pointer, name, stride, lbound, ubound)  */
1315
 
1316
  for ( n_dim = 0 ; n_dim < rank ; n_dim++ )
1317
    {
1318
      NML_FIRST_ARG (dt_parm_addr);
1319
      NML_ADD_ARG (IARG (n_dim));
1320
      NML_ADD_ARG (GFC_TYPE_ARRAY_STRIDE (dt, n_dim));
1321
      NML_ADD_ARG (GFC_TYPE_ARRAY_LBOUND (dt, n_dim));
1322
      NML_ADD_ARG (GFC_TYPE_ARRAY_UBOUND (dt, n_dim));
1323
      tmp = gfc_build_function_call (iocall[IOCALL_SET_NML_VAL_DIM], args);
1324
      gfc_add_expr_to_block (block, tmp);
1325
    }
1326
 
1327
  if (ts->type == BT_DERIVED)
1328
    {
1329
      gfc_component *cmp;
1330
 
1331
      /* Provide the RECORD_TYPE to build component references.  */
1332
 
1333
      tree expr = gfc_build_indirect_ref (addr_expr);
1334
 
1335
      for (cmp = ts->derived->components; cmp; cmp = cmp->next)
1336
        {
1337
          char *full_name = nml_full_name (var_name, cmp->name);
1338
          transfer_namelist_element (block,
1339
                                     full_name,
1340
                                     NULL, cmp, expr);
1341
          gfc_free (full_name);
1342
        }
1343
    }
1344
}
1345
 
1346
#undef IARG
1347
#undef NML_ADD_ARG
1348
#undef NML_FIRST_ARG
1349
 
1350
/* Create a data transfer statement.  Not all of the fields are valid
1351
   for both reading and writing, but improper use has been filtered
1352
   out by now.  */
1353
 
1354
static tree
1355
build_dt (tree function, gfc_code * code)
1356
{
1357
  stmtblock_t block, post_block, post_end_block;
1358
  gfc_dt *dt;
1359
  tree tmp, var;
1360
  gfc_expr *nmlname;
1361
  gfc_namelist *nml;
1362
  unsigned int mask = 0;
1363
 
1364
  gfc_start_block (&block);
1365
  gfc_init_block (&post_block);
1366
  gfc_init_block (&post_end_block);
1367
 
1368
  var = gfc_create_var (st_parameter[IOPARM_ptype_dt].type, "dt_parm");
1369
 
1370
  set_error_locus (&block, var, &code->loc);
1371
 
1372
  if (last_dt == IOLENGTH)
1373
    {
1374
      gfc_inquire *inq;
1375
 
1376
      inq = code->ext.inquire;
1377
 
1378
      /* First check that preconditions are met.  */
1379
      gcc_assert (inq != NULL);
1380
      gcc_assert (inq->iolength != NULL);
1381
 
1382
      /* Connect to the iolength variable.  */
1383
      mask |= set_parameter_ref (&block, &post_end_block, var,
1384
                                 IOPARM_dt_iolength, inq->iolength);
1385
      dt = NULL;
1386
    }
1387
  else
1388
    {
1389
      dt = code->ext.dt;
1390
      gcc_assert (dt != NULL);
1391
    }
1392
 
1393
  if (dt && dt->io_unit)
1394
    {
1395
      if (dt->io_unit->ts.type == BT_CHARACTER)
1396
        {
1397
          mask |= set_internal_unit (&block, var, dt->io_unit);
1398
          set_parameter_const (&block, var, IOPARM_common_unit, 0);
1399
        }
1400
      else
1401
        set_parameter_value (&block, var, IOPARM_common_unit, dt->io_unit);
1402
    }
1403
  else
1404
    set_parameter_const (&block, var, IOPARM_common_unit, 0);
1405
 
1406
  if (dt)
1407
    {
1408
      if (dt->rec)
1409
        mask |= set_parameter_value (&block, var, IOPARM_dt_rec, dt->rec);
1410
 
1411
      if (dt->advance)
1412
        mask |= set_string (&block, &post_block, var, IOPARM_dt_advance,
1413
                            dt->advance);
1414
 
1415
      if (dt->format_expr)
1416
        mask |= set_string (&block, &post_block, var, IOPARM_dt_format,
1417
                            dt->format_expr);
1418
 
1419
      if (dt->format_label)
1420
        {
1421
          if (dt->format_label == &format_asterisk)
1422
            mask |= IOPARM_dt_list_format;
1423
          else
1424
            mask |= set_string (&block, &post_block, var, IOPARM_dt_format,
1425
                                dt->format_label->format);
1426
        }
1427
 
1428
      if (dt->iomsg)
1429
        mask |= set_string (&block, &post_block, var, IOPARM_common_iomsg,
1430
                            dt->iomsg);
1431
 
1432
      if (dt->iostat)
1433
        mask |= set_parameter_ref (&block, &post_end_block, var,
1434
                                   IOPARM_common_iostat, dt->iostat);
1435
 
1436
      if (dt->size)
1437
        mask |= set_parameter_ref (&block, &post_end_block, var,
1438
                                   IOPARM_dt_size, dt->size);
1439
 
1440
      if (dt->err)
1441
        mask |= IOPARM_common_err;
1442
 
1443
      if (dt->eor)
1444
        mask |= IOPARM_common_eor;
1445
 
1446
      if (dt->end)
1447
        mask |= IOPARM_common_end;
1448
 
1449
      if (dt->namelist)
1450
        {
1451
          if (dt->format_expr || dt->format_label)
1452
            gfc_internal_error ("build_dt: format with namelist");
1453
 
1454
          nmlname = gfc_new_nml_name_expr (dt->namelist->name);
1455
 
1456
          mask |= set_string (&block, &post_block, var, IOPARM_dt_namelist_name,
1457
                              nmlname);
1458
 
1459
          if (last_dt == READ)
1460
            mask |= IOPARM_dt_namelist_read_mode;
1461
 
1462
          set_parameter_const (&block, var, IOPARM_common_flags, mask);
1463
 
1464
          dt_parm = var;
1465
 
1466
          for (nml = dt->namelist->namelist; nml; nml = nml->next)
1467
            transfer_namelist_element (&block, nml->sym->name, nml->sym,
1468
                                       NULL, NULL);
1469
        }
1470
      else
1471
        set_parameter_const (&block, var, IOPARM_common_flags, mask);
1472
    }
1473
  else
1474
    set_parameter_const (&block, var, IOPARM_common_flags, mask);
1475
 
1476
  tmp = gfc_build_addr_expr (NULL_TREE, var);
1477
  tmp = gfc_chainon_list (NULL_TREE, tmp);
1478
  tmp = gfc_build_function_call (function, tmp);
1479
  gfc_add_expr_to_block (&block, tmp);
1480
 
1481
  gfc_add_block_to_block (&block, &post_block);
1482
 
1483
  dt_parm = var;
1484
  dt_post_end_block = &post_end_block;
1485
 
1486
  gfc_add_expr_to_block (&block, gfc_trans_code (code->block->next));
1487
 
1488
  dt_parm = NULL;
1489
  dt_post_end_block = NULL;
1490
 
1491
  return gfc_finish_block (&block);
1492
}
1493
 
1494
 
1495
/* Translate the IOLENGTH form of an INQUIRE statement.  We treat
1496
   this as a third sort of data transfer statement, except that
1497
   lengths are summed instead of actually transferring any data.  */
1498
 
1499
tree
1500
gfc_trans_iolength (gfc_code * code)
1501
{
1502
  last_dt = IOLENGTH;
1503
  return build_dt (iocall[IOCALL_IOLENGTH], code);
1504
}
1505
 
1506
 
1507
/* Translate a READ statement.  */
1508
 
1509
tree
1510
gfc_trans_read (gfc_code * code)
1511
{
1512
  last_dt = READ;
1513
  return build_dt (iocall[IOCALL_READ], code);
1514
}
1515
 
1516
 
1517
/* Translate a WRITE statement */
1518
 
1519
tree
1520
gfc_trans_write (gfc_code * code)
1521
{
1522
  last_dt = WRITE;
1523
  return build_dt (iocall[IOCALL_WRITE], code);
1524
}
1525
 
1526
 
1527
/* Finish a data transfer statement.  */
1528
 
1529
tree
1530
gfc_trans_dt_end (gfc_code * code)
1531
{
1532
  tree function, tmp;
1533
  stmtblock_t block;
1534
 
1535
  gfc_init_block (&block);
1536
 
1537
  switch (last_dt)
1538
    {
1539
    case READ:
1540
      function = iocall[IOCALL_READ_DONE];
1541
      break;
1542
 
1543
    case WRITE:
1544
      function = iocall[IOCALL_WRITE_DONE];
1545
      break;
1546
 
1547
    case IOLENGTH:
1548
      function = iocall[IOCALL_IOLENGTH_DONE];
1549
      break;
1550
 
1551
    default:
1552
      gcc_unreachable ();
1553
    }
1554
 
1555
  tmp = gfc_build_addr_expr (NULL_TREE, dt_parm);
1556
  tmp = gfc_chainon_list (NULL_TREE, tmp);
1557
  tmp = gfc_build_function_call (function, tmp);
1558
  gfc_add_expr_to_block (&block, tmp);
1559
  gfc_add_block_to_block (&block, dt_post_end_block);
1560
  gfc_init_block (dt_post_end_block);
1561
 
1562
  if (last_dt != IOLENGTH)
1563
    {
1564
      gcc_assert (code->ext.dt != NULL);
1565
      io_result (&block, dt_parm, code->ext.dt->err,
1566
                 code->ext.dt->end, code->ext.dt->eor);
1567
    }
1568
 
1569
  return gfc_finish_block (&block);
1570
}
1571
 
1572
static void
1573
transfer_expr (gfc_se * se, gfc_typespec * ts, tree addr_expr);
1574
 
1575
/* Given an array field in a derived type variable, generate the code
1576
   for the loop that iterates over array elements, and the code that
1577
   accesses those array elements.  Use transfer_expr to generate code
1578
   for transferring that element.  Because elements may also be
1579
   derived types, transfer_expr and transfer_array_component are mutually
1580
   recursive.  */
1581
 
1582
static tree
1583
transfer_array_component (tree expr, gfc_component * cm)
1584
{
1585
  tree tmp;
1586
  stmtblock_t body;
1587
  stmtblock_t block;
1588
  gfc_loopinfo loop;
1589
  int n;
1590
  gfc_ss *ss;
1591
  gfc_se se;
1592
 
1593
  gfc_start_block (&block);
1594
  gfc_init_se (&se, NULL);
1595
 
1596
  /* Create and initialize Scalarization Status.  Unlike in
1597
     gfc_trans_transfer, we can't simply use gfc_walk_expr to take
1598
     care of this task, because we don't have a gfc_expr at hand.
1599
     Build one manually, as in gfc_trans_subarray_assign.  */
1600
 
1601
  ss = gfc_get_ss ();
1602
  ss->type = GFC_SS_COMPONENT;
1603
  ss->expr = NULL;
1604
  ss->shape = gfc_get_shape (cm->as->rank);
1605
  ss->next = gfc_ss_terminator;
1606
  ss->data.info.dimen = cm->as->rank;
1607
  ss->data.info.descriptor = expr;
1608
  ss->data.info.data = gfc_conv_array_data (expr);
1609
  ss->data.info.offset = gfc_conv_array_offset (expr);
1610
  for (n = 0; n < cm->as->rank; n++)
1611
    {
1612
      ss->data.info.dim[n] = n;
1613
      ss->data.info.start[n] = gfc_conv_array_lbound (expr, n);
1614
      ss->data.info.stride[n] = gfc_index_one_node;
1615
 
1616
      mpz_init (ss->shape[n]);
1617
      mpz_sub (ss->shape[n], cm->as->upper[n]->value.integer,
1618
               cm->as->lower[n]->value.integer);
1619
      mpz_add_ui (ss->shape[n], ss->shape[n], 1);
1620
    }
1621
 
1622
  /* Once we got ss, we use scalarizer to create the loop.  */
1623
 
1624
  gfc_init_loopinfo (&loop);
1625
  gfc_add_ss_to_loop (&loop, ss);
1626
  gfc_conv_ss_startstride (&loop);
1627
  gfc_conv_loop_setup (&loop);
1628
  gfc_mark_ss_chain_used (ss, 1);
1629
  gfc_start_scalarized_body (&loop, &body);
1630
 
1631
  gfc_copy_loopinfo_to_se (&se, &loop);
1632
  se.ss = ss;
1633
 
1634
  /* gfc_conv_tmp_array_ref assumes that se.expr contains the array.  */
1635
  se.expr = expr;
1636
  gfc_conv_tmp_array_ref (&se);
1637
 
1638
  /* Now se.expr contains an element of the array.  Take the address and pass
1639
     it to the IO routines.  */
1640
  tmp = gfc_build_addr_expr (NULL, se.expr);
1641
  transfer_expr (&se, &cm->ts, tmp);
1642
 
1643
  /* We are done now with the loop body.  Wrap up the scalarizer and
1644
     return.  */
1645
 
1646
  gfc_add_block_to_block (&body, &se.pre);
1647
  gfc_add_block_to_block (&body, &se.post);
1648
 
1649
  gfc_trans_scalarizing_loops (&loop, &body);
1650
 
1651
  gfc_add_block_to_block (&block, &loop.pre);
1652
  gfc_add_block_to_block (&block, &loop.post);
1653
 
1654
  for (n = 0; n < cm->as->rank; n++)
1655
    mpz_clear (ss->shape[n]);
1656
  gfc_free (ss->shape);
1657
 
1658
  gfc_cleanup_loop (&loop);
1659
 
1660
  return gfc_finish_block (&block);
1661
}
1662
 
1663
/* Generate the call for a scalar transfer node.  */
1664
 
1665
static void
1666
transfer_expr (gfc_se * se, gfc_typespec * ts, tree addr_expr)
1667
{
1668
  tree args, tmp, function, arg2, field, expr;
1669
  gfc_component *c;
1670
  int kind;
1671
 
1672
  kind = ts->kind;
1673
  function = NULL;
1674
  arg2 = NULL;
1675
 
1676
  switch (ts->type)
1677
    {
1678
    case BT_INTEGER:
1679
      arg2 = build_int_cst (NULL_TREE, kind);
1680
      function = iocall[IOCALL_X_INTEGER];
1681
      break;
1682
 
1683
    case BT_REAL:
1684
      arg2 = build_int_cst (NULL_TREE, kind);
1685
      function = iocall[IOCALL_X_REAL];
1686
      break;
1687
 
1688
    case BT_COMPLEX:
1689
      arg2 = build_int_cst (NULL_TREE, kind);
1690
      function = iocall[IOCALL_X_COMPLEX];
1691
      break;
1692
 
1693
    case BT_LOGICAL:
1694
      arg2 = build_int_cst (NULL_TREE, kind);
1695
      function = iocall[IOCALL_X_LOGICAL];
1696
      break;
1697
 
1698
    case BT_CHARACTER:
1699
      if (se->string_length)
1700
        arg2 = se->string_length;
1701
      else
1702
        {
1703
          tmp = gfc_build_indirect_ref (addr_expr);
1704
          gcc_assert (TREE_CODE (TREE_TYPE (tmp)) == ARRAY_TYPE);
1705
          arg2 = TYPE_MAX_VALUE (TYPE_DOMAIN (TREE_TYPE (tmp)));
1706
        }
1707
      function = iocall[IOCALL_X_CHARACTER];
1708
      break;
1709
 
1710
    case BT_DERIVED:
1711
      /* Recurse into the elements of the derived type.  */
1712
      expr = gfc_evaluate_now (addr_expr, &se->pre);
1713
      expr = gfc_build_indirect_ref (expr);
1714
 
1715
      for (c = ts->derived->components; c; c = c->next)
1716
        {
1717
          field = c->backend_decl;
1718
          gcc_assert (field && TREE_CODE (field) == FIELD_DECL);
1719
 
1720
          tmp = build3 (COMPONENT_REF, TREE_TYPE (field), expr, field,
1721
                        NULL_TREE);
1722
 
1723
          if (c->dimension)
1724
            {
1725
              tmp = transfer_array_component (tmp, c);
1726
              gfc_add_expr_to_block (&se->pre, tmp);
1727
            }
1728
          else
1729
            {
1730
              if (!c->pointer)
1731
                tmp = gfc_build_addr_expr (NULL, tmp);
1732
              transfer_expr (se, &c->ts, tmp);
1733
            }
1734
        }
1735
      return;
1736
 
1737
    default:
1738
      internal_error ("Bad IO basetype (%d)", ts->type);
1739
    }
1740
 
1741
  tmp = gfc_build_addr_expr (NULL_TREE, dt_parm);
1742
  args = gfc_chainon_list (NULL_TREE, tmp);
1743
  args = gfc_chainon_list (args, addr_expr);
1744
  args = gfc_chainon_list (args, arg2);
1745
 
1746
  tmp = gfc_build_function_call (function, args);
1747
  gfc_add_expr_to_block (&se->pre, tmp);
1748
  gfc_add_block_to_block (&se->pre, &se->post);
1749
 
1750
}
1751
 
1752
 
1753
/* Generate a call to pass an array descriptor to the IO library. The
1754
   array should be of one of the intrinsic types.  */
1755
 
1756
static void
1757
transfer_array_desc (gfc_se * se, gfc_typespec * ts, tree addr_expr)
1758
{
1759
  tree args, tmp, charlen_arg, kind_arg;
1760
 
1761
  if (ts->type == BT_CHARACTER)
1762
    charlen_arg = se->string_length;
1763
  else
1764
    charlen_arg = build_int_cstu (NULL_TREE, 0);
1765
 
1766
  kind_arg = build_int_cst (NULL_TREE, ts->kind);
1767
 
1768
  tmp = gfc_build_addr_expr (NULL_TREE, dt_parm);
1769
  args = gfc_chainon_list (NULL_TREE, tmp);
1770
  args = gfc_chainon_list (args, addr_expr);
1771
  args = gfc_chainon_list (args, kind_arg);
1772
  args = gfc_chainon_list (args, charlen_arg);
1773
  tmp = gfc_build_function_call (iocall[IOCALL_X_ARRAY], args);
1774
  gfc_add_expr_to_block (&se->pre, tmp);
1775
  gfc_add_block_to_block (&se->pre, &se->post);
1776
}
1777
 
1778
 
1779
/* gfc_trans_transfer()-- Translate a TRANSFER code node */
1780
 
1781
tree
1782
gfc_trans_transfer (gfc_code * code)
1783
{
1784
  stmtblock_t block, body;
1785
  gfc_loopinfo loop;
1786
  gfc_expr *expr;
1787
  gfc_ref *ref;
1788
  gfc_ss *ss;
1789
  gfc_se se;
1790
  tree tmp;
1791
 
1792
  gfc_start_block (&block);
1793
  gfc_init_block (&body);
1794
 
1795
  expr = code->expr;
1796
  ss = gfc_walk_expr (expr);
1797
 
1798
  ref = NULL;
1799
  gfc_init_se (&se, NULL);
1800
 
1801
  if (ss == gfc_ss_terminator)
1802
    {
1803
      /* Transfer a scalar value.  */
1804
      gfc_conv_expr_reference (&se, expr);
1805
      transfer_expr (&se, &expr->ts, se.expr);
1806
    }
1807
  else
1808
    {
1809
      /* Transfer an array. If it is an array of an intrinsic
1810
         type, pass the descriptor to the library.  Otherwise
1811
         scalarize the transfer.  */
1812
      if (expr->ref)
1813
        {
1814
          for (ref = expr->ref; ref && ref->type != REF_ARRAY;
1815
                 ref = ref->next);
1816
          gcc_assert (ref->type == REF_ARRAY);
1817
        }
1818
 
1819
      if (expr->ts.type != BT_DERIVED && ref && ref->next == NULL)
1820
        {
1821
          /* Get the descriptor.  */
1822
          gfc_conv_expr_descriptor (&se, expr, ss);
1823
          tmp = gfc_build_addr_expr (NULL, se.expr);
1824
          transfer_array_desc (&se, &expr->ts, tmp);
1825
          goto finish_block_label;
1826
        }
1827
 
1828
      /* Initialize the scalarizer.  */
1829
      gfc_init_loopinfo (&loop);
1830
      gfc_add_ss_to_loop (&loop, ss);
1831
 
1832
      /* Initialize the loop.  */
1833
      gfc_conv_ss_startstride (&loop);
1834
      gfc_conv_loop_setup (&loop);
1835
 
1836
      /* The main loop body.  */
1837
      gfc_mark_ss_chain_used (ss, 1);
1838
      gfc_start_scalarized_body (&loop, &body);
1839
 
1840
      gfc_copy_loopinfo_to_se (&se, &loop);
1841
      se.ss = ss;
1842
 
1843
      gfc_conv_expr_reference (&se, expr);
1844
      transfer_expr (&se, &expr->ts, se.expr);
1845
    }
1846
 
1847
 finish_block_label:
1848
 
1849
  gfc_add_block_to_block (&body, &se.pre);
1850
  gfc_add_block_to_block (&body, &se.post);
1851
 
1852
  if (se.ss == NULL)
1853
    tmp = gfc_finish_block (&body);
1854
  else
1855
    {
1856
      gcc_assert (se.ss == gfc_ss_terminator);
1857
      gfc_trans_scalarizing_loops (&loop, &body);
1858
 
1859
      gfc_add_block_to_block (&loop.pre, &loop.post);
1860
      tmp = gfc_finish_block (&loop.pre);
1861
      gfc_cleanup_loop (&loop);
1862
    }
1863
 
1864
  gfc_add_expr_to_block (&block, tmp);
1865
 
1866
  return gfc_finish_block (&block);
1867
}
1868
 
1869
#include "gt-fortran-trans-io.h"
1870
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.