Commit 18623fae by Janne Blomqvist Committed by Bud Davis

[multiple changes]

2005-09-24  Janne Blomqvist  <jblomqvi@cc.hut.fi>

	* trans-io.c (gfc_build_io_library_fndecls): Add entry
	iocall_x_array for transfer_array. (transfer_array_desc): New
	function. (gfc_trans_transfer): Add code to call
	transfer_array_desc.

2005-09-24  Janne Blomqvist <jblomqvi@cc.hut.fi>

	* io.h: Changed prototypes of list_formatted_{read|write}.
	* list_read.c (list_formatted_read): Renamed to
	list_formatted_read_scalar and made static. (list_formatted_read):
	New function.
	* transfer.c: Prototype for transfer_array. Changed transfer
	function pointer. (unformatted_read): Add nelems argument, use
	it. (unformatted_write): Likewise. (formatted_transfer): Changed
	name to formatted_transfer_scalar. (formatted_transfer): New
	function. (transfer_integer): Add nelems argument to transfer
	call, move updating item count to transfer
	functions. (transfer_real): Likewise. (transfer_logical):
	Likewise. (transfer_character): Likewise. (transfer_complex):
	Likewise. (transfer_array): New function. (data_transfer_init):
	Call formatted_transfer with new argument. (iolength_transfer):
	New argument, use it.
	* write.c (list_formatted_write): Renamed to
	list_formatted_write_scalar, made static. (list_formatted_write):
	New function.

