1 /* Generic implementation of the UNPACK intrinsic
2 Copyright (C) 2002-2018 Free Software Foundation, Inc.
3 Contributed by Paul Brook <paul@nowt.org>
5 This file is part of the GNU Fortran runtime library (libgfortran).
7 Libgfortran is free software; you can redistribute it and/or
8 modify it under the terms of the GNU General Public
9 License as published by the Free Software Foundation; either
10 version 3 of the License, or (at your option) any later version.
12 Ligbfortran is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 Under Section 7 of GPL version 3, you are granted additional
18 permissions described in the GCC Runtime Library Exception, version
19 3.1, as published by the Free Software Foundation.
21 You should have received a copy of the GNU General Public License and
22 a copy of the GCC Runtime Library Exception along with this program;
23 see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
24 <http://www.gnu.org/licenses/>. */
26 #include "libgfortran.h"
30 /* All the bounds checking for unpack in one function. If field is NULL,
31 we don't check it, for the unpack0 functions. */
34 unpack_bounds (gfc_array_char
*ret
, const gfc_array_char
*vector
,
35 const gfc_array_l1
*mask
, const gfc_array_char
*field
)
37 index_type vec_size
, mask_count
;
38 vec_size
= size0 ((array_t
*) vector
);
39 mask_count
= count_0 (mask
);
40 if (vec_size
< mask_count
)
41 runtime_error ("Incorrect size of return value in UNPACK"
42 " intrinsic: should be at least %ld, is"
43 " %ld", (long int) mask_count
,
47 bounds_equal_extents ((array_t
*) field
, (array_t
*) mask
,
50 if (ret
->base_addr
!= NULL
)
51 bounds_equal_extents ((array_t
*) ret
, (array_t
*) mask
,
52 "return value", "UNPACK");
57 unpack_internal (gfc_array_char
*ret
, const gfc_array_char
*vector
,
58 const gfc_array_l1
*mask
, const gfc_array_char
*field
,
61 /* r.* indicates the return array. */
62 index_type rstride
[GFC_MAX_DIMENSIONS
];
66 /* v.* indicates the vector array. */
69 /* f.* indicates the field array. */
70 index_type fstride
[GFC_MAX_DIMENSIONS
];
73 /* m.* indicates the mask array. */
74 index_type mstride
[GFC_MAX_DIMENSIONS
];
76 const GFC_LOGICAL_1
*mptr
;
78 index_type count
[GFC_MAX_DIMENSIONS
];
79 index_type extent
[GFC_MAX_DIMENSIONS
];
88 mptr
= mask
->base_addr
;
90 /* Use the same loop for all logical types, by using GFC_LOGICAL_1
91 and using shifting to address size and endian issues. */
93 mask_kind
= GFC_DESCRIPTOR_SIZE (mask
);
95 if (mask_kind
== 1 || mask_kind
== 2 || mask_kind
== 4 || mask_kind
== 8
96 #ifdef HAVE_GFC_LOGICAL_16
101 /* Don't convert a NULL pointer as we use test for NULL below. */
103 mptr
= GFOR_POINTER_TO_L1 (mptr
, mask_kind
);
106 runtime_error ("Funny sized logical array");
108 if (ret
->base_addr
== NULL
)
110 /* The front end has signalled that we need to populate the
111 return array descriptor. */
112 dim
= GFC_DESCRIPTOR_RANK (mask
);
114 for (n
= 0; n
< dim
; n
++)
117 GFC_DIMENSION_SET(ret
->dim
[n
], 0,
118 GFC_DESCRIPTOR_EXTENT(mask
,n
) - 1, rs
);
119 extent
[n
] = GFC_DESCRIPTOR_EXTENT(ret
,n
);
120 empty
= empty
|| extent
[n
] <= 0;
121 rstride
[n
] = GFC_DESCRIPTOR_STRIDE_BYTES(ret
, n
);
122 fstride
[n
] = GFC_DESCRIPTOR_STRIDE_BYTES(field
, n
);
123 mstride
[n
] = GFC_DESCRIPTOR_STRIDE_BYTES(mask
, n
);
127 ret
->base_addr
= xmallocarray (rs
, size
);
131 dim
= GFC_DESCRIPTOR_RANK (ret
);
132 for (n
= 0; n
< dim
; n
++)
135 extent
[n
] = GFC_DESCRIPTOR_EXTENT(ret
,n
);
136 empty
= empty
|| extent
[n
] <= 0;
137 rstride
[n
] = GFC_DESCRIPTOR_STRIDE_BYTES(ret
, n
);
138 fstride
[n
] = GFC_DESCRIPTOR_STRIDE_BYTES(field
, n
);
139 mstride
[n
] = GFC_DESCRIPTOR_STRIDE_BYTES(mask
, n
);
146 /* This assert makes sure GCC knows we can access *stride[0] later. */
149 vstride0
= GFC_DESCRIPTOR_STRIDE_BYTES(vector
,0);
150 rstride0
= rstride
[0];
151 fstride0
= fstride
[0];
152 mstride0
= mstride
[0];
153 rptr
= ret
->base_addr
;
154 fptr
= field
->base_addr
;
155 vptr
= vector
->base_addr
;
162 memcpy (rptr
, vptr
, size
);
168 memcpy (rptr
, fptr
, size
);
170 /* Advance to the next element. */
176 while (count
[n
] == extent
[n
])
178 /* When we get to the end of a dimension, reset it and increment
179 the next dimension. */
181 /* We could precalculate these products, but this is a less
182 frequently used path so probably not worth it. */
183 rptr
-= rstride
[n
] * extent
[n
];
184 fptr
-= fstride
[n
] * extent
[n
];
185 mptr
-= mstride
[n
] * extent
[n
];
189 /* Break out of the loop. */
204 extern void unpack1 (gfc_array_char
*, const gfc_array_char
*,
205 const gfc_array_l1
*, const gfc_array_char
*);
206 export_proto(unpack1
);
209 unpack1 (gfc_array_char
*ret
, const gfc_array_char
*vector
,
210 const gfc_array_l1
*mask
, const gfc_array_char
*field
)
212 index_type type_size
;
215 if (unlikely(compile_options
.bounds_check
))
216 unpack_bounds (ret
, vector
, mask
, field
);
218 type_size
= GFC_DTYPE_TYPE_SIZE (vector
);
219 size
= GFC_DESCRIPTOR_SIZE (vector
);
223 case GFC_DTYPE_LOGICAL_1
:
224 case GFC_DTYPE_INTEGER_1
:
225 unpack1_i1 ((gfc_array_i1
*) ret
, (gfc_array_i1
*) vector
,
226 mask
, (gfc_array_i1
*) field
);
229 case GFC_DTYPE_LOGICAL_2
:
230 case GFC_DTYPE_INTEGER_2
:
231 unpack1_i2 ((gfc_array_i2
*) ret
, (gfc_array_i2
*) vector
,
232 mask
, (gfc_array_i2
*) field
);
235 case GFC_DTYPE_LOGICAL_4
:
236 case GFC_DTYPE_INTEGER_4
:
237 unpack1_i4 ((gfc_array_i4
*) ret
, (gfc_array_i4
*) vector
,
238 mask
, (gfc_array_i4
*) field
);
241 case GFC_DTYPE_LOGICAL_8
:
242 case GFC_DTYPE_INTEGER_8
:
243 unpack1_i8 ((gfc_array_i8
*) ret
, (gfc_array_i8
*) vector
,
244 mask
, (gfc_array_i8
*) field
);
247 #ifdef HAVE_GFC_INTEGER_16
248 case GFC_DTYPE_LOGICAL_16
:
249 case GFC_DTYPE_INTEGER_16
:
250 unpack1_i16 ((gfc_array_i16
*) ret
, (gfc_array_i16
*) vector
,
251 mask
, (gfc_array_i16
*) field
);
255 case GFC_DTYPE_REAL_4
:
256 unpack1_r4 ((gfc_array_r4
*) ret
, (gfc_array_r4
*) vector
,
257 mask
, (gfc_array_r4
*) field
);
260 case GFC_DTYPE_REAL_8
:
261 unpack1_r8 ((gfc_array_r8
*) ret
, (gfc_array_r8
*) vector
,
262 mask
, (gfc_array_r8
*) field
);
265 /* FIXME: This here is a hack, which will have to be removed when
266 the array descriptor is reworked. Currently, we don't store the
267 kind value for the type, but only the size. Because on targets with
268 __float128, we have sizeof(logn double) == sizeof(__float128),
269 we cannot discriminate here and have to fall back to the generic
270 handling (which is suboptimal). */
271 #if !defined(GFC_REAL_16_IS_FLOAT128)
272 # ifdef HAVE_GFC_REAL_10
273 case GFC_DTYPE_REAL_10
:
274 unpack1_r10 ((gfc_array_r10
*) ret
, (gfc_array_r10
*) vector
,
275 mask
, (gfc_array_r10
*) field
);
279 # ifdef HAVE_GFC_REAL_16
280 case GFC_DTYPE_REAL_16
:
281 unpack1_r16 ((gfc_array_r16
*) ret
, (gfc_array_r16
*) vector
,
282 mask
, (gfc_array_r16
*) field
);
287 case GFC_DTYPE_COMPLEX_4
:
288 unpack1_c4 ((gfc_array_c4
*) ret
, (gfc_array_c4
*) vector
,
289 mask
, (gfc_array_c4
*) field
);
292 case GFC_DTYPE_COMPLEX_8
:
293 unpack1_c8 ((gfc_array_c8
*) ret
, (gfc_array_c8
*) vector
,
294 mask
, (gfc_array_c8
*) field
);
297 /* FIXME: This here is a hack, which will have to be removed when
298 the array descriptor is reworked. Currently, we don't store the
299 kind value for the type, but only the size. Because on targets with
300 __float128, we have sizeof(logn double) == sizeof(__float128),
301 we cannot discriminate here and have to fall back to the generic
302 handling (which is suboptimal). */
303 #if !defined(GFC_REAL_16_IS_FLOAT128)
304 # ifdef HAVE_GFC_COMPLEX_10
305 case GFC_DTYPE_COMPLEX_10
:
306 unpack1_c10 ((gfc_array_c10
*) ret
, (gfc_array_c10
*) vector
,
307 mask
, (gfc_array_c10
*) field
);
311 # ifdef HAVE_GFC_COMPLEX_16
312 case GFC_DTYPE_COMPLEX_16
:
313 unpack1_c16 ((gfc_array_c16
*) ret
, (gfc_array_c16
*) vector
,
314 mask
, (gfc_array_c16
*) field
);
321 switch (GFC_DESCRIPTOR_SIZE(ret
))
324 unpack1_i1 ((gfc_array_i1
*) ret
, (gfc_array_i1
*) vector
,
325 mask
, (gfc_array_i1
*) field
);
329 if (GFC_UNALIGNED_2(ret
->base_addr
) || GFC_UNALIGNED_2(vector
->base_addr
)
330 || GFC_UNALIGNED_2(field
->base_addr
))
334 unpack1_i2 ((gfc_array_i2
*) ret
, (gfc_array_i2
*) vector
,
335 mask
, (gfc_array_i2
*) field
);
340 if (GFC_UNALIGNED_4(ret
->base_addr
) || GFC_UNALIGNED_4(vector
->base_addr
)
341 || GFC_UNALIGNED_4(field
->base_addr
))
345 unpack1_i4 ((gfc_array_i4
*) ret
, (gfc_array_i4
*) vector
,
346 mask
, (gfc_array_i4
*) field
);
351 if (GFC_UNALIGNED_8(ret
->base_addr
) || GFC_UNALIGNED_8(vector
->base_addr
)
352 || GFC_UNALIGNED_8(field
->base_addr
))
356 unpack1_i8 ((gfc_array_i8
*) ret
, (gfc_array_i8
*) vector
,
357 mask
, (gfc_array_i8
*) field
);
361 #ifdef HAVE_GFC_INTEGER_16
363 if (GFC_UNALIGNED_16(ret
->base_addr
)
364 || GFC_UNALIGNED_16(vector
->base_addr
)
365 || GFC_UNALIGNED_16(field
->base_addr
))
369 unpack1_i16 ((gfc_array_i16
*) ret
, (gfc_array_i16
*) vector
,
370 mask
, (gfc_array_i16
*) field
);
378 unpack_internal (ret
, vector
, mask
, field
, size
);
382 extern void unpack1_char (gfc_array_char
*, GFC_INTEGER_4
,
383 const gfc_array_char
*, const gfc_array_l1
*,
384 const gfc_array_char
*, GFC_INTEGER_4
,
386 export_proto(unpack1_char
);
389 unpack1_char (gfc_array_char
*ret
,
390 GFC_INTEGER_4 ret_length
__attribute__((unused
)),
391 const gfc_array_char
*vector
, const gfc_array_l1
*mask
,
392 const gfc_array_char
*field
, GFC_INTEGER_4 vector_length
,
393 GFC_INTEGER_4 field_length
__attribute__((unused
)))
396 if (unlikely(compile_options
.bounds_check
))
397 unpack_bounds (ret
, vector
, mask
, field
);
399 unpack_internal (ret
, vector
, mask
, field
, vector_length
);
403 extern void unpack1_char4 (gfc_array_char
*, GFC_INTEGER_4
,
404 const gfc_array_char
*, const gfc_array_l1
*,
405 const gfc_array_char
*, GFC_INTEGER_4
,
407 export_proto(unpack1_char4
);
410 unpack1_char4 (gfc_array_char
*ret
,
411 GFC_INTEGER_4 ret_length
__attribute__((unused
)),
412 const gfc_array_char
*vector
, const gfc_array_l1
*mask
,
413 const gfc_array_char
*field
, GFC_INTEGER_4 vector_length
,
414 GFC_INTEGER_4 field_length
__attribute__((unused
)))
417 if (unlikely(compile_options
.bounds_check
))
418 unpack_bounds (ret
, vector
, mask
, field
);
420 unpack_internal (ret
, vector
, mask
, field
,
421 vector_length
* sizeof (gfc_char4_t
));
425 extern void unpack0 (gfc_array_char
*, const gfc_array_char
*,
426 const gfc_array_l1
*, char *);
427 export_proto(unpack0
);
430 unpack0 (gfc_array_char
*ret
, const gfc_array_char
*vector
,
431 const gfc_array_l1
*mask
, char *field
)
435 index_type type_size
;
437 if (unlikely(compile_options
.bounds_check
))
438 unpack_bounds (ret
, vector
, mask
, NULL
);
440 type_size
= GFC_DTYPE_TYPE_SIZE (vector
);
444 case GFC_DTYPE_LOGICAL_1
:
445 case GFC_DTYPE_INTEGER_1
:
446 unpack0_i1 ((gfc_array_i1
*) ret
, (gfc_array_i1
*) vector
,
447 mask
, (GFC_INTEGER_1
*) field
);
450 case GFC_DTYPE_LOGICAL_2
:
451 case GFC_DTYPE_INTEGER_2
:
452 unpack0_i2 ((gfc_array_i2
*) ret
, (gfc_array_i2
*) vector
,
453 mask
, (GFC_INTEGER_2
*) field
);
456 case GFC_DTYPE_LOGICAL_4
:
457 case GFC_DTYPE_INTEGER_4
:
458 unpack0_i4 ((gfc_array_i4
*) ret
, (gfc_array_i4
*) vector
,
459 mask
, (GFC_INTEGER_4
*) field
);
462 case GFC_DTYPE_LOGICAL_8
:
463 case GFC_DTYPE_INTEGER_8
:
464 unpack0_i8 ((gfc_array_i8
*) ret
, (gfc_array_i8
*) vector
,
465 mask
, (GFC_INTEGER_8
*) field
);
468 #ifdef HAVE_GFC_INTEGER_16
469 case GFC_DTYPE_LOGICAL_16
:
470 case GFC_DTYPE_INTEGER_16
:
471 unpack0_i16 ((gfc_array_i16
*) ret
, (gfc_array_i16
*) vector
,
472 mask
, (GFC_INTEGER_16
*) field
);
476 case GFC_DTYPE_REAL_4
:
477 unpack0_r4 ((gfc_array_r4
*) ret
, (gfc_array_r4
*) vector
,
478 mask
, (GFC_REAL_4
*) field
);
481 case GFC_DTYPE_REAL_8
:
482 unpack0_r8 ((gfc_array_r8
*) ret
, (gfc_array_r8
*) vector
,
483 mask
, (GFC_REAL_8
*) field
);
486 /* FIXME: This here is a hack, which will have to be removed when
487 the array descriptor is reworked. Currently, we don't store the
488 kind value for the type, but only the size. Because on targets with
489 __float128, we have sizeof(logn double) == sizeof(__float128),
490 we cannot discriminate here and have to fall back to the generic
491 handling (which is suboptimal). */
492 #if !defined(GFC_REAL_16_IS_FLOAT128)
493 # ifdef HAVE_GFC_REAL_10
494 case GFC_DTYPE_REAL_10
:
495 unpack0_r10 ((gfc_array_r10
*) ret
, (gfc_array_r10
*) vector
,
496 mask
, (GFC_REAL_10
*) field
);
500 # ifdef HAVE_GFC_REAL_16
501 case GFC_DTYPE_REAL_16
:
502 unpack0_r16 ((gfc_array_r16
*) ret
, (gfc_array_r16
*) vector
,
503 mask
, (GFC_REAL_16
*) field
);
508 case GFC_DTYPE_COMPLEX_4
:
509 unpack0_c4 ((gfc_array_c4
*) ret
, (gfc_array_c4
*) vector
,
510 mask
, (GFC_COMPLEX_4
*) field
);
513 case GFC_DTYPE_COMPLEX_8
:
514 unpack0_c8 ((gfc_array_c8
*) ret
, (gfc_array_c8
*) vector
,
515 mask
, (GFC_COMPLEX_8
*) field
);
518 /* FIXME: This here is a hack, which will have to be removed when
519 the array descriptor is reworked. Currently, we don't store the
520 kind value for the type, but only the size. Because on targets with
521 __float128, we have sizeof(logn double) == sizeof(__float128),
522 we cannot discriminate here and have to fall back to the generic
523 handling (which is suboptimal). */
524 #if !defined(GFC_REAL_16_IS_FLOAT128)
525 # ifdef HAVE_GFC_COMPLEX_10
526 case GFC_DTYPE_COMPLEX_10
:
527 unpack0_c10 ((gfc_array_c10
*) ret
, (gfc_array_c10
*) vector
,
528 mask
, (GFC_COMPLEX_10
*) field
);
532 # ifdef HAVE_GFC_COMPLEX_16
533 case GFC_DTYPE_COMPLEX_16
:
534 unpack0_c16 ((gfc_array_c16
*) ret
, (gfc_array_c16
*) vector
,
535 mask
, (GFC_COMPLEX_16
*) field
);
542 switch (GFC_DESCRIPTOR_SIZE(ret
))
545 unpack0_i1 ((gfc_array_i1
*) ret
, (gfc_array_i1
*) vector
,
546 mask
, (GFC_INTEGER_1
*) field
);
550 if (GFC_UNALIGNED_2(ret
->base_addr
) || GFC_UNALIGNED_2(vector
->base_addr
)
551 || GFC_UNALIGNED_2(field
))
555 unpack0_i2 ((gfc_array_i2
*) ret
, (gfc_array_i2
*) vector
,
556 mask
, (GFC_INTEGER_2
*) field
);
561 if (GFC_UNALIGNED_4(ret
->base_addr
) || GFC_UNALIGNED_4(vector
->base_addr
)
562 || GFC_UNALIGNED_4(field
))
566 unpack0_i4 ((gfc_array_i4
*) ret
, (gfc_array_i4
*) vector
,
567 mask
, (GFC_INTEGER_4
*) field
);
572 if (GFC_UNALIGNED_8(ret
->base_addr
) || GFC_UNALIGNED_8(vector
->base_addr
)
573 || GFC_UNALIGNED_8(field
))
577 unpack0_i8 ((gfc_array_i8
*) ret
, (gfc_array_i8
*) vector
,
578 mask
, (GFC_INTEGER_8
*) field
);
582 #ifdef HAVE_GFC_INTEGER_16
584 if (GFC_UNALIGNED_16(ret
->base_addr
)
585 || GFC_UNALIGNED_16(vector
->base_addr
)
586 || GFC_UNALIGNED_16(field
))
590 unpack0_i16 ((gfc_array_i16
*) ret
, (gfc_array_i16
*) vector
,
591 mask
, (GFC_INTEGER_16
*) field
);
597 memset (&tmp
, 0, sizeof (tmp
));
598 GFC_DTYPE_CLEAR(&tmp
);
599 tmp
.base_addr
= field
;
600 unpack_internal (ret
, vector
, mask
, &tmp
, GFC_DESCRIPTOR_SIZE (vector
));
604 extern void unpack0_char (gfc_array_char
*, GFC_INTEGER_4
,
605 const gfc_array_char
*, const gfc_array_l1
*,
606 char *, GFC_INTEGER_4
, GFC_INTEGER_4
);
607 export_proto(unpack0_char
);
610 unpack0_char (gfc_array_char
*ret
,
611 GFC_INTEGER_4 ret_length
__attribute__((unused
)),
612 const gfc_array_char
*vector
, const gfc_array_l1
*mask
,
613 char *field
, GFC_INTEGER_4 vector_length
,
614 GFC_INTEGER_4 field_length
__attribute__((unused
)))
618 if (unlikely(compile_options
.bounds_check
))
619 unpack_bounds (ret
, vector
, mask
, NULL
);
621 memset (&tmp
, 0, sizeof (tmp
));
622 GFC_DTYPE_CLEAR(&tmp
);
623 tmp
.base_addr
= field
;
624 unpack_internal (ret
, vector
, mask
, &tmp
, vector_length
);
628 extern void unpack0_char4 (gfc_array_char
*, GFC_INTEGER_4
,
629 const gfc_array_char
*, const gfc_array_l1
*,
630 char *, GFC_INTEGER_4
, GFC_INTEGER_4
);
631 export_proto(unpack0_char4
);
634 unpack0_char4 (gfc_array_char
*ret
,
635 GFC_INTEGER_4 ret_length
__attribute__((unused
)),
636 const gfc_array_char
*vector
, const gfc_array_l1
*mask
,
637 char *field
, GFC_INTEGER_4 vector_length
,
638 GFC_INTEGER_4 field_length
__attribute__((unused
)))
642 if (unlikely(compile_options
.bounds_check
))
643 unpack_bounds (ret
, vector
, mask
, NULL
);
645 memset (&tmp
, 0, sizeof (tmp
));
646 GFC_DTYPE_CLEAR(&tmp
);
647 tmp
.base_addr
= field
;
648 unpack_internal (ret
, vector
, mask
, &tmp
,
649 vector_length
* sizeof (gfc_char4_t
));