Disable tests for strdup/strndup on __hpux__
[official-gcc.git] / libgfortran / m4 / ifunction.m4
blob8e32d49218b7577d5e69d6d430c5267b846d9eba
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,
22 extern void name`'rtype_qual`_'atype_code (rtype * const restrict, 
23         atype` * const restrict, const 'index_type` * const restrict'back_arg`);
24 export_proto('name`'rtype_qual`_'atype_code);
26 void
27 name`'rtype_qual`_'atype_code` ('rtype` * const restrict retarray, 
28         'atype` * const restrict array, 
29         const index_type * const restrict pdim'back_arg`)
31   index_type count[GFC_MAX_DIMENSIONS];
32   index_type extent[GFC_MAX_DIMENSIONS];
33   index_type sstride[GFC_MAX_DIMENSIONS];
34   index_type dstride[GFC_MAX_DIMENSIONS];
35   const 'atype_name * restrict base;
36   rtype_name * restrict dest;
37   index_type rank;
38   index_type n;
39   index_type len;
40   index_type delta;
41   index_type dim;
42   int continue_loop;
44   /* Make dim zero based to avoid confusion.  */
45   rank = GFC_DESCRIPTOR_RANK (array) - 1;
46   dim = (*pdim) - 1;
48   if (unlikely (dim < 0 || dim > rank))
49     {
50       runtime_error ("Dim argument incorrect in u_name intrinsic: "
51                      "is %ld, should be between 1 and %ld",
52                      (long int) dim + 1, (long int) rank + 1);
53     }
55   len = GFC_DESCRIPTOR_EXTENT(array,dim);
56   if (len < 0)
57     len = 0;
58   delta = GFC_DESCRIPTOR_STRIDE(array,dim);
60   for (n = 0; n < dim; n++)
61     {
62       sstride[n] = GFC_DESCRIPTOR_STRIDE(array,n);
63       extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
65       if (extent[n] < 0)
66         extent[n] = 0;
67     }
68   for (n = dim; n < rank; n++)
69     {
70       sstride[n] = GFC_DESCRIPTOR_STRIDE(array, n + 1);
71       extent[n] = GFC_DESCRIPTOR_EXTENT(array, n + 1);
73       if (extent[n] < 0)
74         extent[n] = 0;
75     }
77   if (retarray->base_addr == NULL)
78     {
79       size_t alloc_size, str;
81       for (n = 0; n < rank; n++)
82         {
83           if (n == 0)
84             str = 1;
85           else
86             str = GFC_DESCRIPTOR_STRIDE(retarray,n-1) * extent[n-1];
88           GFC_DIMENSION_SET(retarray->dim[n], 0, extent[n] - 1, str);
90         }
92       retarray->offset = 0;
93       retarray->dtype.rank = rank;
95       alloc_size = GFC_DESCRIPTOR_STRIDE(retarray,rank-1) * extent[rank-1];
97       retarray->base_addr = xmallocarray (alloc_size, sizeof (rtype_name));
98       if (alloc_size == 0)
99         return;
100     }
101   else
102     {
103       if (rank != GFC_DESCRIPTOR_RANK (retarray))
104         runtime_error ("rank of return array incorrect in"
105                        " u_name intrinsic: is %ld, should be %ld",
106                        (long int) (GFC_DESCRIPTOR_RANK (retarray)),
107                        (long int) rank);
109       if (unlikely (compile_options.bounds_check))
110         bounds_ifunction_return ((array_t *) retarray, extent,
111                                  "return value", "u_name");
112     }
114   for (n = 0; n < rank; n++)
115     {
116       count[n] = 0;
117       dstride[n] = GFC_DESCRIPTOR_STRIDE(retarray,n);
118       if (extent[n] <= 0)
119         return;
120     }
122   base = array->base_addr;
123   dest = retarray->base_addr;
125   continue_loop = 1;
126   while (continue_loop)
127     {
128       const atype_name * restrict src;
129       rtype_name result;
130       src = base;
131       {
132 ')dnl
133 define(START_ARRAY_BLOCK,
134 `       if (len <= 0)
135           *dest = '$1`;
136         else
137           {
138 #if ! defined HAVE_BACK_ARG
139             for (n = 0; n < len; n++, src += delta)
140               {
141 #endif
142 ')dnl
143 define(FINISH_ARRAY_FUNCTION,
144 `             }
145             '$1`
146             *dest = result;
147           }
148       }
149       /* Advance to the next element.  */
150       count[0]++;
151       base += sstride[0];
152       dest += dstride[0];
153       n = 0;
154       while (count[n] == extent[n])
155         {
156           /* When we get to the end of a dimension, reset it and increment
157              the next dimension.  */
158           count[n] = 0;
159           /* We could precalculate these products, but this is a less
160              frequently used path so probably not worth it.  */
161           base -= sstride[n] * extent[n];
162           dest -= dstride[n] * extent[n];
163           n++;
164           if (n >= rank)
165             {
166               /* Break out of the loop.  */
167               continue_loop = 0;
168               break;
169             }
170           else
171             {
172               count[n]++;
173               base += sstride[n];
174               dest += dstride[n];
175             }
176         }
177     }
178 }')dnl
179 define(START_MASKED_ARRAY_FUNCTION,
181 extern void `m'name`'rtype_qual`_'atype_code` ('rtype` * const restrict, 
182         'atype` * const restrict, const 'index_type` * const restrict,
183         gfc_array_l1 * const restrict'back_arg`);
184 export_proto(m'name`'rtype_qual`_'atype_code`);
186 void
187 m'name`'rtype_qual`_'atype_code` ('rtype` * const restrict retarray, 
188         'atype` * const restrict array, 
189         const index_type * const restrict pdim, 
190         gfc_array_l1 * const restrict mask'back_arg`)
192   index_type count[GFC_MAX_DIMENSIONS];
193   index_type extent[GFC_MAX_DIMENSIONS];
194   index_type sstride[GFC_MAX_DIMENSIONS];
195   index_type dstride[GFC_MAX_DIMENSIONS];
196   index_type mstride[GFC_MAX_DIMENSIONS];
197   'rtype_name * restrict dest;
198   const atype_name * restrict base;
199   const GFC_LOGICAL_1 * restrict mbase;
200   index_type rank;
201   index_type dim;
202   index_type n;
203   index_type len;
204   index_type delta;
205   index_type mdelta;
206   int mask_kind;
208   if (mask == NULL)
209     {
210 #ifdef HAVE_BACK_ARG
211       name`'rtype_qual`_'atype_code (retarray, array, pdim, back);
212 #else
213       name`'rtype_qual`_'atype_code (retarray, array, pdim);
214 #endif
215       return;
216     }
218   dim = (*pdim) - 1;
219   rank = GFC_DESCRIPTOR_RANK (array) - 1;
222   if (unlikely (dim < 0 || dim > rank))
223     {
224       runtime_error ("Dim argument incorrect in u_name intrinsic: "
225                      "is %ld, should be between 1 and %ld",
226                      (long int) dim + 1, (long int) rank + 1);
227     }
229   len = GFC_DESCRIPTOR_EXTENT(array,dim);
230   if (len < 0)
231     len = 0;
233   mbase = mask->base_addr;
235   mask_kind = GFC_DESCRIPTOR_SIZE (mask);
237   if (mask_kind == 1 || mask_kind == 2 || mask_kind == 4 || mask_kind == 8
238 #ifdef HAVE_GFC_LOGICAL_16
239       || mask_kind == 16
240 #endif
241       )
242     mbase = GFOR_POINTER_TO_L1 (mbase, mask_kind);
243   else
244     runtime_error ("Funny sized logical array");
246   delta = GFC_DESCRIPTOR_STRIDE(array,dim);
247   mdelta = GFC_DESCRIPTOR_STRIDE_BYTES(mask,dim);
249   for (n = 0; n < dim; n++)
250     {
251       sstride[n] = GFC_DESCRIPTOR_STRIDE(array,n);
252       mstride[n] = GFC_DESCRIPTOR_STRIDE_BYTES(mask,n);
253       extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
255       if (extent[n] < 0)
256         extent[n] = 0;
258     }
259   for (n = dim; n < rank; n++)
260     {
261       sstride[n] = GFC_DESCRIPTOR_STRIDE(array,n + 1);
262       mstride[n] = GFC_DESCRIPTOR_STRIDE_BYTES(mask, n + 1);
263       extent[n] = GFC_DESCRIPTOR_EXTENT(array, n + 1);
265       if (extent[n] < 0)
266         extent[n] = 0;
267     }
269   if (retarray->base_addr == NULL)
270     {
271       size_t alloc_size, str;
273       for (n = 0; n < rank; n++)
274         {
275           if (n == 0)
276             str = 1;
277           else
278             str= GFC_DESCRIPTOR_STRIDE(retarray,n-1) * extent[n-1];
280           GFC_DIMENSION_SET(retarray->dim[n], 0, extent[n] - 1, str);
282         }
284       alloc_size = GFC_DESCRIPTOR_STRIDE(retarray,rank-1) * extent[rank-1];
286       retarray->offset = 0;
287       retarray->dtype.rank = rank;
289       retarray->base_addr = xmallocarray (alloc_size, sizeof (rtype_name));
290       if (alloc_size == 0)
291         return;
292     }
293   else
294     {
295       if (rank != GFC_DESCRIPTOR_RANK (retarray))
296         runtime_error ("rank of return array incorrect in u_name intrinsic");
298       if (unlikely (compile_options.bounds_check))
299         {
300           bounds_ifunction_return ((array_t *) retarray, extent,
301                                    "return value", "u_name");
302           bounds_equal_extents ((array_t *) mask, (array_t *) array,
303                                 "MASK argument", "u_name");
304         }
305     }
307   for (n = 0; n < rank; n++)
308     {
309       count[n] = 0;
310       dstride[n] = GFC_DESCRIPTOR_STRIDE(retarray,n);
311       if (extent[n] <= 0)
312         return;
313     }
315   dest = retarray->base_addr;
316   base = array->base_addr;
318   while (base)
319     {
320       const atype_name * restrict src;
321       const GFC_LOGICAL_1 * restrict msrc;
322       rtype_name result;
323       src = base;
324       msrc = mbase;
325       {
326 ')dnl
327 define(START_MASKED_ARRAY_BLOCK,
328 `       for (n = 0; n < len; n++, src += delta, msrc += mdelta)
329           {
330 ')dnl
331 define(FINISH_MASKED_ARRAY_FUNCTION,
332 `         }
333         *dest = result;
334       }
335       /* Advance to the next element.  */
336       count[0]++;
337       base += sstride[0];
338       mbase += mstride[0];
339       dest += dstride[0];
340       n = 0;
341       while (count[n] == extent[n])
342         {
343           /* When we get to the end of a dimension, reset it and increment
344              the next dimension.  */
345           count[n] = 0;
346           /* We could precalculate these products, but this is a less
347              frequently used path so probably not worth it.  */
348           base -= sstride[n] * extent[n];
349           mbase -= mstride[n] * extent[n];
350           dest -= dstride[n] * extent[n];
351           n++;
352           if (n >= rank)
353             {
354               /* Break out of the loop.  */
355               base = NULL;
356               break;
357             }
358           else
359             {
360               count[n]++;
361               base += sstride[n];
362               mbase += mstride[n];
363               dest += dstride[n];
364             }
365         }
366     }
367 }')dnl
368 define(SCALAR_ARRAY_FUNCTION,
370 extern void `s'name`'rtype_qual`_'atype_code` ('rtype` * const restrict, 
371         'atype` * const restrict, const index_type * const restrict,
372         GFC_LOGICAL_4 *'back_arg`);
373 export_proto(s'name`'rtype_qual`_'atype_code);
375 void
376 `s'name`'rtype_qual`_'atype_code` ('rtype` * const restrict retarray, 
377         'atype` * const restrict array, 
378         const index_type * const restrict pdim, 
379         GFC_LOGICAL_4 * mask'back_arg`)
381   index_type count[GFC_MAX_DIMENSIONS];
382   index_type extent[GFC_MAX_DIMENSIONS];
383   index_type dstride[GFC_MAX_DIMENSIONS];
384   'rtype_name * restrict dest;
385   index_type rank;
386   index_type n;
387   index_type dim;
390   if (mask == NULL || *mask)
391     {
392 #ifdef HAVE_BACK_ARG
393       name`'rtype_qual`_'atype_code (retarray, array, pdim, back);
394 #else
395       name`'rtype_qual`_'atype_code (retarray, array, pdim);
396 #endif
397       return;
398     }
399   /* Make dim zero based to avoid confusion.  */
400   dim = (*pdim) - 1;
401   rank = GFC_DESCRIPTOR_RANK (array) - 1;
403   if (unlikely (dim < 0 || dim > rank))
404     {
405       runtime_error ("Dim argument incorrect in u_name intrinsic: "
406                      "is %ld, should be between 1 and %ld",
407                      (long int) dim + 1, (long int) rank + 1);
408     }
410   for (n = 0; n < dim; n++)
411     {
412       extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
414       if (extent[n] <= 0)
415         extent[n] = 0;
416     }
418   for (n = dim; n < rank; n++)
419     {
420       extent[n] =
421         GFC_DESCRIPTOR_EXTENT(array,n + 1);
423       if (extent[n] <= 0)
424         extent[n] = 0;
425     }
427   if (retarray->base_addr == NULL)
428     {
429       size_t alloc_size, str;
431       for (n = 0; n < rank; n++)
432         {
433           if (n == 0)
434             str = 1;
435           else
436             str = GFC_DESCRIPTOR_STRIDE(retarray,n-1) * extent[n-1];
438           GFC_DIMENSION_SET(retarray->dim[n], 0, extent[n] - 1, str);
440         }
442       retarray->offset = 0;
443       retarray->dtype.rank = rank;
445       alloc_size = GFC_DESCRIPTOR_STRIDE(retarray,rank-1) * extent[rank-1];
447       retarray->base_addr = xmallocarray (alloc_size, sizeof (rtype_name));
448       if (alloc_size == 0)
449         return;
450     }
451   else
452     {
453       if (rank != GFC_DESCRIPTOR_RANK (retarray))
454         runtime_error ("rank of return array incorrect in"
455                        " u_name intrinsic: is %ld, should be %ld",
456                        (long int) (GFC_DESCRIPTOR_RANK (retarray)),
457                        (long int) rank);
459       if (unlikely (compile_options.bounds_check))
460         {
461           for (n=0; n < rank; n++)
462             {
463               index_type ret_extent;
465               ret_extent = GFC_DESCRIPTOR_EXTENT(retarray,n);
466               if (extent[n] != ret_extent)
467                 runtime_error ("Incorrect extent in return value of"
468                                " u_name intrinsic in dimension %ld:"
469                                " is %ld, should be %ld", (long int) n + 1,
470                                (long int) ret_extent, (long int) extent[n]);
471             }
472         }
473     }
475   for (n = 0; n < rank; n++)
476     {
477       count[n] = 0;
478       dstride[n] = GFC_DESCRIPTOR_STRIDE(retarray,n);
479     }
481   dest = retarray->base_addr;
483   while(1)
484     {
485       *dest = '$1`;
486       count[0]++;
487       dest += dstride[0];
488       n = 0;
489       while (count[n] == extent[n])
490         {
491           /* When we get to the end of a dimension, reset it and increment
492              the next dimension.  */
493           count[n] = 0;
494           /* We could precalculate these products, but this is a less
495              frequently used path so probably not worth it.  */
496           dest -= dstride[n] * extent[n];
497           n++;
498           if (n >= rank)
499             return;
500           else
501             {
502               count[n]++;
503               dest += dstride[n];
504             }
505         }
506     }
507 }')dnl
508 define(ARRAY_FUNCTION,
509 `START_ARRAY_FUNCTION
511 START_ARRAY_BLOCK($1)
513 FINISH_ARRAY_FUNCTION($4)')dnl
514 define(MASKED_ARRAY_FUNCTION,
515 `START_MASKED_ARRAY_FUNCTION
517 START_MASKED_ARRAY_BLOCK
519 FINISH_MASKED_ARRAY_FUNCTION')dnl