1*4c3eb207Smrg /* Copyright (C) 2009-2020 Free Software Foundation, Inc.
2627f7eb2Smrg Contributed by Thomas Koenig
3627f7eb2Smrg
4627f7eb2Smrg This file is part of the GNU Fortran runtime library (libgfortran).
5627f7eb2Smrg
6627f7eb2Smrg Libgfortran is free software; you can redistribute it and/or modify
7627f7eb2Smrg it under the terms of the GNU General Public License as published by
8627f7eb2Smrg the Free Software Foundation; either version 3, or (at your option)
9627f7eb2Smrg any later version.
10627f7eb2Smrg
11627f7eb2Smrg Libgfortran is distributed in the hope that it will be useful,
12627f7eb2Smrg but WITHOUT ANY WARRANTY; without even the implied warranty of
13627f7eb2Smrg MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14627f7eb2Smrg GNU General Public License for more details.
15627f7eb2Smrg
16627f7eb2Smrg Under Section 7 of GPL version 3, you are granted additional
17627f7eb2Smrg permissions described in the GCC Runtime Library Exception, version
18627f7eb2Smrg 3.1, as published by the Free Software Foundation.
19627f7eb2Smrg
20627f7eb2Smrg You should have received a copy of the GNU General Public License and
21627f7eb2Smrg a copy of the GCC Runtime Library Exception along with this program;
22627f7eb2Smrg see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
23627f7eb2Smrg <http://www.gnu.org/licenses/>. */
24627f7eb2Smrg
25627f7eb2Smrg #include "libgfortran.h"
26627f7eb2Smrg #include <assert.h>
27627f7eb2Smrg
28627f7eb2Smrg /* Auxiliary functions for bounds checking, mostly to reduce library size. */
29627f7eb2Smrg
30627f7eb2Smrg /* Bounds checking for the return values of the iforeach functions (such
31627f7eb2Smrg as maxloc and minloc). The extent of ret_array must
32627f7eb2Smrg must match the rank of array. */
33627f7eb2Smrg
34627f7eb2Smrg void
bounds_iforeach_return(array_t * retarray,array_t * array,const char * name)35627f7eb2Smrg bounds_iforeach_return (array_t *retarray, array_t *array, const char *name)
36627f7eb2Smrg {
37627f7eb2Smrg index_type rank;
38627f7eb2Smrg index_type ret_rank;
39627f7eb2Smrg index_type ret_extent;
40627f7eb2Smrg
41627f7eb2Smrg ret_rank = GFC_DESCRIPTOR_RANK (retarray);
42627f7eb2Smrg
43627f7eb2Smrg /* ret_rank should always be 1, otherwise there is an internal error */
44627f7eb2Smrg GFC_ASSERT(ret_rank == 1);
45627f7eb2Smrg
46627f7eb2Smrg rank = GFC_DESCRIPTOR_RANK (array);
47627f7eb2Smrg ret_extent = GFC_DESCRIPTOR_EXTENT(retarray,0);
48627f7eb2Smrg if (ret_extent != rank)
49627f7eb2Smrg runtime_error ("Incorrect extent in return value of"
50627f7eb2Smrg " %s intrinsic: is %ld, should be %ld",
51627f7eb2Smrg name, (long int) ret_extent, (long int) rank);
52627f7eb2Smrg
53627f7eb2Smrg }
54627f7eb2Smrg
55627f7eb2Smrg /* Check the return of functions generated from ifunction.m4.
56627f7eb2Smrg We check the array descriptor "a" against the extents precomputed
57627f7eb2Smrg from ifunction.m4, and complain about the argument a_name in the
58627f7eb2Smrg intrinsic function. */
59627f7eb2Smrg
60627f7eb2Smrg void
bounds_ifunction_return(array_t * a,const index_type * extent,const char * a_name,const char * intrinsic)61627f7eb2Smrg bounds_ifunction_return (array_t * a, const index_type * extent,
62627f7eb2Smrg const char * a_name, const char * intrinsic)
63627f7eb2Smrg {
64627f7eb2Smrg int empty;
65627f7eb2Smrg int rank;
66627f7eb2Smrg index_type a_size;
67627f7eb2Smrg
68627f7eb2Smrg rank = GFC_DESCRIPTOR_RANK (a);
69627f7eb2Smrg a_size = size0 (a);
70627f7eb2Smrg
71627f7eb2Smrg empty = 0;
72627f7eb2Smrg for (index_type n = 0; n < rank; n++)
73627f7eb2Smrg {
74627f7eb2Smrg if (extent[n] == 0)
75627f7eb2Smrg empty = 1;
76627f7eb2Smrg }
77627f7eb2Smrg if (empty)
78627f7eb2Smrg {
79627f7eb2Smrg if (a_size != 0)
80627f7eb2Smrg runtime_error ("Incorrect size in %s of %s"
81627f7eb2Smrg " intrinsic: should be zero-sized",
82627f7eb2Smrg a_name, intrinsic);
83627f7eb2Smrg }
84627f7eb2Smrg else
85627f7eb2Smrg {
86627f7eb2Smrg if (a_size == 0)
87627f7eb2Smrg runtime_error ("Incorrect size of %s in %s"
88627f7eb2Smrg " intrinsic: should not be zero-sized",
89627f7eb2Smrg a_name, intrinsic);
90627f7eb2Smrg
91627f7eb2Smrg for (index_type n = 0; n < rank; n++)
92627f7eb2Smrg {
93627f7eb2Smrg index_type a_extent;
94627f7eb2Smrg a_extent = GFC_DESCRIPTOR_EXTENT(a, n);
95627f7eb2Smrg if (a_extent != extent[n])
96627f7eb2Smrg runtime_error("Incorrect extent in %s of %s"
97627f7eb2Smrg " intrinsic in dimension %ld: is %ld,"
98627f7eb2Smrg " should be %ld", a_name, intrinsic, (long int) n + 1,
99627f7eb2Smrg (long int) a_extent, (long int) extent[n]);
100627f7eb2Smrg
101627f7eb2Smrg }
102627f7eb2Smrg }
103627f7eb2Smrg }
104627f7eb2Smrg
105627f7eb2Smrg /* Check that two arrays have equal extents, or are both zero-sized. Abort
106627f7eb2Smrg with a runtime error if this is not the case. Complain that a has the
107627f7eb2Smrg wrong size. */
108627f7eb2Smrg
109627f7eb2Smrg void
bounds_equal_extents(array_t * a,array_t * b,const char * a_name,const char * intrinsic)110627f7eb2Smrg bounds_equal_extents (array_t *a, array_t *b, const char *a_name,
111627f7eb2Smrg const char *intrinsic)
112627f7eb2Smrg {
113627f7eb2Smrg index_type a_size, b_size, n;
114627f7eb2Smrg
115627f7eb2Smrg assert (GFC_DESCRIPTOR_RANK(a) == GFC_DESCRIPTOR_RANK(b));
116627f7eb2Smrg
117627f7eb2Smrg a_size = size0 (a);
118627f7eb2Smrg b_size = size0 (b);
119627f7eb2Smrg
120627f7eb2Smrg if (b_size == 0)
121627f7eb2Smrg {
122627f7eb2Smrg if (a_size != 0)
123627f7eb2Smrg runtime_error ("Incorrect size of %s in %s"
124627f7eb2Smrg " intrinsic: should be zero-sized",
125627f7eb2Smrg a_name, intrinsic);
126627f7eb2Smrg }
127627f7eb2Smrg else
128627f7eb2Smrg {
129627f7eb2Smrg if (a_size == 0)
130627f7eb2Smrg runtime_error ("Incorrect size of %s of %s"
131627f7eb2Smrg " intrinsic: Should not be zero-sized",
132627f7eb2Smrg a_name, intrinsic);
133627f7eb2Smrg
134627f7eb2Smrg for (n = 0; n < GFC_DESCRIPTOR_RANK (b); n++)
135627f7eb2Smrg {
136627f7eb2Smrg index_type a_extent, b_extent;
137627f7eb2Smrg
138627f7eb2Smrg a_extent = GFC_DESCRIPTOR_EXTENT(a, n);
139627f7eb2Smrg b_extent = GFC_DESCRIPTOR_EXTENT(b, n);
140627f7eb2Smrg if (a_extent != b_extent)
141627f7eb2Smrg runtime_error("Incorrect extent in %s of %s"
142627f7eb2Smrg " intrinsic in dimension %ld: is %ld,"
143627f7eb2Smrg " should be %ld", a_name, intrinsic, (long int) n + 1,
144627f7eb2Smrg (long int) a_extent, (long int) b_extent);
145627f7eb2Smrg }
146627f7eb2Smrg }
147627f7eb2Smrg }
148627f7eb2Smrg
149627f7eb2Smrg /* Check that the extents of a and b agree, except that a has a missing
150627f7eb2Smrg dimension in argument which. Complain about a if anything is wrong. */
151627f7eb2Smrg
152627f7eb2Smrg void
bounds_reduced_extents(array_t * a,array_t * b,int which,const char * a_name,const char * intrinsic)153627f7eb2Smrg bounds_reduced_extents (array_t *a, array_t *b, int which, const char *a_name,
154627f7eb2Smrg const char *intrinsic)
155627f7eb2Smrg {
156627f7eb2Smrg
157627f7eb2Smrg index_type i, n, a_size, b_size;
158627f7eb2Smrg
159627f7eb2Smrg assert (GFC_DESCRIPTOR_RANK(a) == GFC_DESCRIPTOR_RANK(b) - 1);
160627f7eb2Smrg
161627f7eb2Smrg a_size = size0 (a);
162627f7eb2Smrg b_size = size0 (b);
163627f7eb2Smrg
164627f7eb2Smrg if (b_size == 0)
165627f7eb2Smrg {
166627f7eb2Smrg if (a_size != 0)
167627f7eb2Smrg runtime_error ("Incorrect size in %s of %s"
168627f7eb2Smrg " intrinsic: should not be zero-sized",
169627f7eb2Smrg a_name, intrinsic);
170627f7eb2Smrg }
171627f7eb2Smrg else
172627f7eb2Smrg {
173627f7eb2Smrg if (a_size == 0)
174627f7eb2Smrg runtime_error ("Incorrect size of %s of %s"
175627f7eb2Smrg " intrinsic: should be zero-sized",
176627f7eb2Smrg a_name, intrinsic);
177627f7eb2Smrg
178627f7eb2Smrg i = 0;
179627f7eb2Smrg for (n = 0; n < GFC_DESCRIPTOR_RANK (b); n++)
180627f7eb2Smrg {
181627f7eb2Smrg index_type a_extent, b_extent;
182627f7eb2Smrg
183627f7eb2Smrg if (n != which)
184627f7eb2Smrg {
185627f7eb2Smrg a_extent = GFC_DESCRIPTOR_EXTENT(a, i);
186627f7eb2Smrg b_extent = GFC_DESCRIPTOR_EXTENT(b, n);
187627f7eb2Smrg if (a_extent != b_extent)
188627f7eb2Smrg runtime_error("Incorrect extent in %s of %s"
189627f7eb2Smrg " intrinsic in dimension %ld: is %ld,"
190627f7eb2Smrg " should be %ld", a_name, intrinsic, (long int) i + 1,
191627f7eb2Smrg (long int) a_extent, (long int) b_extent);
192627f7eb2Smrg i++;
193627f7eb2Smrg }
194627f7eb2Smrg }
195627f7eb2Smrg }
196627f7eb2Smrg }
197627f7eb2Smrg
198627f7eb2Smrg /* count_0 - count all the true elements in an array. The front
199627f7eb2Smrg end usually inlines this, we need this for bounds checking
200627f7eb2Smrg for unpack. */
201627f7eb2Smrg
count_0(const gfc_array_l1 * array)202627f7eb2Smrg index_type count_0 (const gfc_array_l1 * array)
203627f7eb2Smrg {
204627f7eb2Smrg const GFC_LOGICAL_1 * restrict base;
205627f7eb2Smrg index_type rank;
206627f7eb2Smrg int kind;
207627f7eb2Smrg int continue_loop;
208627f7eb2Smrg index_type count[GFC_MAX_DIMENSIONS];
209627f7eb2Smrg index_type extent[GFC_MAX_DIMENSIONS];
210627f7eb2Smrg index_type sstride[GFC_MAX_DIMENSIONS];
211627f7eb2Smrg index_type result;
212627f7eb2Smrg index_type n;
213627f7eb2Smrg
214627f7eb2Smrg rank = GFC_DESCRIPTOR_RANK (array);
215627f7eb2Smrg kind = GFC_DESCRIPTOR_SIZE (array);
216627f7eb2Smrg
217627f7eb2Smrg base = array->base_addr;
218627f7eb2Smrg
219627f7eb2Smrg if (kind == 1 || kind == 2 || kind == 4 || kind == 8
220627f7eb2Smrg #ifdef HAVE_GFC_LOGICAL_16
221627f7eb2Smrg || kind == 16
222627f7eb2Smrg #endif
223627f7eb2Smrg )
224627f7eb2Smrg {
225627f7eb2Smrg if (base)
226627f7eb2Smrg base = GFOR_POINTER_TO_L1 (base, kind);
227627f7eb2Smrg }
228627f7eb2Smrg else
229627f7eb2Smrg internal_error (NULL, "Funny sized logical array in count_0");
230627f7eb2Smrg
231627f7eb2Smrg for (n = 0; n < rank; n++)
232627f7eb2Smrg {
233627f7eb2Smrg sstride[n] = GFC_DESCRIPTOR_STRIDE_BYTES(array,n);
234627f7eb2Smrg extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
235627f7eb2Smrg count[n] = 0;
236627f7eb2Smrg
237627f7eb2Smrg if (extent[n] <= 0)
238627f7eb2Smrg return 0;
239627f7eb2Smrg }
240627f7eb2Smrg
241627f7eb2Smrg result = 0;
242627f7eb2Smrg continue_loop = 1;
243627f7eb2Smrg while (continue_loop)
244627f7eb2Smrg {
245627f7eb2Smrg if (*base)
246627f7eb2Smrg result ++;
247627f7eb2Smrg
248627f7eb2Smrg count[0]++;
249627f7eb2Smrg base += sstride[0];
250627f7eb2Smrg n = 0;
251627f7eb2Smrg while (count[n] == extent[n])
252627f7eb2Smrg {
253627f7eb2Smrg count[n] = 0;
254627f7eb2Smrg base -= sstride[n] * extent[n];
255627f7eb2Smrg n++;
256627f7eb2Smrg if (n == rank)
257627f7eb2Smrg {
258627f7eb2Smrg continue_loop = 0;
259627f7eb2Smrg break;
260627f7eb2Smrg }
261627f7eb2Smrg else
262627f7eb2Smrg {
263627f7eb2Smrg count[n]++;
264627f7eb2Smrg base += sstride[n];
265627f7eb2Smrg }
266627f7eb2Smrg }
267627f7eb2Smrg }
268627f7eb2Smrg return result;
269627f7eb2Smrg }
270