* gcc-interface/decl.c (gnat_to_gnu_field): Do not set the alignment
[official-gcc.git] / libgfortran / m4 / iforeach-s.m4
blob39868ddf3eef6a553c2466b14506dcce5715085b
1 dnl Support macro file for intrinsic functions.
2 dnl Contains the generic sections of the array functions.
3 dnl This file is part of the GNU Fortran Runtime Library (libgfortran)
4 dnl Distributed under the GNU GPL with exception.  See COPYING for details.
5 define(START_FOREACH_FUNCTION,
6 `static inline int
7 compare_fcn (const atype_name *a, const atype_name *b, gfc_charlen_type n)
9   if (sizeof ('atype_name`) == 1)
10     return memcmp (a, b, n);
11   else
12     return memcmp_char4 (a, b, n);
16 extern void name`'rtype_qual`_'atype_code (rtype * const restrict retarray, 
17         atype * const restrict array, gfc_charlen_type len);
18 export_proto(name`'rtype_qual`_'atype_code);
20 void
21 name`'rtype_qual`_'atype_code (rtype * const restrict retarray, 
22         atype * const restrict array, gfc_charlen_type len)
24   index_type count[GFC_MAX_DIMENSIONS];
25   index_type extent[GFC_MAX_DIMENSIONS];
26   index_type sstride[GFC_MAX_DIMENSIONS];
27   index_type dstride;
28   const atype_name *base;
29   rtype_name * restrict dest;
30   index_type rank;
31   index_type n;
33   rank = GFC_DESCRIPTOR_RANK (array);
34   if (rank <= 0)
35     runtime_error ("Rank of array needs to be > 0");
37   if (retarray->base_addr == NULL)
38     {
39       GFC_DIMENSION_SET(retarray->dim[0], 0, rank-1, 1);
40       retarray->dtype = (retarray->dtype & ~GFC_DTYPE_RANK_MASK) | 1;
41       retarray->offset = 0;
42       retarray->base_addr = xmallocarray (rank, sizeof (rtype_name));
43     }
44   else
45     {
46       if (unlikely (compile_options.bounds_check))
47         bounds_iforeach_return ((array_t *) retarray, (array_t *) array,
48                                 "u_name");
49     }
51   dstride = GFC_DESCRIPTOR_STRIDE(retarray,0);
52   dest = retarray->base_addr;
53   for (n = 0; n < rank; n++)
54     {
55       sstride[n] = GFC_DESCRIPTOR_STRIDE(array,n) * len;
56       extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
57       count[n] = 0;
58       if (extent[n] <= 0)
59         {
60           /* Set the return value.  */
61           for (n = 0; n < rank; n++)
62             dest[n * dstride] = 0;
63           return;
64         }
65     }
67   base = array->base_addr;
69   /* Initialize the return value.  */
70   for (n = 0; n < rank; n++)
71     dest[n * dstride] = 1;
72   {
73 ')dnl
74 define(START_FOREACH_BLOCK,
75 `  while (base)
76     {
77       do
78         {
79           /* Implementation start.  */
80 ')dnl
81 define(FINISH_FOREACH_FUNCTION,
82 `         /* Implementation end.  */
83           /* Advance to the next element.  */
84           base += sstride[0];
85         }
86       while (++count[0] != extent[0]);
87       n = 0;
88       do
89         {
90           /* When we get to the end of a dimension, reset it and increment
91              the next dimension.  */
92           count[n] = 0;
93           /* We could precalculate these products, but this is a less
94              frequently used path so probably not worth it.  */
95           base -= sstride[n] * extent[n];
96           n++;
97           if (n >= rank)
98             {
99               /* Break out of the loop.  */
100               base = NULL;
101               break;
102             }
103           else
104             {
105               count[n]++;
106               base += sstride[n];
107             }
108         }
109       while (count[n] == extent[n]);
110     }
111   }
112 }')dnl
113 define(START_MASKED_FOREACH_FUNCTION,
115 extern void `m'name`'rtype_qual`_'atype_code (rtype * const restrict, 
116         atype * const restrict, gfc_array_l1 * const restrict, gfc_charlen_type len);
117 export_proto(`m'name`'rtype_qual`_'atype_code);
119 void
120 `m'name`'rtype_qual`_'atype_code (rtype * const restrict retarray, 
121         atype * const restrict array,
122         gfc_array_l1 * const restrict mask, gfc_charlen_type len)
124   index_type count[GFC_MAX_DIMENSIONS];
125   index_type extent[GFC_MAX_DIMENSIONS];
126   index_type sstride[GFC_MAX_DIMENSIONS];
127   index_type mstride[GFC_MAX_DIMENSIONS];
128   index_type dstride;
129   rtype_name *dest;
130   const atype_name *base;
131   GFC_LOGICAL_1 *mbase;
132   int rank;
133   index_type n;
134   int mask_kind;
136   rank = GFC_DESCRIPTOR_RANK (array);
137   if (rank <= 0)
138     runtime_error ("Rank of array needs to be > 0");
140   if (retarray->base_addr == NULL)
141     {
142       GFC_DIMENSION_SET(retarray->dim[0], 0, rank - 1, 1);
143       retarray->dtype = (retarray->dtype & ~GFC_DTYPE_RANK_MASK) | 1;
144       retarray->offset = 0;
145       retarray->base_addr = xmallocarray (rank, sizeof (rtype_name));
146     }
147   else
148     {
149       if (unlikely (compile_options.bounds_check))
150         {
152           bounds_iforeach_return ((array_t *) retarray, (array_t *) array,
153                                   "u_name");
154           bounds_equal_extents ((array_t *) mask, (array_t *) array,
155                                   "MASK argument", "u_name");
156         }
157     }
159   mask_kind = GFC_DESCRIPTOR_SIZE (mask);
161   mbase = mask->base_addr;
163   if (mask_kind == 1 || mask_kind == 2 || mask_kind == 4 || mask_kind == 8
164 #ifdef HAVE_GFC_LOGICAL_16
165       || mask_kind == 16
166 #endif
167       )
168     mbase = GFOR_POINTER_TO_L1 (mbase, mask_kind);
169   else
170     runtime_error ("Funny sized logical array");
172   dstride = GFC_DESCRIPTOR_STRIDE(retarray,0);
173   dest = retarray->base_addr;
174   for (n = 0; n < rank; n++)
175     {
176       sstride[n] = GFC_DESCRIPTOR_STRIDE(array,n) * len;
177       mstride[n] = GFC_DESCRIPTOR_STRIDE_BYTES(mask,n);
178       extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
179       count[n] = 0;
180       if (extent[n] <= 0)
181         {
182           /* Set the return value.  */
183           for (n = 0; n < rank; n++)
184             dest[n * dstride] = 0;
185           return;
186         }
187     }
189   base = array->base_addr;
191   /* Initialize the return value.  */
192   for (n = 0; n < rank; n++)
193     dest[n * dstride] = 0;
194   {
195 ')dnl
196 define(START_MASKED_FOREACH_BLOCK, `START_FOREACH_BLOCK')dnl
197 define(FINISH_MASKED_FOREACH_FUNCTION,
198 `         /* Implementation end.  */
199           /* Advance to the next element.  */
200           base += sstride[0];
201           mbase += mstride[0];
202         }
203       while (++count[0] != extent[0]);
204       n = 0;
205       do
206         {
207           /* When we get to the end of a dimension, reset it and increment
208              the next dimension.  */
209           count[n] = 0;
210           /* We could precalculate these products, but this is a less
211              frequently used path so probably not worth it.  */
212           base -= sstride[n] * extent[n];
213           mbase -= mstride[n] * extent[n];
214           n++;
215           if (n >= rank)
216             {
217               /* Break out of the loop.  */
218               base = NULL;
219               break;
220             }
221           else
222             {
223               count[n]++;
224               base += sstride[n];
225               mbase += mstride[n];
226             }
227         }
228       while (count[n] == extent[n]);
229     }
230   }
231 }')dnl
232 define(FOREACH_FUNCTION,
233 `START_FOREACH_FUNCTION
235 START_FOREACH_BLOCK
237 FINISH_FOREACH_FUNCTION')dnl
238 define(MASKED_FOREACH_FUNCTION,
239 `START_MASKED_FOREACH_FUNCTION
241 START_MASKED_FOREACH_BLOCK
243 FINISH_MASKED_FOREACH_FUNCTION')dnl
244 define(SCALAR_FOREACH_FUNCTION,
246 extern void `s'name`'rtype_qual`_'atype_code (rtype * const restrict, 
247         atype * const restrict, GFC_LOGICAL_4 *, gfc_charlen_type len);
248 export_proto(`s'name`'rtype_qual`_'atype_code);
250 void
251 `s'name`'rtype_qual`_'atype_code (rtype * const restrict retarray, 
252         atype * const restrict array,
253         GFC_LOGICAL_4 * mask, gfc_charlen_type len)
255   index_type rank;
256   index_type dstride;
257   index_type n;
258   rtype_name *dest;
260   if (*mask)
261     {
262       name`'rtype_qual`_'atype_code (retarray, array, len);
263       return;
264     }
266   rank = GFC_DESCRIPTOR_RANK (array);
268   if (rank <= 0)
269     runtime_error ("Rank of array needs to be > 0");
271   if (retarray->base_addr == NULL)
272     {
273       GFC_DIMENSION_SET(retarray->dim[0], 0, rank-1, 1);
274       retarray->dtype = (retarray->dtype & ~GFC_DTYPE_RANK_MASK) | 1;
275       retarray->offset = 0;
276       retarray->base_addr = xmallocarray (rank, sizeof (rtype_name));
277     }
278   else if (unlikely (compile_options.bounds_check))
279     {
280        bounds_iforeach_return ((array_t *) retarray, (array_t *) array,
281                                "u_name");
282     }
284   dstride = GFC_DESCRIPTOR_STRIDE(retarray,0);
285   dest = retarray->base_addr;
286   for (n = 0; n<rank; n++)
287     dest[n * dstride] = $1 ;
288 }')dnl