re PR libfortran/62188 (Array bounds overrun in bessel_yn_r4/8/16 and other functions)
[gcc.git] / libgfortran / m4 / ifunction_logical.m4
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 `
22 extern void name`'rtype_qual`_'atype_code (rtype * const restrict,
23 gfc_array_l1 * const restrict, const index_type * const restrict);
24 export_proto(name`'rtype_qual`_'atype_code);
25
26 void
27 name`'rtype_qual`_'atype_code (rtype * const restrict retarray,
28 gfc_array_l1 * const restrict array,
29 const index_type * const restrict pdim)
30 {
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 GFC_LOGICAL_1 * 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 src_kind;
43 int continue_loop;
44
45 /* Make dim zero based to avoid confusion. */
46 dim = (*pdim) - 1;
47 rank = GFC_DESCRIPTOR_RANK (array) - 1;
48
49 src_kind = GFC_DESCRIPTOR_SIZE (array);
50
51 len = GFC_DESCRIPTOR_EXTENT(array,dim);
52 if (len < 0)
53 len = 0;
54
55 delta = GFC_DESCRIPTOR_STRIDE_BYTES(array,dim);
56
57 for (n = 0; n < dim; n++)
58 {
59 sstride[n] = GFC_DESCRIPTOR_STRIDE_BYTES(array,n);
60 extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
61
62 if (extent[n] < 0)
63 extent[n] = 0;
64 }
65 for (n = dim; n < rank; n++)
66 {
67 sstride[n] = GFC_DESCRIPTOR_STRIDE_BYTES(array,n + 1);
68 extent[n] = GFC_DESCRIPTOR_EXTENT(array,n + 1);
69
70 if (extent[n] < 0)
71 extent[n] = 0;
72 }
73
74 if (retarray->base_addr == NULL)
75 {
76 size_t alloc_size, str;
77
78 for (n = 0; n < rank; n++)
79 {
80 if (n == 0)
81 str = 1;
82 else
83 str = GFC_DESCRIPTOR_STRIDE(retarray,n-1) * extent[n-1];
84
85 GFC_DIMENSION_SET(retarray->dim[n], 0, extent[n] - 1, str);
86
87 }
88
89 retarray->offset = 0;
90 retarray->dtype = (array->dtype & ~GFC_DTYPE_RANK_MASK) | rank;
91
92 alloc_size = GFC_DESCRIPTOR_STRIDE(retarray,rank-1) * extent[rank-1];
93
94 if (alloc_size == 0)
95 {
96 /* Make sure we have a zero-sized array. */
97 GFC_DIMENSION_SET(retarray->dim[0], 0, -1, 1);
98 return;
99 }
100 else
101 retarray->base_addr = xmallocarray (alloc_size, sizeof (rtype_name));
102 }
103 else
104 {
105 if (rank != GFC_DESCRIPTOR_RANK (retarray))
106 runtime_error ("rank of return array incorrect in"
107 " u_name intrinsic: is %ld, should be %ld",
108 (long int) GFC_DESCRIPTOR_RANK (retarray),
109 (long int) rank);
110
111 if (unlikely (compile_options.bounds_check))
112 {
113 for (n=0; n < rank; n++)
114 {
115 index_type ret_extent;
116
117 ret_extent = GFC_DESCRIPTOR_EXTENT(retarray,n);
118 if (extent[n] != ret_extent)
119 runtime_error ("Incorrect extent in return value of"
120 " u_name intrinsic in dimension %d:"
121 " is %ld, should be %ld", (int) n + 1,
122 (long int) ret_extent, (long int) extent[n]);
123 }
124 }
125 }
126
127 for (n = 0; n < rank; n++)
128 {
129 count[n] = 0;
130 dstride[n] = GFC_DESCRIPTOR_STRIDE(retarray,n);
131 if (extent[n] <= 0)
132 return;
133 }
134
135 base = array->base_addr;
136
137 if (src_kind == 1 || src_kind == 2 || src_kind == 4 || src_kind == 8
138 #ifdef HAVE_GFC_LOGICAL_16
139 || src_kind == 16
140 #endif
141 )
142 {
143 if (base)
144 base = GFOR_POINTER_TO_L1 (base, src_kind);
145 }
146 else
147 internal_error (NULL, "Funny sized logical array in u_name intrinsic");
148
149 dest = retarray->base_addr;
150
151 continue_loop = 1;
152 while (continue_loop)
153 {
154 const GFC_LOGICAL_1 * restrict src;
155 rtype_name result;
156 src = base;
157 {
158 ')dnl
159 define(START_ARRAY_BLOCK,
160 ` if (len <= 0)
161 *dest = '$1`;
162 else
163 {
164 for (n = 0; n < len; n++, src += delta)
165 {
166 ')dnl
167 define(FINISH_ARRAY_FUNCTION,
168 ` }
169 *dest = result;
170 }
171 }
172 /* Advance to the next element. */
173 count[0]++;
174 base += sstride[0];
175 dest += dstride[0];
176 n = 0;
177 while (count[n] == extent[n])
178 {
179 /* When we get to the end of a dimension, reset it and increment
180 the next dimension. */
181 count[n] = 0;
182 /* We could precalculate these products, but this is a less
183 frequently used path so probably not worth it. */
184 base -= sstride[n] * extent[n];
185 dest -= dstride[n] * extent[n];
186 n++;
187 if (n == rank)
188 {
189 /* Break out of the look. */
190 continue_loop = 0;
191 break;
192 }
193 else
194 {
195 count[n]++;
196 base += sstride[n];
197 dest += dstride[n];
198 }
199 }
200 }
201 }')dnl
202 define(ARRAY_FUNCTION,
203 `START_ARRAY_FUNCTION
204 $2
205 START_ARRAY_BLOCK($1)
206 $3
207 FINISH_ARRAY_FUNCTION')dnl