testsuite: arm: Use effective-target for pr68620 and pr78041 tests
[official-gcc.git] / libgfortran / m4 / iforeach-s.m4
blobb841d1519c5b9a99849f6958d7430c05ce0de9c4
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'back_arg`, 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'back_arg`, 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.rank = 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 'back_arg`,
117         gfc_charlen_type len);
118 export_proto(m'name`'rtype_qual`_'atype_code`);
120 void
121 m'name`'rtype_qual`_'atype_code` ('rtype` * const restrict retarray, 
122         'atype` * const restrict array,
123         gfc_array_l1 * const restrict mask'back_arg`,
124         gfc_charlen_type len)
126   index_type count[GFC_MAX_DIMENSIONS];
127   index_type extent[GFC_MAX_DIMENSIONS];
128   index_type sstride[GFC_MAX_DIMENSIONS];
129   index_type mstride[GFC_MAX_DIMENSIONS];
130   index_type dstride;
131   'rtype_name *dest;
132   const atype_name *base;
133   GFC_LOGICAL_1 *mbase;
134   int rank;
135   index_type n;
136   int mask_kind;
138   if (mask == NULL)
139     {
140 #ifdef HAVE_BACK_ARG    
141       name`'rtype_qual`_'atype_code (retarray, array, back, len);
142 #else
143       name`'rtype_qual`_'atype_code (retarray, array, len);
144 #endif
145       return;
146     }
148   rank = GFC_DESCRIPTOR_RANK (array);
149   if (rank <= 0)
150     runtime_error ("Rank of array needs to be > 0");
152   if (retarray->base_addr == NULL)
153     {
154       GFC_DIMENSION_SET(retarray->dim[0], 0, rank - 1, 1);
155       retarray->dtype.rank = 1;
156       retarray->offset = 0;
157       retarray->base_addr = xmallocarray (rank, sizeof (rtype_name));
158     }
159   else
160     {
161       if (unlikely (compile_options.bounds_check))
162         {
164           bounds_iforeach_return ((array_t *) retarray, (array_t *) array,
165                                   "u_name");
166           bounds_equal_extents ((array_t *) mask, (array_t *) array,
167                                   "MASK argument", "u_name");
168         }
169     }
171   mask_kind = GFC_DESCRIPTOR_SIZE (mask);
173   mbase = mask->base_addr;
175   if (mask_kind == 1 || mask_kind == 2 || mask_kind == 4 || mask_kind == 8
176 #ifdef HAVE_GFC_LOGICAL_16
177       || mask_kind == 16
178 #endif
179       )
180     mbase = GFOR_POINTER_TO_L1 (mbase, mask_kind);
181   else
182     runtime_error ("Funny sized logical array");
184   dstride = GFC_DESCRIPTOR_STRIDE(retarray,0);
185   dest = retarray->base_addr;
186   for (n = 0; n < rank; n++)
187     {
188       sstride[n] = GFC_DESCRIPTOR_STRIDE(array,n) * len;
189       mstride[n] = GFC_DESCRIPTOR_STRIDE_BYTES(mask,n);
190       extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
191       count[n] = 0;
192       if (extent[n] <= 0)
193         {
194           /* Set the return value.  */
195           for (n = 0; n < rank; n++)
196             dest[n * dstride] = 0;
197           return;
198         }
199     }
201   base = array->base_addr;
203   /* Initialize the return value.  */
204   for (n = 0; n < rank; n++)
205     dest[n * dstride] = 0;
206   {
207 ')dnl
208 define(START_MASKED_FOREACH_BLOCK, `START_FOREACH_BLOCK')dnl
209 define(FINISH_MASKED_FOREACH_FUNCTION,
210 `         /* Implementation end.  */
211           /* Advance to the next element.  */
212           base += sstride[0];
213           mbase += mstride[0];
214         }
215       while (++count[0] != extent[0]);
216       n = 0;
217       do
218         {
219           /* When we get to the end of a dimension, reset it and increment
220              the next dimension.  */
221           count[n] = 0;
222           /* We could precalculate these products, but this is a less
223              frequently used path so probably not worth it.  */
224           base -= sstride[n] * extent[n];
225           mbase -= mstride[n] * extent[n];
226           n++;
227           if (n >= rank)
228             {
229               /* Break out of the loop.  */
230               base = NULL;
231               break;
232             }
233           else
234             {
235               count[n]++;
236               base += sstride[n];
237               mbase += mstride[n];
238             }
239         }
240       while (count[n] == extent[n]);
241     }
242   }
243 }')dnl
244 define(FOREACH_FUNCTION,
245 `START_FOREACH_FUNCTION
247 START_FOREACH_BLOCK
249 FINISH_FOREACH_FUNCTION')dnl
250 define(MASKED_FOREACH_FUNCTION,
251 `START_MASKED_FOREACH_FUNCTION
253 START_MASKED_FOREACH_BLOCK
255 FINISH_MASKED_FOREACH_FUNCTION')dnl
256 define(SCALAR_FOREACH_FUNCTION,
258 extern void `s'name`'rtype_qual`_'atype_code` ('rtype` * const restrict, 
259         'atype` * const restrict, GFC_LOGICAL_4 *'back_arg`,
260         gfc_charlen_type len);
261 export_proto(s'name`'rtype_qual`_'atype_code);
263 void
264 `s'name`'rtype_qual`_'atype_code` ('rtype` * const restrict retarray, 
265         'atype` * const restrict array,
266         GFC_LOGICAL_4 * mask'back_arg`,
267         gfc_charlen_type len)
269   index_type rank;
270   index_type dstride;
271   index_type n;
272   'rtype_name *dest;
274   if (mask == NULL || *mask)
275     {
276 #ifdef HAVE_BACK_ARG    
277       name`'rtype_qual`_'atype_code (retarray, array, back, len);
278 #else
279       name`'rtype_qual`_'atype_code (retarray, array, len);
280 #endif
281       return;
282     }
284   rank = GFC_DESCRIPTOR_RANK (array);
286   if (rank <= 0)
287     runtime_error ("Rank of array needs to be > 0");
289   if (retarray->base_addr == NULL)
290     {
291       GFC_DIMENSION_SET(retarray->dim[0], 0, rank-1, 1);
292       retarray->dtype.rank = 1;
293       retarray->offset = 0;
294       retarray->base_addr = xmallocarray (rank, sizeof (rtype_name));
295     }
296   else if (unlikely (compile_options.bounds_check))
297     {
298        bounds_iforeach_return ((array_t *) retarray, (array_t *) array,
299                                "u_name");
300     }
302   dstride = GFC_DESCRIPTOR_STRIDE(retarray,0);
303   dest = retarray->base_addr;
304   for (n = 0; n<rank; n++)
305     dest[n * dstride] = $1 ;
306 }')dnl