Retro68/gcc/libgfortran/m4/iforeach.m4

283 lines
6.9 KiB
Plaintext
Raw Normal View History

2012-03-27 23:13:14 +00:00
dnl Support macro file for intrinsic functions.
dnl Contains the generic sections of the array functions.
2014-09-21 17:33:12 +00:00
dnl This file is part of the GNU Fortran Runtime Library (libgfortran)
2012-03-27 23:13:14 +00:00
dnl Distributed under the GNU GPL with exception. See COPYING for details.
define(START_FOREACH_FUNCTION,
`
extern void name`'rtype_qual`_'atype_code (rtype * const restrict retarray,
2018-12-28 15:30:48 +00:00
atype * const restrict array, GFC_LOGICAL_4);
2012-03-27 23:13:14 +00:00
export_proto(name`'rtype_qual`_'atype_code);
void
name`'rtype_qual`_'atype_code (rtype * const restrict retarray,
2018-12-28 15:30:48 +00:00
atype * const restrict array, GFC_LOGICAL_4 back)
2012-03-27 23:13:14 +00:00
{
index_type count[GFC_MAX_DIMENSIONS];
index_type extent[GFC_MAX_DIMENSIONS];
index_type sstride[GFC_MAX_DIMENSIONS];
index_type dstride;
const atype_name *base;
rtype_name * restrict dest;
index_type rank;
index_type n;
2018-12-28 15:30:48 +00:00
assert(back == 0);
2012-03-27 23:13:14 +00:00
rank = GFC_DESCRIPTOR_RANK (array);
if (rank <= 0)
runtime_error ("Rank of array needs to be > 0");
2014-09-21 17:33:12 +00:00
if (retarray->base_addr == NULL)
2012-03-27 23:13:14 +00:00
{
GFC_DIMENSION_SET(retarray->dim[0], 0, rank-1, 1);
2018-12-28 15:30:48 +00:00
retarray->dtype.rank = 1;
2012-03-27 23:13:14 +00:00
retarray->offset = 0;
2015-08-28 15:33:40 +00:00
retarray->base_addr = xmallocarray (rank, sizeof (rtype_name));
2012-03-27 23:13:14 +00:00
}
else
{
if (unlikely (compile_options.bounds_check))
bounds_iforeach_return ((array_t *) retarray, (array_t *) array,
"u_name");
}
dstride = GFC_DESCRIPTOR_STRIDE(retarray,0);
2014-09-21 17:33:12 +00:00
dest = retarray->base_addr;
2012-03-27 23:13:14 +00:00
for (n = 0; n < rank; n++)
{
sstride[n] = GFC_DESCRIPTOR_STRIDE(array,n);
extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
count[n] = 0;
if (extent[n] <= 0)
{
/* Set the return value. */
for (n = 0; n < rank; n++)
dest[n * dstride] = 0;
return;
}
}
2014-09-21 17:33:12 +00:00
base = array->base_addr;
2012-03-27 23:13:14 +00:00
/* Initialize the return value. */
for (n = 0; n < rank; n++)
dest[n * dstride] = 1;
{
')dnl
define(START_FOREACH_BLOCK,
` while (base)
{
do
{
/* Implementation start. */
')dnl
define(FINISH_FOREACH_FUNCTION,
` /* Implementation end. */
/* Advance to the next element. */
base += sstride[0];
}
while (++count[0] != extent[0]);
n = 0;
do
{
/* When we get to the end of a dimension, reset it and increment
the next dimension. */
count[n] = 0;
/* We could precalculate these products, but this is a less
frequently used path so probably not worth it. */
base -= sstride[n] * extent[n];
n++;
if (n >= rank)
2012-03-27 23:13:14 +00:00
{
/* Break out of the loop. */
base = NULL;
break;
}
else
{
count[n]++;
base += sstride[n];
}
}
while (count[n] == extent[n]);
}
}
}')dnl
define(START_MASKED_FOREACH_FUNCTION,
`
extern void `m'name`'rtype_qual`_'atype_code (rtype * const restrict,
2018-12-28 15:30:48 +00:00
atype * const restrict, gfc_array_l1 * const restrict,
GFC_LOGICAL_4);
2012-03-27 23:13:14 +00:00
export_proto(`m'name`'rtype_qual`_'atype_code);
void
`m'name`'rtype_qual`_'atype_code (rtype * const restrict retarray,
atype * const restrict array,
2018-12-28 15:30:48 +00:00
gfc_array_l1 * const restrict mask, GFC_LOGICAL_4 back)
2012-03-27 23:13:14 +00:00
{
index_type count[GFC_MAX_DIMENSIONS];
index_type extent[GFC_MAX_DIMENSIONS];
index_type sstride[GFC_MAX_DIMENSIONS];
index_type mstride[GFC_MAX_DIMENSIONS];
index_type dstride;
rtype_name *dest;
const atype_name *base;
GFC_LOGICAL_1 *mbase;
int rank;
index_type n;
int mask_kind;
2018-12-28 15:30:48 +00:00
assert(back == 0);
2012-03-27 23:13:14 +00:00
rank = GFC_DESCRIPTOR_RANK (array);
if (rank <= 0)
runtime_error ("Rank of array needs to be > 0");
2014-09-21 17:33:12 +00:00
if (retarray->base_addr == NULL)
2012-03-27 23:13:14 +00:00
{
GFC_DIMENSION_SET(retarray->dim[0], 0, rank - 1, 1);
2018-12-28 15:30:48 +00:00
retarray->dtype.rank = 1;
2012-03-27 23:13:14 +00:00
retarray->offset = 0;
2015-08-28 15:33:40 +00:00
retarray->base_addr = xmallocarray (rank, sizeof (rtype_name));
2012-03-27 23:13:14 +00:00
}
else
{
if (unlikely (compile_options.bounds_check))
{
bounds_iforeach_return ((array_t *) retarray, (array_t *) array,
"u_name");
bounds_equal_extents ((array_t *) mask, (array_t *) array,
"MASK argument", "u_name");
}
}
mask_kind = GFC_DESCRIPTOR_SIZE (mask);
2014-09-21 17:33:12 +00:00
mbase = mask->base_addr;
2012-03-27 23:13:14 +00:00
if (mask_kind == 1 || mask_kind == 2 || mask_kind == 4 || mask_kind == 8
#ifdef HAVE_GFC_LOGICAL_16
|| mask_kind == 16
#endif
)
mbase = GFOR_POINTER_TO_L1 (mbase, mask_kind);
else
runtime_error ("Funny sized logical array");
dstride = GFC_DESCRIPTOR_STRIDE(retarray,0);
2014-09-21 17:33:12 +00:00
dest = retarray->base_addr;
2012-03-27 23:13:14 +00:00
for (n = 0; n < rank; n++)
{
sstride[n] = GFC_DESCRIPTOR_STRIDE(array,n);
mstride[n] = GFC_DESCRIPTOR_STRIDE_BYTES(mask,n);
extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
count[n] = 0;
if (extent[n] <= 0)
{
/* Set the return value. */
for (n = 0; n < rank; n++)
dest[n * dstride] = 0;
return;
}
}
2014-09-21 17:33:12 +00:00
base = array->base_addr;
2012-03-27 23:13:14 +00:00
/* Initialize the return value. */
for (n = 0; n < rank; n++)
dest[n * dstride] = 0;
{
')dnl
define(START_MASKED_FOREACH_BLOCK, `START_FOREACH_BLOCK')dnl
define(FINISH_MASKED_FOREACH_FUNCTION,
` /* Implementation end. */
/* Advance to the next element. */
base += sstride[0];
mbase += mstride[0];
}
while (++count[0] != extent[0]);
n = 0;
do
{
/* When we get to the end of a dimension, reset it and increment
the next dimension. */
count[n] = 0;
/* We could precalculate these products, but this is a less
frequently used path so probably not worth it. */
base -= sstride[n] * extent[n];
mbase -= mstride[n] * extent[n];
n++;
if (n >= rank)
2012-03-27 23:13:14 +00:00
{
/* Break out of the loop. */
base = NULL;
break;
}
else
{
count[n]++;
base += sstride[n];
mbase += mstride[n];
}
}
while (count[n] == extent[n]);
}
}
}')dnl
define(FOREACH_FUNCTION,
`START_FOREACH_FUNCTION
$1
START_FOREACH_BLOCK
$2
FINISH_FOREACH_FUNCTION')dnl
define(MASKED_FOREACH_FUNCTION,
`START_MASKED_FOREACH_FUNCTION
$1
START_MASKED_FOREACH_BLOCK
$2
FINISH_MASKED_FOREACH_FUNCTION')dnl
define(SCALAR_FOREACH_FUNCTION,
`
extern void `s'name`'rtype_qual`_'atype_code (rtype * const restrict,
2018-12-28 15:30:48 +00:00
atype * const restrict, GFC_LOGICAL_4 *, GFC_LOGICAL_4);
2012-03-27 23:13:14 +00:00
export_proto(`s'name`'rtype_qual`_'atype_code);
void
`s'name`'rtype_qual`_'atype_code (rtype * const restrict retarray,
atype * const restrict array,
2018-12-28 15:30:48 +00:00
GFC_LOGICAL_4 * mask, GFC_LOGICAL_4 back)
2012-03-27 23:13:14 +00:00
{
index_type rank;
index_type dstride;
index_type n;
rtype_name *dest;
if (*mask)
{
2018-12-28 15:30:48 +00:00
name`'rtype_qual`_'atype_code (retarray, array, back);
2012-03-27 23:13:14 +00:00
return;
}
rank = GFC_DESCRIPTOR_RANK (array);
if (rank <= 0)
runtime_error ("Rank of array needs to be > 0");
2014-09-21 17:33:12 +00:00
if (retarray->base_addr == NULL)
2012-03-27 23:13:14 +00:00
{
GFC_DIMENSION_SET(retarray->dim[0], 0, rank-1, 1);
2018-12-28 15:30:48 +00:00
retarray->dtype.rank = 1;
2012-03-27 23:13:14 +00:00
retarray->offset = 0;
2015-08-28 15:33:40 +00:00
retarray->base_addr = xmallocarray (rank, sizeof (rtype_name));
2012-03-27 23:13:14 +00:00
}
else if (unlikely (compile_options.bounds_check))
{
bounds_iforeach_return ((array_t *) retarray, (array_t *) array,
"u_name");
}
dstride = GFC_DESCRIPTOR_STRIDE(retarray,0);
2014-09-21 17:33:12 +00:00
dest = retarray->base_addr;
2012-03-27 23:13:14 +00:00
for (n = 0; n<rank; n++)
dest[n * dstride] = $1 ;
}')dnl