hppa: Implement TARGET_ATOMIC_ASSIGN_EXPAND_FENV
[official-gcc.git] / libgfortran / m4 / ifunction-s2.m4
blob4189dd9e2d8f4000c3b529f97376f0674f3f8dc0
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 dnl
6 dnl Pass the implementation for a single section as the parameter to
7 dnl {MASK_}ARRAY_FUNCTION.
8 dnl The variables base, delta, and len describe the input section.
9 dnl For masked section the mask is described by mbase and mdelta.
10 dnl These should not be modified. The result should be stored in *dest.
11 dnl The names count, extent, sstride, dstride, base, dest, rank, dim
12 dnl retarray, array, pdim and mstride should not be used.
13 dnl The variable n is declared as index_type and may be used.
14 dnl Other variable declarations may be placed at the start of the code,
15 dnl The types of the array parameter and the return value are
16 dnl atype_name and rtype_name respectively.
17 dnl Execution should be allowed to continue to the end of the block.
18 dnl You should not return or break from the inner loop of the implementation.
19 dnl Care should also be taken to avoid using the names defined in iparm.m4
20 define(START_ARRAY_FUNCTION,
21 `#include <string.h>
22 #include <assert.h>
24 static inline int
25 compare_fcn (const atype_name *a, const atype_name *b, gfc_charlen_type n)
27   if (sizeof ('atype_name`) == 1)
28     return memcmp (a, b, n);
29   else
30     return memcmp_char4 (a, b, n);
33 extern void name`'rtype_qual`_'atype_code (rtype * const restrict,
34         gfc_charlen_type, atype * const restrict,
35         const index_type * const restrict, gfc_charlen_type);
36 export_proto(name`'rtype_qual`_'atype_code);
38 void
39 name`'rtype_qual`_'atype_code (rtype * const restrict retarray, 
40         gfc_charlen_type xlen, atype * const restrict array, 
41         const index_type * const restrict pdim, gfc_charlen_type string_len)
43   index_type count[GFC_MAX_DIMENSIONS];
44   index_type extent[GFC_MAX_DIMENSIONS];
45   index_type sstride[GFC_MAX_DIMENSIONS];
46   index_type dstride[GFC_MAX_DIMENSIONS];
47   const atype_name * restrict base;
48   rtype_name * restrict dest;
49   index_type rank;
50   index_type n;
51   index_type len;
52   index_type delta;
53   index_type dim;
54   int continue_loop;
56   assert (xlen == string_len);
57   /* Make dim zero based to avoid confusion.  */
58   rank = GFC_DESCRIPTOR_RANK (array) - 1;
59   dim = (*pdim) - 1;
61   if (unlikely (dim < 0 || dim > rank))
62     {
63       runtime_error ("Dim argument incorrect in u_name intrinsic: "
64                      "is %ld, should be between 1 and %ld",
65                      (long int) dim + 1, (long int) rank + 1);
66     }
68   len = GFC_DESCRIPTOR_EXTENT(array,dim);
69   if (len < 0)
70     len = 0;
72   delta = GFC_DESCRIPTOR_STRIDE(array,dim) * string_len;
74   for (n = 0; n < dim; n++)
75     {
76       sstride[n] = GFC_DESCRIPTOR_STRIDE(array,n) * string_len;
77       extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
79       if (extent[n] < 0)
80         extent[n] = 0;
81     }
82   for (n = dim; n < rank; n++)
83     {
84       sstride[n] = GFC_DESCRIPTOR_STRIDE(array, n + 1) * string_len;
85       extent[n] = GFC_DESCRIPTOR_EXTENT(array, n + 1);
87       if (extent[n] < 0)
88         extent[n] = 0;
89     }
91   if (retarray->base_addr == NULL)
92     {
93       size_t alloc_size, str;
95       for (n = 0; n < rank; n++)
96         {
97           if (n == 0)
98             str = 1;
99           else
100             str = GFC_DESCRIPTOR_STRIDE(retarray,n-1) * extent[n-1];
102           GFC_DIMENSION_SET(retarray->dim[n], 0, extent[n] - 1, str);
104         }
106       retarray->offset = 0;
107       retarray->dtype.rank = rank;
109       alloc_size = GFC_DESCRIPTOR_STRIDE(retarray,rank-1) * extent[rank-1]
110                  * string_len;
112       retarray->base_addr = xmallocarray (alloc_size, sizeof (rtype_name));
113       if (alloc_size == 0)
114         return;
115     }
116   else
117     {
118       if (rank != GFC_DESCRIPTOR_RANK (retarray))
119         runtime_error ("rank of return array incorrect in"
120                        " u_name intrinsic: is %ld, should be %ld",
121                        (long int) (GFC_DESCRIPTOR_RANK (retarray)),
122                        (long int) rank);
124       if (unlikely (compile_options.bounds_check))
125         bounds_ifunction_return ((array_t *) retarray, extent,
126                                  "return value", "u_name");
127     }
129   for (n = 0; n < rank; n++)
130     {
131       count[n] = 0;
132       dstride[n] = GFC_DESCRIPTOR_STRIDE(retarray,n) * string_len;
133       if (extent[n] <= 0)
134         return;
135     }
137   base = array->base_addr;
138   dest = retarray->base_addr;
140   continue_loop = 1;
141   while (continue_loop)
142     {
143       const atype_name * restrict src;
144       src = base;
145       {
146 ')dnl
147 define(START_ARRAY_BLOCK,
148 `       if (len <= 0)
149           memset (dest, '$1`, sizeof (*dest) * string_len);
150         else
151           {
152             for (n = 0; n < len; n++, src += delta)
153               {
154 ')dnl
155 define(FINISH_ARRAY_FUNCTION,
156 `             }
157             '$1`
158             memcpy (dest, retval, sizeof (*dest) * string_len);
159           }
160       }
161       /* Advance to the next element.  */
162       count[0]++;
163       base += sstride[0];
164       dest += dstride[0];
165       n = 0;
166       while (count[n] == extent[n])
167         {
168           /* When we get to the end of a dimension, reset it and increment
169              the next dimension.  */
170           count[n] = 0;
171           /* We could precalculate these products, but this is a less
172              frequently used path so probably not worth it.  */
173           base -= sstride[n] * extent[n];
174           dest -= dstride[n] * extent[n];
175           n++;
176           if (n >= rank)
177             {
178               /* Break out of the loop.  */
179               continue_loop = 0;
180               break;
181             }
182           else
183             {
184               count[n]++;
185               base += sstride[n];
186               dest += dstride[n];
187             }
188         }
189     }
190 }')dnl
191 define(START_MASKED_ARRAY_FUNCTION,
193 extern void `m'name`'rtype_qual`_'atype_code (rtype * const restrict,
194         gfc_charlen_type, atype * const restrict,
195         const index_type * const restrict,
196         gfc_array_l1 * const restrict, gfc_charlen_type);
197 export_proto(`m'name`'rtype_qual`_'atype_code);
199 void
200 `m'name`'rtype_qual`_'atype_code (rtype * const restrict retarray, 
201         gfc_charlen_type xlen, atype * const restrict array, 
202         const index_type * const restrict pdim,
203         gfc_array_l1 * const restrict mask,
204         gfc_charlen_type string_len)
207   index_type count[GFC_MAX_DIMENSIONS];
208   index_type extent[GFC_MAX_DIMENSIONS];
209   index_type sstride[GFC_MAX_DIMENSIONS];
210   index_type dstride[GFC_MAX_DIMENSIONS];
211   index_type mstride[GFC_MAX_DIMENSIONS];
212   rtype_name * restrict dest;
213   const atype_name * restrict base;
214   const GFC_LOGICAL_1 * restrict mbase;
215   index_type rank;
216   index_type dim;
217   index_type n;
218   index_type len;
219   index_type delta;
220   index_type mdelta;
221   int mask_kind;
223   if (mask == NULL)
224     {
225       name`'rtype_qual`_'atype_code (retarray, xlen, array, pdim, string_len);
226       return;
227     }
229   assert (xlen == string_len);
231   dim = (*pdim) - 1;
232   rank = GFC_DESCRIPTOR_RANK (array) - 1;
234   if (unlikely (dim < 0 || dim > rank))
235     {
236       runtime_error ("Dim argument incorrect in u_name intrinsic: "
237                      "is %ld, should be between 1 and %ld",
238                      (long int) dim + 1, (long int) rank + 1);
239     }
241   len = GFC_DESCRIPTOR_EXTENT(array,dim);
242   if (len < 0)
243     len = 0;
245   mbase = mask->base_addr;
247   mask_kind = GFC_DESCRIPTOR_SIZE (mask);
249   if (mask_kind == 1 || mask_kind == 2 || mask_kind == 4 || mask_kind == 8
250 #ifdef HAVE_GFC_LOGICAL_16
251       || mask_kind == 16
252 #endif
253       )
254     mbase = GFOR_POINTER_TO_L1 (mbase, mask_kind);
255   else
256     runtime_error ("Funny sized logical array");
258   delta = GFC_DESCRIPTOR_STRIDE(array,dim) * string_len;
259   mdelta = GFC_DESCRIPTOR_STRIDE_BYTES(mask,dim);
261   for (n = 0; n < dim; n++)
262     {
263       sstride[n] = GFC_DESCRIPTOR_STRIDE(array,n) * string_len;
264       mstride[n] = GFC_DESCRIPTOR_STRIDE_BYTES(mask,n);
265       extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
267       if (extent[n] < 0)
268         extent[n] = 0;
270     }
271   for (n = dim; n < rank; n++)
272     {
273       sstride[n] = GFC_DESCRIPTOR_STRIDE(array,n + 1) * string_len;
274       mstride[n] = GFC_DESCRIPTOR_STRIDE_BYTES(mask, n + 1);
275       extent[n] = GFC_DESCRIPTOR_EXTENT(array, n + 1);
277       if (extent[n] < 0)
278         extent[n] = 0;
279     }
281   if (retarray->base_addr == NULL)
282     {
283       size_t alloc_size, str;
285       for (n = 0; n < rank; n++)
286         {
287           if (n == 0)
288             str = 1;
289           else
290             str= GFC_DESCRIPTOR_STRIDE(retarray,n-1) * extent[n-1];
292           GFC_DIMENSION_SET(retarray->dim[n], 0, extent[n] - 1, str);
294         }
296       alloc_size = GFC_DESCRIPTOR_STRIDE(retarray,rank-1) * extent[rank-1]
297                  * string_len;
299       retarray->offset = 0;
300       retarray->dtype.rank = rank;
302       retarray->base_addr = xmallocarray (alloc_size, sizeof (rtype_name));
303       if (alloc_size == 0)
304         return;
305     }
306   else
307     {
308       if (rank != GFC_DESCRIPTOR_RANK (retarray))
309         runtime_error ("rank of return array incorrect in u_name intrinsic");
311       if (unlikely (compile_options.bounds_check))
312         {
313           bounds_ifunction_return ((array_t *) retarray, extent,
314                                    "return value", "u_name");
315           bounds_equal_extents ((array_t *) mask, (array_t *) array,
316                                 "MASK argument", "u_name");
317         }
318     }
320   for (n = 0; n < rank; n++)
321     {
322       count[n] = 0;
323       dstride[n] = GFC_DESCRIPTOR_STRIDE(retarray,n) * string_len;
324       if (extent[n] <= 0)
325         return;
326     }
328   dest = retarray->base_addr;
329   base = array->base_addr;
331   while (base)
332     {
333       const atype_name * restrict src;
334       const GFC_LOGICAL_1 * restrict msrc;
336       src = base;
337       msrc = mbase;
338       {
339 ')dnl
340 define(START_MASKED_ARRAY_BLOCK,
341 `       for (n = 0; n < len; n++, src += delta, msrc += mdelta)
342           {
343 ')dnl
344 define(FINISH_MASKED_ARRAY_FUNCTION,
345 `         }
346         memcpy (dest, retval, sizeof (*dest) * string_len);
347       }
348       /* Advance to the next element.  */
349       count[0]++;
350       base += sstride[0];
351       mbase += mstride[0];
352       dest += dstride[0];
353       n = 0;
354       while (count[n] == extent[n])
355         {
356           /* When we get to the end of a dimension, reset it and increment
357              the next dimension.  */
358           count[n] = 0;
359           /* We could precalculate these products, but this is a less
360              frequently used path so probably not worth it.  */
361           base -= sstride[n] * extent[n];
362           mbase -= mstride[n] * extent[n];
363           dest -= dstride[n] * extent[n];
364           n++;
365           if (n >= rank)
366             {
367               /* Break out of the loop.  */
368               base = NULL;
369               break;
370             }
371           else
372             {
373               count[n]++;
374               base += sstride[n];
375               mbase += mstride[n];
376               dest += dstride[n];
377             }
378         }
379     }
380 }')dnl
381 define(SCALAR_ARRAY_FUNCTION,
383 void `s'name`'rtype_qual`_'atype_code (rtype * const restrict,
384         gfc_charlen_type, atype * const restrict,
385         const index_type * const restrict,
386         GFC_LOGICAL_4 *, gfc_charlen_type);
388 export_proto(`s'name`'rtype_qual`_'atype_code);
390 void
391 `s'name`'rtype_qual`_'atype_code (rtype * const restrict retarray, 
392         gfc_charlen_type xlen, atype * const restrict array, 
393         const index_type * const restrict pdim,
394         GFC_LOGICAL_4 *mask, gfc_charlen_type string_len)
397   index_type count[GFC_MAX_DIMENSIONS];
398   index_type extent[GFC_MAX_DIMENSIONS];
399   index_type dstride[GFC_MAX_DIMENSIONS];
400   rtype_name * restrict dest;
401   index_type rank;
402   index_type n;
403   index_type dim;
406   if (mask == NULL || *mask)
407     {
408       name`'rtype_qual`_'atype_code (retarray, xlen, array, pdim, string_len);
409       return;
410     }
411   /* Make dim zero based to avoid confusion.  */
412   dim = (*pdim) - 1;
413   rank = GFC_DESCRIPTOR_RANK (array) - 1;
415   if (unlikely (dim < 0 || dim > rank))
416     {
417       runtime_error ("Dim argument incorrect in u_name intrinsic: "
418                      "is %ld, should be between 1 and %ld",
419                      (long int) dim + 1, (long int) rank + 1);
420     }
422   for (n = 0; n < dim; n++)
423     {
424       extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
426       if (extent[n] <= 0)
427         extent[n] = 0;
428     }
430   for (n = dim; n < rank; n++)
431     {
432       extent[n] =
433         GFC_DESCRIPTOR_EXTENT(array,n + 1);
435       if (extent[n] <= 0)
436         extent[n] = 0;
437     }
439   if (retarray->base_addr == NULL)
440     {
441       size_t alloc_size, str;
443       for (n = 0; n < rank; n++)
444         {
445           if (n == 0)
446             str = 1;
447           else
448             str = GFC_DESCRIPTOR_STRIDE(retarray,n-1) * extent[n-1];
450           GFC_DIMENSION_SET(retarray->dim[n], 0, extent[n] - 1, str);
452         }
454       retarray->offset = 0;
455       retarray->dtype.rank = rank;
457       alloc_size = GFC_DESCRIPTOR_STRIDE(retarray,rank-1) * extent[rank-1]
458                  * string_len;
460       retarray->base_addr = xmallocarray (alloc_size, sizeof (rtype_name));
461       if (alloc_size == 0)
462         return;
463     }
464   else
465     {
466       if (rank != GFC_DESCRIPTOR_RANK (retarray))
467         runtime_error ("rank of return array incorrect in"
468                        " u_name intrinsic: is %ld, should be %ld",
469                        (long int) (GFC_DESCRIPTOR_RANK (retarray)),
470                        (long int) rank);
472       if (unlikely (compile_options.bounds_check))
473         {
474           for (n=0; n < rank; n++)
475             {
476               index_type ret_extent;
478               ret_extent = GFC_DESCRIPTOR_EXTENT(retarray,n);
479               if (extent[n] != ret_extent)
480                 runtime_error ("Incorrect extent in return value of"
481                                " u_name intrinsic in dimension %ld:"
482                                " is %ld, should be %ld", (long int) n + 1,
483                                (long int) ret_extent, (long int) extent[n]);
484             }
485         }
486     }
488   for (n = 0; n < rank; n++)
489     {
490       count[n] = 0;
491       dstride[n] = GFC_DESCRIPTOR_STRIDE(retarray,n) * string_len;
492     }
494   dest = retarray->base_addr;
496   while(1)
497     {
498       memset (dest, '$1`, sizeof (*dest) * string_len);
499       count[0]++;
500       dest += dstride[0];
501       n = 0;
502       while (count[n] == extent[n])
503         {
504           /* When we get to the end of a dimension, reset it and increment
505              the next dimension.  */
506           count[n] = 0;
507           /* We could precalculate these products, but this is a less
508              frequently used path so probably not worth it.  */
509           dest -= dstride[n] * extent[n];
510           n++;
511           if (n >= rank)
512             return;
513           else
514             {
515               count[n]++;
516               dest += dstride[n];
517             }
518         }
519     }
520 }')dnl
521 define(ARRAY_FUNCTION,
522 `START_ARRAY_FUNCTION($1)
524 START_ARRAY_BLOCK($1)
526 FINISH_ARRAY_FUNCTION($4)')dnl
527 define(MASKED_ARRAY_FUNCTION,
528 `START_MASKED_ARRAY_FUNCTION
530 START_MASKED_ARRAY_BLOCK
532 FINISH_MASKED_ARRAY_FUNCTION')dnl