From-SVN: r104662
parent d05d9ac7
2005-09-24 Janne Blomqvist <jblomqvi@cc.hut.fi>
* trans-io.c (gfc_build_io_library_fndecls): Add entry
iocall_x_array for transfer_array. (transfer_array_desc): New
function. (gfc_trans_transfer): Add code to call
transfer_array_desc.
2005-09-26 Jakub Jelinek <jakub@redhat.com> 2005-09-26 Jakub Jelinek <jakub@redhat.com>
PR fortran/23677 PR fortran/23677
......
...@@ -120,6 +120,7 @@ static GTY(()) tree iocall_x_logical; ...@@ -120,6 +120,7 @@ static GTY(()) tree iocall_x_logical;
static GTY(()) tree iocall_x_character; static GTY(()) tree iocall_x_character;
static GTY(()) tree iocall_x_real; static GTY(()) tree iocall_x_real;
static GTY(()) tree iocall_x_complex; static GTY(()) tree iocall_x_complex;
static GTY(()) tree iocall_x_array;
static GTY(()) tree iocall_open; static GTY(()) tree iocall_open;
static GTY(()) tree iocall_close; static GTY(()) tree iocall_close;
static GTY(()) tree iocall_inquire; static GTY(()) tree iocall_inquire;
...@@ -267,6 +268,12 @@ gfc_build_io_library_fndecls (void) ...@@ -267,6 +268,12 @@ gfc_build_io_library_fndecls (void)
void_type_node, 2, pvoid_type_node, void_type_node, 2, pvoid_type_node,
gfc_int4_type_node); gfc_int4_type_node);
iocall_x_array =
gfc_build_library_function_decl (get_identifier
(PREFIX("transfer_array")),
void_type_node, 2, pvoid_type_node,
gfc_charlen_type_node);
/* Library entry points */ /* Library entry points */
iocall_read = iocall_read =
...@@ -1584,6 +1591,27 @@ transfer_expr (gfc_se * se, gfc_typespec * ts, tree addr_expr) ...@@ -1584,6 +1591,27 @@ transfer_expr (gfc_se * se, gfc_typespec * ts, tree addr_expr)
} }
/* Generate a call to pass an array descriptor to the IO library. The
array should be of one of the intrinsic types. */
static void
transfer_array_desc (gfc_se * se, gfc_typespec * ts, tree addr_expr)
{
tree args, tmp, charlen_arg;
if (ts->type == BT_CHARACTER)
charlen_arg = se->string_length;
else
charlen_arg = build_int_cstu (NULL_TREE, 0);
args = gfc_chainon_list (NULL_TREE, addr_expr);
args = gfc_chainon_list (args, charlen_arg);
tmp = gfc_build_function_call (iocall_x_array, args);
gfc_add_expr_to_block (&se->pre, tmp);
gfc_add_block_to_block (&se->pre, &se->post);
}
/* gfc_trans_transfer()-- Translate a TRANSFER code node */ /* gfc_trans_transfer()-- Translate a TRANSFER code node */
tree tree
...@@ -1597,6 +1625,7 @@ gfc_trans_transfer (gfc_code * code) ...@@ -1597,6 +1625,7 @@ gfc_trans_transfer (gfc_code * code)
tree tmp; tree tmp;
gfc_start_block (&block); gfc_start_block (&block);
gfc_init_block (&body);
expr = code->expr; expr = code->expr;
ss = gfc_walk_expr (expr); ss = gfc_walk_expr (expr);
...@@ -1604,8 +1633,11 @@ gfc_trans_transfer (gfc_code * code) ...@@ -1604,8 +1633,11 @@ gfc_trans_transfer (gfc_code * code)
gfc_init_se (&se, NULL); gfc_init_se (&se, NULL);
if (ss == gfc_ss_terminator) if (ss == gfc_ss_terminator)
gfc_init_block (&body); {
else gfc_conv_expr_reference (&se, expr);
transfer_expr (&se, &expr->ts, se.expr);
}
else if (expr->ts.type == BT_DERIVED)
{ {
/* Initialize the scalarizer. */ /* Initialize the scalarizer. */
gfc_init_loopinfo (&loop); gfc_init_loopinfo (&loop);
...@@ -1621,11 +1653,17 @@ gfc_trans_transfer (gfc_code * code) ...@@ -1621,11 +1653,17 @@ gfc_trans_transfer (gfc_code * code)
gfc_copy_loopinfo_to_se (&se, &loop); gfc_copy_loopinfo_to_se (&se, &loop);
se.ss = ss; se.ss = ss;
}
gfc_conv_expr_reference (&se, expr);
transfer_expr (&se, &expr->ts, se.expr); gfc_conv_expr_reference (&se, expr);
transfer_expr (&se, &expr->ts, se.expr);
}
else
{
/* Pass the array descriptor to the library. */
gfc_conv_expr_descriptor (&se, expr, ss);
tmp = gfc_build_addr_expr (NULL, se.expr);
transfer_array_desc (&se, &expr->ts, tmp);
}
gfc_add_block_to_block (&body, &se.pre); gfc_add_block_to_block (&body, &se.pre);
gfc_add_block_to_block (&body, &se.post); gfc_add_block_to_block (&body, &se.post);
......
2005-09-24 Janne Blomqvist <jblomqvi@cc.hut.fi>
* io.h: Changed prototypes of list_formatted_{read|write}.
* list_read.c (list_formatted_read): Renamed to
list_formatted_read_scalar and made static. (list_formatted_read):
New function.
* transfer.c: Prototype for transfer_array. Changed transfer
function pointer. (unformatted_read): Add nelems argument, use
it. (unformatted_write): Likewise. (formatted_transfer): Changed
name to formatted_transfer_scalar. (formatted_transfer): New
function. (transfer_integer): Add nelems argument to transfer
call, move updating item count to transfer
functions. (transfer_real): Likewise. (transfer_logical):
Likewise. (transfer_character): Likewise. (transfer_complex):
Likewise. (transfer_array): New function. (data_transfer_init):
Call formatted_transfer with new argument. (iolength_transfer):
New argument, use it.
* write.c (list_formatted_write): Renamed to
list_formatted_write_scalar, made static. (list_formatted_write):
New function.
2005-09-26 David Edelsohn <dje@watson.ibm.com> 2005-09-26 David Edelsohn <dje@watson.ibm.com>
* configure.ac: Add check for __clog. * configure.ac: Add check for __clog.
......
...@@ -613,7 +613,7 @@ internal_proto(read_decimal); ...@@ -613,7 +613,7 @@ internal_proto(read_decimal);
/* list_read.c */ /* list_read.c */
extern void list_formatted_read (bt, void *, int); extern void list_formatted_read (bt, void *, int, size_t);
internal_proto(list_formatted_read); internal_proto(list_formatted_read);
extern void finish_list_read (void); extern void finish_list_read (void);
...@@ -666,7 +666,7 @@ internal_proto(write_x); ...@@ -666,7 +666,7 @@ internal_proto(write_x);
extern void write_z (fnode *, const char *, int); extern void write_z (fnode *, const char *, int);
internal_proto(write_z); internal_proto(write_z);
extern void list_formatted_write (bt, void *, int); extern void list_formatted_write (bt, void *, int, size_t);
internal_proto(list_formatted_write); internal_proto(list_formatted_write);
/* error.c */ /* error.c */
......
...@@ -1285,8 +1285,8 @@ check_type (bt type, int len) ...@@ -1285,8 +1285,8 @@ check_type (bt type, int len)
reading, usually in the value[] array. If a repeat count is reading, usually in the value[] array. If a repeat count is
greater than one, we copy the data item multiple times. */ greater than one, we copy the data item multiple times. */
void static void
list_formatted_read (bt type, void *p, int len) list_formatted_read_scalar (bt type, void *p, int len)
{ {
char c; char c;
int m; int m;
...@@ -1406,6 +1406,30 @@ list_formatted_read (bt type, void *p, int len) ...@@ -1406,6 +1406,30 @@ list_formatted_read (bt type, void *p, int len)
free_saved (); free_saved ();
} }
void
list_formatted_read (bt type, void *p, int len, size_t nelems)
{
size_t elem;
int size;
char *tmp;
tmp = (char *) p;
if (type == BT_COMPLEX)
size = 2 * len;
else
size = len;
/* Big loop over all the elements. */
for (elem = 0; elem < nelems; elem++)
{
g.item_count++;
list_formatted_read_scalar (type, tmp + size*elem, len);
}
}
void void
init_at_eol(void) init_at_eol(void)
{ {
......
...@@ -78,6 +78,9 @@ export_proto(transfer_character); ...@@ -78,6 +78,9 @@ export_proto(transfer_character);
extern void transfer_complex (void *, int); extern void transfer_complex (void *, int);
export_proto(transfer_complex); export_proto(transfer_complex);
extern void transfer_array (gfc_array_char *, gfc_charlen_type);
export_proto(transfer_array);
gfc_unit *current_unit = NULL; gfc_unit *current_unit = NULL;
static int sf_seen_eor = 0; static int sf_seen_eor = 0;
static int eor_condition = 0; static int eor_condition = 0;
...@@ -101,7 +104,7 @@ static st_option advance_opt[] = { ...@@ -101,7 +104,7 @@ static st_option advance_opt[] = {
}; };
static void (*transfer) (bt, void *, int); static void (*transfer) (bt, void *, int, size_t);
typedef enum typedef enum
...@@ -312,11 +315,13 @@ write_block (int length) ...@@ -312,11 +315,13 @@ write_block (int length)
/* Master function for unformatted reads. */ /* Master function for unformatted reads. */
static void static void
unformatted_read (bt type, void *dest, int length) unformatted_read (bt type, void *dest, int length, size_t nelems)
{ {
void *source; void *source;
int w; int w;
length *= nelems;
/* Transfer functions get passed the kind of the entity, so we have /* Transfer functions get passed the kind of the entity, so we have
to fix this for COMPLEX data which are twice the size of their to fix this for COMPLEX data which are twice the size of their
kind. */ kind. */
...@@ -337,17 +342,20 @@ unformatted_read (bt type, void *dest, int length) ...@@ -337,17 +342,20 @@ unformatted_read (bt type, void *dest, int length)
/* Master function for unformatted writes. */ /* Master function for unformatted writes. */
static void static void
unformatted_write (bt type, void *source, int length) unformatted_write (bt type, void *source, int length, size_t nelems)
{ {
void *dest; void *dest;
size_t len;
len = length * nelems;
/* Correction for kind vs. length as in unformatted_read. */ /* Correction for kind vs. length as in unformatted_read. */
if (type == BT_COMPLEX) if (type == BT_COMPLEX)
length *= 2; len *= 2;
dest = write_block (length); dest = write_block (len);
if (dest != NULL) if (dest != NULL)
memcpy (dest, source, length); memcpy (dest, source, len);
} }
...@@ -442,7 +450,7 @@ require_type (bt expected, bt actual, fnode * f) ...@@ -442,7 +450,7 @@ require_type (bt expected, bt actual, fnode * f)
of the next element, then comes back here to process it. */ of the next element, then comes back here to process it. */
static void static void
formatted_transfer (bt type, void *p, int len) formatted_transfer_scalar (bt type, void *p, int len)
{ {
int pos, bytes_used; int pos, bytes_used;
fnode *f; fnode *f;
...@@ -837,6 +845,29 @@ formatted_transfer (bt type, void *p, int len) ...@@ -837,6 +845,29 @@ formatted_transfer (bt type, void *p, int len)
unget_format (f); unget_format (f);
} }
static void
formatted_transfer (bt type, void *p, int len, size_t nelems)
{
size_t elem;
int size;
char *tmp;
tmp = (char *) p;
if (type == BT_COMPLEX)
size = 2 * len;
else
size = len;
/* Big loop over all the elements. */
for (elem = 0; elem < nelems; elem++)
{
g.item_count++;
formatted_transfer_scalar (type, tmp + size*elem, len);
}
}
/* Data transfer entry points. The type of the data entity is /* Data transfer entry points. The type of the data entity is
implicit in the subroutine call. This prevents us from having to implicit in the subroutine call. This prevents us from having to
...@@ -845,50 +876,153 @@ formatted_transfer (bt type, void *p, int len) ...@@ -845,50 +876,153 @@ formatted_transfer (bt type, void *p, int len)
void void
transfer_integer (void *p, int kind) transfer_integer (void *p, int kind)
{ {
g.item_count++;
if (ioparm.library_return != LIBRARY_OK) if (ioparm.library_return != LIBRARY_OK)
return; return;
transfer (BT_INTEGER, p, kind); transfer (BT_INTEGER, p, kind, 1);
} }
void void
transfer_real (void *p, int kind) transfer_real (void *p, int kind)
{ {
g.item_count++;
if (ioparm.library_return != LIBRARY_OK) if (ioparm.library_return != LIBRARY_OK)
return; return;
transfer (BT_REAL, p, kind); transfer (BT_REAL, p, kind, 1);
} }
void void
transfer_logical (void *p, int kind) transfer_logical (void *p, int kind)
{ {
g.item_count++;
if (ioparm.library_return != LIBRARY_OK) if (ioparm.library_return != LIBRARY_OK)
return; return;
transfer (BT_LOGICAL, p, kind); transfer (BT_LOGICAL, p, kind, 1);
} }
void void
transfer_character (void *p, int len) transfer_character (void *p, int len)
{ {
g.item_count++;
if (ioparm.library_return != LIBRARY_OK) if (ioparm.library_return != LIBRARY_OK)
return; return;
transfer (BT_CHARACTER, p, len); transfer (BT_CHARACTER, p, len, 1);
} }
void void
transfer_complex (void *p, int kind) transfer_complex (void *p, int kind)
{ {
g.item_count++;
if (ioparm.library_return != LIBRARY_OK) if (ioparm.library_return != LIBRARY_OK)
return; return;
transfer (BT_COMPLEX, p, kind); transfer (BT_COMPLEX, p, kind, 1);
}
void
transfer_array (gfc_array_char *desc, gfc_charlen_type charlen)
{
index_type count[GFC_MAX_DIMENSIONS];
index_type extent[GFC_MAX_DIMENSIONS];
index_type stride[GFC_MAX_DIMENSIONS];
index_type stride0, rank, size, type, n, kind;
size_t tsize;
char *data;
bt iotype;
if (ioparm.library_return != LIBRARY_OK)
return;
type = GFC_DESCRIPTOR_TYPE (desc);
size = GFC_DESCRIPTOR_SIZE (desc);
kind = size;
/* FIXME: What a kludge: Array descriptors and the IO library use
different enums for types. */
switch (type)
{
case GFC_DTYPE_UNKNOWN:
iotype = BT_NULL; /* Is this correct? */
break;
case GFC_DTYPE_INTEGER:
iotype = BT_INTEGER;
break;
case GFC_DTYPE_LOGICAL:
iotype = BT_LOGICAL;
break;
case GFC_DTYPE_REAL:
iotype = BT_REAL;
break;
case GFC_DTYPE_COMPLEX:
iotype = BT_COMPLEX;
kind /= 2;
break;
case GFC_DTYPE_CHARACTER:
iotype = BT_CHARACTER;
/* FIXME: Currently dtype contains the charlen, which is
clobbered if charlen > 2**24. That's why we use a separate
argument for the charlen. However, if we want to support
non-8-bit charsets we need to fix dtype to contain
sizeof(chartype) and fix the code below. */
size = charlen;
kind = charlen;
break;
case GFC_DTYPE_DERIVED:
internal_error ("Derived type I/O should have been handled via the frontend.");
break;
default:
internal_error ("transfer_array(): Bad type");
}
if (desc->dim[0].stride == 0)
desc->dim[0].stride = 1;
rank = GFC_DESCRIPTOR_RANK (desc);
for (n = 0; n < rank; n++)
{
count[n] = 0;
stride[n] = desc->dim[n].stride;
extent[n] = desc->dim[n].ubound + 1 - desc->dim[n].lbound;
/* If the extent of even one dimension is zero, then the entire
array section contains zero elements, so we return. */
if (extent[n] == 0)
return;
}
stride0 = stride[0];
/* If the innermost dimension has stride 1, we can do the transfer
in contiguous chunks. */
if (stride0 == 1)
tsize = extent[0];
else
tsize = 1;
data = GFC_DESCRIPTOR_DATA (desc);
while (data)
{
transfer (iotype, data, kind, tsize);
data += stride0 * size * tsize;
count[0] += tsize;
n = 0;
while (count[n] == extent[n])
{
count[n] = 0;
data -= stride[n] * extent[n] * size;
n++;
if (n == rank)
{
data = NULL;
break;
}
else
{
count[n]++;
data += stride[n] * size;
}
}
}
} }
...@@ -1245,7 +1379,7 @@ data_transfer_init (int read_flag) ...@@ -1245,7 +1379,7 @@ data_transfer_init (int read_flag)
/* Start the data transfer if we are doing a formatted transfer. */ /* Start the data transfer if we are doing a formatted transfer. */
if (current_unit->flags.form == FORM_FORMATTED && !ioparm.list_format if (current_unit->flags.form == FORM_FORMATTED && !ioparm.list_format
&& ioparm.namelist_name == NULL && ionml == NULL) && ioparm.namelist_name == NULL && ionml == NULL)
formatted_transfer (0, NULL, 0); formatted_transfer (0, NULL, 0, 1);
} }
...@@ -1568,15 +1702,15 @@ finalize_transfer (void) ...@@ -1568,15 +1702,15 @@ finalize_transfer (void)
data transfer, it just updates the length counter. */ data transfer, it just updates the length counter. */
static void static void
iolength_transfer (bt type , void *dest __attribute__ ((unused)), iolength_transfer (bt type, void *dest __attribute__ ((unused)),
int len) int len, size_t nelems)
{ {
if (ioparm.iolength != NULL) if (ioparm.iolength != NULL)
{ {
if (type == BT_COMPLEX) if (type == BT_COMPLEX)
*ioparm.iolength += 2*len; *ioparm.iolength += 2 * len * nelems;
else else
*ioparm.iolength += len; *ioparm.iolength += len * nelems;
} }
} }
......
...@@ -1423,8 +1423,8 @@ write_separator (void) ...@@ -1423,8 +1423,8 @@ write_separator (void)
TODO: handle skipping to the next record correctly, particularly TODO: handle skipping to the next record correctly, particularly
with strings. */ with strings. */
void static void
list_formatted_write (bt type, void *p, int len) list_formatted_write_scalar (bt type, void *p, int len)
{ {
static int char_flag; static int char_flag;
...@@ -1468,6 +1468,29 @@ list_formatted_write (bt type, void *p, int len) ...@@ -1468,6 +1468,29 @@ list_formatted_write (bt type, void *p, int len)
char_flag = (type == BT_CHARACTER); char_flag = (type == BT_CHARACTER);
} }
void
list_formatted_write (bt type, void *p, int len, size_t nelems)
{
size_t elem;
int size;
char *tmp;
tmp = (char *) p;
if (type == BT_COMPLEX)
size = 2 * len;
else
size = len;
/* Big loop over all the elements. */
for (elem = 0; elem < nelems; elem++)
{
g.item_count++;
list_formatted_write_scalar (type, tmp + size*elem, len);
}
}
/* NAMELIST OUTPUT /* NAMELIST OUTPUT
nml_write_obj writes a namelist object to the output stream. It is called nml_write_obj writes a namelist object to the output stream. It is called
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment