Home | History | Annotate | Line # | Download | only in m4
      1  1.1  mrg dnl Support macro file for intrinsic functions.
      2  1.1  mrg dnl Contains the generic sections of the array functions.
      3  1.1  mrg dnl This file is part of the GNU Fortran Runtime Library (libgfortran)
      4  1.1  mrg dnl Distributed under the GNU GPL with exception.  See COPYING for details.
      5  1.1  mrg dnl
      6  1.1  mrg dnl Pass the implementation for a single section as the parameter to
      7  1.1  mrg dnl {MASK_}ARRAY_FUNCTION.
      8  1.1  mrg dnl The variables base, delta, and len describe the input section.
      9  1.1  mrg dnl For masked section the mask is described by mbase and mdelta.
     10  1.1  mrg dnl These should not be modified. The result should be stored in *dest.
     11  1.1  mrg dnl The names count, extent, sstride, dstride, base, dest, rank, dim
     12  1.1  mrg dnl retarray, array, pdim and mstride should not be used.
     13  1.1  mrg dnl The variable n is declared as index_type and may be used.
     14  1.1  mrg dnl Other variable declarations may be placed at the start of the code,
     15  1.1  mrg dnl The types of the array parameter and the return value are
     16  1.1  mrg dnl atype_name and rtype_name respectively.
     17  1.1  mrg dnl Execution should be allowed to continue to the end of the block.
     18  1.1  mrg dnl You should not return or break from the inner loop of the implementation.
     19  1.1  mrg dnl Care should also be taken to avoid using the names defined in iparm.m4
     20  1.1  mrg define(START_ARRAY_FUNCTION,
     21  1.1  mrg `
     22  1.1  mrg extern void name`'rtype_qual`_'atype_code (rtype * const restrict, 
     23  1.1  mrg 	gfc_array_l1 * const restrict, const index_type * const restrict);
     24  1.1  mrg export_proto(name`'rtype_qual`_'atype_code);
     25  1.1  mrg 
     26  1.1  mrg void
     27  1.1  mrg name`'rtype_qual`_'atype_code (rtype * const restrict retarray, 
     28  1.1  mrg 	gfc_array_l1 * const restrict array, 
     29  1.1  mrg 	const index_type * const restrict pdim)
     30  1.1  mrg {
     31  1.1  mrg   index_type count[GFC_MAX_DIMENSIONS];
     32  1.1  mrg   index_type extent[GFC_MAX_DIMENSIONS];
     33  1.1  mrg   index_type sstride[GFC_MAX_DIMENSIONS];
     34  1.1  mrg   index_type dstride[GFC_MAX_DIMENSIONS];
     35  1.1  mrg   const GFC_LOGICAL_1 * restrict base;
     36  1.1  mrg   rtype_name * restrict dest;
     37  1.1  mrg   index_type rank;
     38  1.1  mrg   index_type n;
     39  1.1  mrg   index_type len;
     40  1.1  mrg   index_type delta;
     41  1.1  mrg   index_type dim;
     42  1.1  mrg   int src_kind;
     43  1.1  mrg   int continue_loop;
     44  1.1  mrg 
     45  1.1  mrg   /* Make dim zero based to avoid confusion.  */
     46  1.1  mrg   dim = (*pdim) - 1;
     47  1.1  mrg   rank = GFC_DESCRIPTOR_RANK (array) - 1;
     48  1.1  mrg 
     49  1.1  mrg   src_kind = GFC_DESCRIPTOR_SIZE (array);
     50  1.1  mrg 
     51  1.1  mrg   len = GFC_DESCRIPTOR_EXTENT(array,dim);
     52  1.1  mrg   if (len < 0)
     53  1.1  mrg     len = 0;
     54  1.1  mrg 
     55  1.1  mrg   delta = GFC_DESCRIPTOR_STRIDE_BYTES(array,dim);
     56  1.1  mrg 
     57  1.1  mrg   for (n = 0; n < dim; n++)
     58  1.1  mrg     {
     59  1.1  mrg       sstride[n] = GFC_DESCRIPTOR_STRIDE_BYTES(array,n);
     60  1.1  mrg       extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
     61  1.1  mrg 
     62  1.1  mrg       if (extent[n] < 0)
     63  1.1  mrg 	extent[n] = 0;
     64  1.1  mrg     }
     65  1.1  mrg   for (n = dim; n < rank; n++)
     66  1.1  mrg     {
     67  1.1  mrg       sstride[n] = GFC_DESCRIPTOR_STRIDE_BYTES(array,n + 1);
     68  1.1  mrg       extent[n] = GFC_DESCRIPTOR_EXTENT(array,n + 1);
     69  1.1  mrg 
     70  1.1  mrg       if (extent[n] < 0)
     71  1.1  mrg 	extent[n] = 0;
     72  1.1  mrg     }
     73  1.1  mrg 
     74  1.1  mrg   if (retarray->base_addr == NULL)
     75  1.1  mrg     {
     76  1.1  mrg       size_t alloc_size, str;
     77  1.1  mrg 
     78  1.1  mrg       for (n = 0; n < rank; n++)
     79  1.1  mrg         {
     80  1.1  mrg           if (n == 0)
     81  1.1  mrg             str = 1;
     82  1.1  mrg           else
     83  1.1  mrg             str = GFC_DESCRIPTOR_STRIDE(retarray,n-1) * extent[n-1];
     84  1.1  mrg 
     85  1.1  mrg 	  GFC_DIMENSION_SET(retarray->dim[n], 0, extent[n] - 1, str);
     86  1.1  mrg 
     87  1.1  mrg         }
     88  1.1  mrg 
     89  1.1  mrg       retarray->offset = 0;
     90  1.1  mrg       retarray->dtype.rank = rank;
     91  1.1  mrg 
     92  1.1  mrg       alloc_size = GFC_DESCRIPTOR_STRIDE(retarray,rank-1) * extent[rank-1];
     93  1.1  mrg 
     94  1.1  mrg       if (alloc_size == 0)
     95  1.1  mrg 	{
     96  1.1  mrg 	  /* Make sure we have a zero-sized array.  */
     97  1.1  mrg 	  GFC_DIMENSION_SET(retarray->dim[0], 0, -1, 1);
     98  1.1  mrg 	  return;
     99  1.1  mrg 	}
    100  1.1  mrg       else
    101  1.1  mrg 	retarray->base_addr = xmallocarray (alloc_size, sizeof (rtype_name));
    102  1.1  mrg     }
    103  1.1  mrg   else
    104  1.1  mrg     {
    105  1.1  mrg       if (rank != GFC_DESCRIPTOR_RANK (retarray))
    106  1.1  mrg 	runtime_error ("rank of return array incorrect in"
    107  1.1  mrg 		       " u_name intrinsic: is %ld, should be %ld",
    108  1.1  mrg 		       (long int) GFC_DESCRIPTOR_RANK (retarray),
    109  1.1  mrg 		       (long int) rank);
    110  1.1  mrg 
    111  1.1  mrg       if (unlikely (compile_options.bounds_check))
    112  1.1  mrg 	{
    113  1.1  mrg 	  for (n=0; n < rank; n++)
    114  1.1  mrg 	    {
    115  1.1  mrg 	      index_type ret_extent;
    116  1.1  mrg 
    117  1.1  mrg 	      ret_extent = GFC_DESCRIPTOR_EXTENT(retarray,n);
    118  1.1  mrg 	      if (extent[n] != ret_extent)
    119  1.1  mrg 		runtime_error ("Incorrect extent in return value of"
    120  1.1  mrg 			       " u_name intrinsic in dimension %d:"
    121  1.1  mrg 			       " is %ld, should be %ld", (int) n + 1,
    122  1.1  mrg 			       (long int) ret_extent, (long int) extent[n]);
    123  1.1  mrg 	    }
    124  1.1  mrg 	}
    125  1.1  mrg     }
    126  1.1  mrg 
    127  1.1  mrg   for (n = 0; n < rank; n++)
    128  1.1  mrg     {
    129  1.1  mrg       count[n] = 0;
    130  1.1  mrg       dstride[n] = GFC_DESCRIPTOR_STRIDE(retarray,n);
    131  1.1  mrg       if (extent[n] <= 0)
    132  1.1  mrg 	return;
    133  1.1  mrg     }
    134  1.1  mrg 
    135  1.1  mrg   base = array->base_addr;
    136  1.1  mrg 
    137  1.1  mrg   if (src_kind == 1 || src_kind == 2 || src_kind == 4 || src_kind == 8
    138  1.1  mrg #ifdef HAVE_GFC_LOGICAL_16
    139  1.1  mrg       || src_kind == 16
    140  1.1  mrg #endif
    141  1.1  mrg     )
    142  1.1  mrg     {
    143  1.1  mrg       if (base)
    144  1.1  mrg 	base = GFOR_POINTER_TO_L1 (base, src_kind);
    145  1.1  mrg     }
    146  1.1  mrg   else
    147  1.1  mrg     internal_error (NULL, "Funny sized logical array in u_name intrinsic");
    148  1.1  mrg 
    149  1.1  mrg   dest = retarray->base_addr;
    150  1.1  mrg 
    151  1.1  mrg   continue_loop = 1;
    152  1.1  mrg   while (continue_loop)
    153  1.1  mrg     {
    154  1.1  mrg       const GFC_LOGICAL_1 * restrict src;
    155  1.1  mrg       rtype_name result;
    156  1.1  mrg       src = base;
    157  1.1  mrg       {
    158  1.1  mrg ')dnl
    159  1.1  mrg define(START_ARRAY_BLOCK,
    160  1.1  mrg `        if (len <= 0)
    161  1.1  mrg 	  *dest = '$1`;
    162  1.1  mrg 	else
    163  1.1  mrg 	  {
    164  1.1  mrg 	    for (n = 0; n < len; n++, src += delta)
    165  1.1  mrg 	      {
    166  1.1  mrg ')dnl
    167  1.1  mrg define(FINISH_ARRAY_FUNCTION,
    168  1.1  mrg     `          }
    169  1.1  mrg 	    *dest = result;
    170  1.1  mrg 	  }
    171  1.1  mrg       }
    172  1.1  mrg       /* Advance to the next element.  */
    173  1.1  mrg       count[0]++;
    174  1.1  mrg       base += sstride[0];
    175  1.1  mrg       dest += dstride[0];
    176  1.1  mrg       n = 0;
    177  1.1  mrg       while (count[n] == extent[n])
    178  1.1  mrg         {
    179  1.1  mrg           /* When we get to the end of a dimension, reset it and increment
    180  1.1  mrg              the next dimension.  */
    181  1.1  mrg           count[n] = 0;
    182  1.1  mrg           /* We could precalculate these products, but this is a less
    183  1.1  mrg              frequently used path so probably not worth it.  */
    184  1.1  mrg           base -= sstride[n] * extent[n];
    185  1.1  mrg           dest -= dstride[n] * extent[n];
    186  1.1  mrg           n++;
    187  1.1  mrg           if (n >= rank)
    188  1.1  mrg             {
    189  1.1  mrg               /* Break out of the loop.  */
    190  1.1  mrg               continue_loop = 0;
    191  1.1  mrg               break;
    192  1.1  mrg             }
    193  1.1  mrg           else
    194  1.1  mrg             {
    195  1.1  mrg               count[n]++;
    196  1.1  mrg               base += sstride[n];
    197  1.1  mrg               dest += dstride[n];
    198  1.1  mrg             }
    199  1.1  mrg         }
    200  1.1  mrg     }
    201  1.1  mrg }')dnl
    202  1.1  mrg define(ARRAY_FUNCTION,
    203  1.1  mrg `START_ARRAY_FUNCTION
    204  1.1  mrg $2
    205  1.1  mrg START_ARRAY_BLOCK($1)
    206  1.1  mrg $3
    207  1.1  mrg FINISH_ARRAY_FUNCTION')dnl
    208