Update LOCAL_PATCHES after libsanitizer merge.
[official-gcc.git] / libgfortran / generated / findloc0_s1.c
blob3b0f9b07349af572d1691579a5bd704a9a7b0659
2 /* Implementation of the FINDLOC intrinsic
3 Copyright (C) 2018 Free Software Foundation, Inc.
4 Contributed by Thomas König <tk@tkoenig.net>
6 This file is part of the GNU Fortran 95 runtime library (libgfortran).
8 Libgfortran is free software; you can redistribute it and/or
9 modify it under the terms of the GNU General Public
10 License as published by the Free Software Foundation; either
11 version 3 of the License, or (at your option) any later version.
13 Libgfortran is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 Under Section 7 of GPL version 3, you are granted additional
19 permissions described in the GCC Runtime Library Exception, version
20 3.1, as published by the Free Software Foundation.
22 You should have received a copy of the GNU General Public License and
23 a copy of the GCC Runtime Library Exception along with this program;
24 see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
25 <http://www.gnu.org/licenses/>. */
27 #include "libgfortran.h"
28 #include <assert.h>
30 #if defined (HAVE_GFC_UINTEGER_1)
31 extern void findloc0_s1 (gfc_array_index_type * const restrict retarray,
32 gfc_array_s1 * const restrict array, GFC_UINTEGER_1 *value,
33 GFC_LOGICAL_4 back, gfc_charlen_type len_array, gfc_charlen_type len_value);
35 export_proto(findloc0_s1);
37 void
38 findloc0_s1 (gfc_array_index_type * const restrict retarray,
39 gfc_array_s1 * const restrict array, GFC_UINTEGER_1 *value,
40 GFC_LOGICAL_4 back, gfc_charlen_type len_array, gfc_charlen_type len_value)
42 index_type count[GFC_MAX_DIMENSIONS];
43 index_type extent[GFC_MAX_DIMENSIONS];
44 index_type sstride[GFC_MAX_DIMENSIONS];
45 index_type dstride;
46 const GFC_UINTEGER_1 *base;
47 index_type * restrict dest;
48 index_type rank;
49 index_type n;
50 index_type sz;
52 rank = GFC_DESCRIPTOR_RANK (array);
53 if (rank <= 0)
54 runtime_error ("Rank of array needs to be > 0");
56 if (retarray->base_addr == NULL)
58 GFC_DIMENSION_SET(retarray->dim[0], 0, rank-1, 1);
59 retarray->dtype.rank = 1;
60 retarray->offset = 0;
61 retarray->base_addr = xmallocarray (rank, sizeof (GFC_INTEGER_4));
63 else
65 if (unlikely (compile_options.bounds_check))
66 bounds_iforeach_return ((array_t *) retarray, (array_t *) array,
67 "FINDLOC");
70 dstride = GFC_DESCRIPTOR_STRIDE(retarray,0);
71 dest = retarray->base_addr;
73 /* Set the return value. */
74 for (n = 0; n < rank; n++)
75 dest[n * dstride] = 0;
77 sz = 1;
78 for (n = 0; n < rank; n++)
80 sstride[n] = GFC_DESCRIPTOR_STRIDE(array,n);
81 extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
82 sz *= extent[n];
83 if (extent[n] <= 0)
84 return;
87 for (n = 0; n < rank; n++)
88 count[n] = 0;
90 if (back)
92 base = array->base_addr + (sz - 1) * len_array;
94 while (1)
98 if (unlikely(compare_string (len_array, (char *) base, len_value, (char *) value) == 0))
100 for (n = 0; n < rank; n++)
101 dest[n * dstride] = extent[n] - count[n];
103 return;
105 base -= sstride[0] * len_array;
106 } while(++count[0] != extent[0]);
108 n = 0;
111 /* When we get to the end of a dimension, reset it and increment
112 the next dimension. */
113 count[n] = 0;
114 /* We could precalculate these products, but this is a less
115 frequently used path so probably not worth it. */
116 base += sstride[n] * extent[n] * len_array;
117 n++;
118 if (n >= rank)
119 return;
120 else
122 count[n]++;
123 base -= sstride[n] * len_array;
125 } while (count[n] == extent[n]);
128 else
130 base = array->base_addr;
131 while (1)
135 if (unlikely(compare_string (len_array, (char *) base, len_value, (char *) value) == 0))
137 for (n = 0; n < rank; n++)
138 dest[n * dstride] = count[n] + 1;
140 return;
142 base += sstride[0] * len_array;
143 } while(++count[0] != extent[0]);
145 n = 0;
148 /* When we get to the end of a dimension, reset it and increment
149 the next dimension. */
150 count[n] = 0;
151 /* We could precalculate these products, but this is a less
152 frequently used path so probably not worth it. */
153 base -= sstride[n] * extent[n] * len_array;
154 n++;
155 if (n >= rank)
156 return;
157 else
159 count[n]++;
160 base += sstride[n] * len_array;
162 } while (count[n] == extent[n]);
165 return;
168 extern void mfindloc0_s1 (gfc_array_index_type * const restrict retarray,
169 gfc_array_s1 * const restrict array, GFC_UINTEGER_1 *value,
170 gfc_array_l1 *const restrict, GFC_LOGICAL_4 back, gfc_charlen_type len_array,
171 gfc_charlen_type len_value);
172 export_proto(mfindloc0_s1);
174 void
175 mfindloc0_s1 (gfc_array_index_type * const restrict retarray,
176 gfc_array_s1 * const restrict array, GFC_UINTEGER_1 *value,
177 gfc_array_l1 *const restrict mask, GFC_LOGICAL_4 back,
178 gfc_charlen_type len_array, gfc_charlen_type len_value)
180 index_type count[GFC_MAX_DIMENSIONS];
181 index_type extent[GFC_MAX_DIMENSIONS];
182 index_type sstride[GFC_MAX_DIMENSIONS];
183 index_type mstride[GFC_MAX_DIMENSIONS];
184 index_type dstride;
185 const GFC_UINTEGER_1 *base;
186 index_type * restrict dest;
187 GFC_LOGICAL_1 *mbase;
188 index_type rank;
189 index_type n;
190 int mask_kind;
191 index_type sz;
193 rank = GFC_DESCRIPTOR_RANK (array);
194 if (rank <= 0)
195 runtime_error ("Rank of array needs to be > 0");
197 if (retarray->base_addr == NULL)
199 GFC_DIMENSION_SET(retarray->dim[0], 0, rank-1, 1);
200 retarray->dtype.rank = 1;
201 retarray->offset = 0;
202 retarray->base_addr = xmallocarray (rank, sizeof (GFC_INTEGER_4));
204 else
206 if (unlikely (compile_options.bounds_check))
208 bounds_iforeach_return ((array_t *) retarray, (array_t *) array,
209 "FINDLOC");
210 bounds_equal_extents ((array_t *) mask, (array_t *) array,
211 "MASK argument", "FINDLOC");
215 mask_kind = GFC_DESCRIPTOR_SIZE (mask);
217 mbase = mask->base_addr;
219 if (mask_kind == 1 || mask_kind == 2 || mask_kind == 4 || mask_kind == 8
220 #ifdef HAVE_GFC_LOGICAL_16
221 || mask_kind == 16
222 #endif
224 mbase = GFOR_POINTER_TO_L1 (mbase, mask_kind);
225 else
226 internal_error (NULL, "Funny sized logical array");
228 dstride = GFC_DESCRIPTOR_STRIDE(retarray,0);
229 dest = retarray->base_addr;
231 /* Set the return value. */
232 for (n = 0; n < rank; n++)
233 dest[n * dstride] = 0;
235 sz = 1;
236 for (n = 0; n < rank; n++)
238 sstride[n] = GFC_DESCRIPTOR_STRIDE(array,n);
239 mstride[n] = GFC_DESCRIPTOR_STRIDE_BYTES(mask,n);
240 extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
241 sz *= extent[n];
242 if (extent[n] <= 0)
243 return;
246 for (n = 0; n < rank; n++)
247 count[n] = 0;
249 if (back)
251 base = array->base_addr + (sz - 1) * len_array;
252 mbase = mbase + (sz - 1) * mask_kind;
253 while (1)
257 if (unlikely(*mbase && compare_string (len_array, (char *) base, len_value, (char *) value) == 0))
259 for (n = 0; n < rank; n++)
260 dest[n * dstride] = extent[n] - count[n];
262 return;
264 base -= sstride[0] * len_array;
265 mbase -= mstride[0];
266 } while(++count[0] != extent[0]);
268 n = 0;
271 /* When we get to the end of a dimension, reset it and increment
272 the next dimension. */
273 count[n] = 0;
274 /* We could precalculate these products, but this is a less
275 frequently used path so probably not worth it. */
276 base += sstride[n] * extent[n] * len_array;
277 mbase -= mstride[n] * extent[n];
278 n++;
279 if (n >= rank)
280 return;
281 else
283 count[n]++;
284 base -= sstride[n] * len_array;
285 mbase += mstride[n];
287 } while (count[n] == extent[n]);
290 else
292 base = array->base_addr;
293 while (1)
297 if (unlikely(*mbase && compare_string (len_array, (char *) base, len_value, (char *) value) == 0))
299 for (n = 0; n < rank; n++)
300 dest[n * dstride] = count[n] + 1;
302 return;
304 base += sstride[0] * len_array;
305 mbase += mstride[0];
306 } while(++count[0] != extent[0]);
308 n = 0;
311 /* When we get to the end of a dimension, reset it and increment
312 the next dimension. */
313 count[n] = 0;
314 /* We could precalculate these products, but this is a less
315 frequently used path so probably not worth it. */
316 base -= sstride[n] * extent[n] * len_array;
317 mbase -= mstride[n] * extent[n];
318 n++;
319 if (n >= rank)
320 return;
321 else
323 count[n]++;
324 base += sstride[n]* len_array;
325 mbase += mstride[n];
327 } while (count[n] == extent[n]);
330 return;
333 extern void sfindloc0_s1 (gfc_array_index_type * const restrict retarray,
334 gfc_array_s1 * const restrict array, GFC_UINTEGER_1 *value,
335 GFC_LOGICAL_4 *, GFC_LOGICAL_4 back, gfc_charlen_type len_array,
336 gfc_charlen_type len_value);
337 export_proto(sfindloc0_s1);
339 void
340 sfindloc0_s1 (gfc_array_index_type * const restrict retarray,
341 gfc_array_s1 * const restrict array, GFC_UINTEGER_1 *value,
342 GFC_LOGICAL_4 * mask, GFC_LOGICAL_4 back, gfc_charlen_type len_array,
343 gfc_charlen_type len_value)
345 index_type rank;
346 index_type dstride;
347 index_type * restrict dest;
348 index_type n;
350 if (*mask)
352 findloc0_s1 (retarray, array, value, back, len_array, len_value);
353 return;
356 rank = GFC_DESCRIPTOR_RANK (array);
358 if (rank <= 0)
359 internal_error (NULL, "Rank of array needs to be > 0");
361 if (retarray->base_addr == NULL)
363 GFC_DIMENSION_SET(retarray->dim[0], 0, rank-1, 1);
364 retarray->dtype.rank = 1;
365 retarray->offset = 0;
366 retarray->base_addr = xmallocarray (rank, sizeof (GFC_INTEGER_4));
368 else if (unlikely (compile_options.bounds_check))
370 bounds_iforeach_return ((array_t *) retarray, (array_t *) array,
371 "FINDLOC");
374 dstride = GFC_DESCRIPTOR_STRIDE(retarray,0);
375 dest = retarray->base_addr;
376 for (n = 0; n<rank; n++)
377 dest[n * dstride] = 0 ;
380 #endif