]> git.ipfire.org Git - thirdparty/gcc.git/blame - libgfortran/runtime/in_unpack_generic.c
[nvptx] Fix some missing mode warnings in nvptx.md
[thirdparty/gcc.git] / libgfortran / runtime / in_unpack_generic.c
CommitLineData
4ee9c684 1/* Generic helper function for repacking arrays.
fbd26352 2 Copyright (C) 2003-2019 Free Software Foundation, Inc.
4ee9c684 3 Contributed by Paul Brook <paul@nowt.org>
4
553877d9 5This file is part of the GNU Fortran runtime library (libgfortran).
4ee9c684 6
b417ea8c 7Libgfortran is free software; you can redistribute it and/or
8modify it under the terms of the GNU General Public
4ee9c684 9License as published by the Free Software Foundation; either
6bc9506f 10version 3 of the License, or (at your option) any later version.
b417ea8c 11
12Libgfortran is distributed in the hope that it will be useful,
4ee9c684 13but WITHOUT ANY WARRANTY; without even the implied warranty of
14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
b417ea8c 15GNU General Public License for more details.
4ee9c684 16
6bc9506f 17Under Section 7 of GPL version 3, you are granted additional
18permissions described in the GCC Runtime Library Exception, version
193.1, as published by the Free Software Foundation.
20
21You should have received a copy of the GNU General Public License and
22a copy of the GCC Runtime Library Exception along with this program;
23see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
24<http://www.gnu.org/licenses/>. */
4ee9c684 25
41f2d5e8 26#include "libgfortran.h"
4ee9c684 27#include <string.h>
4ee9c684 28
7b6cb5bd 29extern void internal_unpack (gfc_array_char *, const void *);
30export_proto(internal_unpack);
31
4ee9c684 32void
33internal_unpack (gfc_array_char * d, const void * s)
34{
fa6176a2 35 index_type count[GFC_MAX_DIMENSIONS];
36 index_type extent[GFC_MAX_DIMENSIONS];
37 index_type stride[GFC_MAX_DIMENSIONS];
4ee9c684 38 index_type stride0;
39 index_type dim;
40 index_type dsize;
41 char *dest;
42 const char *src;
df52c9a4 43 index_type size;
ed3634f6 44 int type_size;
4ee9c684 45
553877d9 46 dest = d->base_addr;
4ee9c684 47 /* This check may be redundant, but do it anyway. */
48 if (s == dest || !s)
49 return;
50
ed3634f6 51 type_size = GFC_DTYPE_TYPE_SIZE (d);
52 switch (type_size)
4ee9c684 53 {
ed3634f6 54 case GFC_DTYPE_INTEGER_1:
55 case GFC_DTYPE_LOGICAL_1:
ed3634f6 56 internal_unpack_1 ((gfc_array_i1 *) d, (const GFC_INTEGER_1 *) s);
57 return;
58
59 case GFC_DTYPE_INTEGER_2:
60 case GFC_DTYPE_LOGICAL_2:
61 internal_unpack_2 ((gfc_array_i2 *) d, (const GFC_INTEGER_2 *) s);
62 return;
63
64 case GFC_DTYPE_INTEGER_4:
65 case GFC_DTYPE_LOGICAL_4:
66 internal_unpack_4 ((gfc_array_i4 *) d, (const GFC_INTEGER_4 *) s);
67 return;
68
69 case GFC_DTYPE_INTEGER_8:
70 case GFC_DTYPE_LOGICAL_8:
71 internal_unpack_8 ((gfc_array_i8 *) d, (const GFC_INTEGER_8 *) s);
72 return;
4ee9c684 73
98380129 74#if defined (HAVE_GFC_INTEGER_16)
ed3634f6 75 case GFC_DTYPE_INTEGER_16:
76 case GFC_DTYPE_LOGICAL_16:
77 internal_unpack_16 ((gfc_array_i16 *) d, (const GFC_INTEGER_16 *) s);
78 return;
98380129 79#endif
87969c8c 80
ed3634f6 81 case GFC_DTYPE_REAL_4:
82 internal_unpack_r4 ((gfc_array_r4 *) d, (const GFC_REAL_4 *) s);
83 return;
f27ef643 84
ed3634f6 85 case GFC_DTYPE_REAL_8:
86 internal_unpack_r8 ((gfc_array_r8 *) d, (const GFC_REAL_8 *) s);
87 return;
98380129 88
87969c8c 89/* FIXME: This here is a hack, which will have to be removed when
90 the array descriptor is reworked. Currently, we don't store the
91 kind value for the type, but only the size. Because on targets with
92 __float128, we have sizeof(logn double) == sizeof(__float128),
93 we cannot discriminate here and have to fall back to the generic
94 handling (which is suboptimal). */
95#if !defined(GFC_REAL_16_IS_FLOAT128)
96# if defined(HAVE_GFC_REAL_10)
ed3634f6 97 case GFC_DTYPE_REAL_10:
98 internal_unpack_r10 ((gfc_array_r10 *) d, (const GFC_REAL_10 *) s);
99 return;
87969c8c 100# endif
98380129 101
87969c8c 102# if defined(HAVE_GFC_REAL_16)
ed3634f6 103 case GFC_DTYPE_REAL_16:
104 internal_unpack_r16 ((gfc_array_r16 *) d, (const GFC_REAL_16 *) s);
105 return;
87969c8c 106# endif
98380129 107#endif
87969c8c 108
ed3634f6 109 case GFC_DTYPE_COMPLEX_4:
110 internal_unpack_c4 ((gfc_array_c4 *)d, (const GFC_COMPLEX_4 *)s);
111 return;
98380129 112
ed3634f6 113 case GFC_DTYPE_COMPLEX_8:
114 internal_unpack_c8 ((gfc_array_c8 *)d, (const GFC_COMPLEX_8 *)s);
115 return;
98380129 116
87969c8c 117/* FIXME: This here is a hack, which will have to be removed when
118 the array descriptor is reworked. Currently, we don't store the
119 kind value for the type, but only the size. Because on targets with
120 __float128, we have sizeof(logn double) == sizeof(__float128),
121 we cannot discriminate here and have to fall back to the generic
122 handling (which is suboptimal). */
123#if !defined(GFC_REAL_16_IS_FLOAT128)
124# if defined(HAVE_GFC_COMPLEX_10)
ed3634f6 125 case GFC_DTYPE_COMPLEX_10:
126 internal_unpack_c10 ((gfc_array_c10 *) d, (const GFC_COMPLEX_10 *) s);
127 return;
87969c8c 128# endif
ed3634f6 129
87969c8c 130# if defined(HAVE_GFC_COMPLEX_16)
ed3634f6 131 case GFC_DTYPE_COMPLEX_16:
132 internal_unpack_c16 ((gfc_array_c16 *) d, (const GFC_COMPLEX_16 *) s);
133 return;
87969c8c 134# endif
ed3634f6 135#endif
87969c8c 136
4daa8efe 137 default:
138 break;
139 }
140
141 switch (GFC_DESCRIPTOR_SIZE(d))
142 {
143 case 1:
144 internal_unpack_1 ((gfc_array_i1 *) d, (const GFC_INTEGER_1 *) s);
145 return;
146
147 case 2:
553877d9 148 if (GFC_UNALIGNED_2(d->base_addr) || GFC_UNALIGNED_2(s))
ed3634f6 149 break;
150 else
f27ef643 151 {
ed3634f6 152 internal_unpack_2 ((gfc_array_i2 *) d, (const GFC_INTEGER_2 *) s);
f27ef643 153 return;
ed3634f6 154 }
4daa8efe 155
156 case 4:
553877d9 157 if (GFC_UNALIGNED_4(d->base_addr) || GFC_UNALIGNED_4(s))
ed3634f6 158 break;
159 else
160 {
161 internal_unpack_4 ((gfc_array_i4 *) d, (const GFC_INTEGER_4 *) s);
f27ef643 162 return;
ed3634f6 163 }
98380129 164
4daa8efe 165 case 8:
553877d9 166 if (GFC_UNALIGNED_8(d->base_addr) || GFC_UNALIGNED_8(s))
ed3634f6 167 break;
168 else
169 {
170 internal_unpack_8 ((gfc_array_i8 *) d, (const GFC_INTEGER_8 *) s);
98380129 171 return;
ed3634f6 172 }
98380129 173
ed3634f6 174#ifdef HAVE_GFC_INTEGER_16
4daa8efe 175 case 16:
553877d9 176 if (GFC_UNALIGNED_16(d->base_addr) || GFC_UNALIGNED_16(s))
ed3634f6 177 break;
178 else
179 {
180 internal_unpack_16 ((gfc_array_i16 *) d, (const GFC_INTEGER_16 *) s);
98380129 181 return;
ed3634f6 182 }
98380129 183#endif
f27ef643 184 default:
185 break;
4ee9c684 186 }
187
ed3634f6 188 size = GFC_DESCRIPTOR_SIZE (d);
189
4ee9c684 190 dim = GFC_DESCRIPTOR_RANK (d);
191 dsize = 1;
df52c9a4 192 for (index_type n = 0; n < dim; n++)
4ee9c684 193 {
194 count[n] = 0;
827aef63 195 stride[n] = GFC_DESCRIPTOR_STRIDE(d,n);
196 extent[n] = GFC_DESCRIPTOR_EXTENT(d,n);
4ee9c684 197 if (extent[n] <= 0)
edfaa9e3 198 return;
4ee9c684 199
200 if (dsize == stride[n])
edfaa9e3 201 dsize *= extent[n];
4ee9c684 202 else
edfaa9e3 203 dsize = 0;
4ee9c684 204 }
205
206 src = s;
207
208 if (dsize != 0)
209 {
210 memcpy (dest, src, dsize * size);
211 return;
212 }
213
214 stride0 = stride[0] * size;
215
216 while (dest)
217 {
218 /* Copy the data. */
219 memcpy (dest, src, size);
220 /* Advance to the next element. */
221 src += size;
222 dest += stride0;
223 count[0]++;
224 /* Advance to the next source element. */
df52c9a4 225 index_type n = 0;
4ee9c684 226 while (count[n] == extent[n])
227 {
228 /* When we get to the end of a dimension, reset it and increment
229 the next dimension. */
230 count[n] = 0;
231 /* We could precalculate these products, but this is a less
a2ffc2c4 232 frequently used path so probably not worth it. */
4ee9c684 233 dest -= stride[n] * extent[n] * size;
234 n++;
235 if (n == dim)
236 {
237 dest = NULL;
238 break;
239 }
240 else
241 {
242 count[n]++;
243 dest += stride[n] * size;
244 }
245 }
246 }
247}