1 /* Single-image implementation of GNU Fortran Coarray Library
2 Copyright (C) 2011-2017 Free Software Foundation, Inc.
3 Contributed by Tobias Burnus <burnus@net-b.de>
5 This file is part of the GNU Fortran Coarray Runtime Library (libcaf).
7 Libcaf is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3, or (at your option)
12 Libcaf 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/>. */
27 #include <stdio.h> /* For fputs and fprintf. */
28 #include <stdlib.h> /* For exit and malloc. */
29 #include <string.h> /* For memcpy and memset. */
30 #include <stdarg.h> /* For variadic arguments. */
33 /* Define GFC_CAF_CHECK to enable run-time checking. */
34 /* #define GFC_CAF_CHECK 1 */
36 struct caf_single_token
38 /* The pointer to the memory registered. For arrays this is the data member
39 in the descriptor. For components it's the pure data pointer. */
41 /* The descriptor when this token is associated to an allocatable array. */
42 gfc_descriptor_t
*desc
;
43 /* Set when the caf lib has allocated the memory in memptr and is responsible
44 for freeing it on deregister. */
47 typedef struct caf_single_token
*caf_single_token_t
;
49 #define TOKEN(X) ((caf_single_token_t) (X))
50 #define MEMTOK(X) ((caf_single_token_t) (X))->memptr
52 /* Single-image implementation of the CAF library.
53 Note: For performance reasons -fcoarry=single should be used
54 rather than this library. */
56 /* Global variables. */
57 caf_static_t
*caf_static_list
= NULL
;
59 /* Keep in sync with mpi.c. */
61 caf_runtime_error (const char *message
, ...)
64 fprintf (stderr
, "Fortran runtime error: ");
65 va_start (ap
, message
);
66 vfprintf (stderr
, message
, ap
);
68 fprintf (stderr
, "\n");
70 /* FIXME: Shutdown the Fortran RTL to flush the buffer. PR 43849. */
74 /* Error handling is similar everytime. */
76 caf_internal_error (const char *msg
, int *stat
, char *errmsg
,
80 va_start (args
, errmsg_len
);
86 size_t len
= snprintf (errmsg
, errmsg_len
, msg
, args
);
87 if ((size_t)errmsg_len
> len
)
88 memset (&errmsg
[len
], ' ', errmsg_len
- len
);
94 caf_runtime_error (msg
, args
);
100 _gfortran_caf_init (int *argc
__attribute__ ((unused
)),
101 char ***argv
__attribute__ ((unused
)))
107 _gfortran_caf_finalize (void)
109 while (caf_static_list
!= NULL
)
111 caf_static_t
*tmp
= caf_static_list
->prev
;
112 free (caf_static_list
->token
);
113 free (caf_static_list
);
114 caf_static_list
= tmp
;
120 _gfortran_caf_this_image (int distance
__attribute__ ((unused
)))
127 _gfortran_caf_num_images (int distance
__attribute__ ((unused
)),
128 int failed
__attribute__ ((unused
)))
135 _gfortran_caf_register (size_t size
, caf_register_t type
, caf_token_t
*token
,
136 gfc_descriptor_t
*data
, int *stat
, char *errmsg
,
139 const char alloc_fail_msg
[] = "Failed to allocate coarray";
141 caf_single_token_t single_token
;
143 if (type
== CAF_REGTYPE_LOCK_STATIC
|| type
== CAF_REGTYPE_LOCK_ALLOC
144 || type
== CAF_REGTYPE_CRITICAL
)
145 local
= calloc (size
, sizeof (bool));
146 else if (type
== CAF_REGTYPE_EVENT_STATIC
|| type
== CAF_REGTYPE_EVENT_ALLOC
)
147 /* In the event_(wait|post) function the counter for events is a uint32,
148 so better allocate enough memory here. */
149 local
= calloc (size
, sizeof (uint32_t));
150 else if (type
== CAF_REGTYPE_COARRAY_ALLOC_REGISTER_ONLY
)
153 local
= malloc (size
);
155 if (type
!= CAF_REGTYPE_COARRAY_ALLOC_ALLOCATE_ONLY
)
156 *token
= malloc (sizeof (struct caf_single_token
));
158 if (unlikely (*token
== NULL
160 && type
!= CAF_REGTYPE_COARRAY_ALLOC_REGISTER_ONLY
)))
162 /* Freeing the memory conditionally seems pointless, but
163 caf_internal_error () may return, when a stat is given and then the
164 memory may be lost. */
169 caf_internal_error (alloc_fail_msg
, stat
, errmsg
, errmsg_len
);
173 single_token
= TOKEN (*token
);
174 single_token
->memptr
= local
;
175 single_token
->owning_memory
= type
!= CAF_REGTYPE_COARRAY_ALLOC_REGISTER_ONLY
;
176 single_token
->desc
= GFC_DESCRIPTOR_RANK (data
) > 0 ? data
: NULL
;
182 if (type
== CAF_REGTYPE_COARRAY_STATIC
|| type
== CAF_REGTYPE_LOCK_STATIC
183 || type
== CAF_REGTYPE_CRITICAL
|| type
== CAF_REGTYPE_EVENT_STATIC
184 || type
== CAF_REGTYPE_EVENT_ALLOC
)
186 caf_static_t
*tmp
= malloc (sizeof (caf_static_t
));
187 tmp
->prev
= caf_static_list
;
189 caf_static_list
= tmp
;
191 GFC_DESCRIPTOR_DATA (data
) = local
;
196 _gfortran_caf_deregister (caf_token_t
*token
, caf_deregister_t type
, int *stat
,
197 char *errmsg
__attribute__ ((unused
)),
198 int errmsg_len
__attribute__ ((unused
)))
200 caf_single_token_t single_token
= TOKEN (*token
);
202 if (single_token
->owning_memory
&& single_token
->memptr
)
203 free (single_token
->memptr
);
205 if (type
!= CAF_DEREGTYPE_COARRAY_DEALLOCATE_ONLY
)
207 free (TOKEN (*token
));
212 single_token
->memptr
= NULL
;
213 single_token
->owning_memory
= false;
222 _gfortran_caf_sync_all (int *stat
,
223 char *errmsg
__attribute__ ((unused
)),
224 int errmsg_len
__attribute__ ((unused
)))
226 __asm__
__volatile__ ("":::"memory");
233 _gfortran_caf_sync_memory (int *stat
,
234 char *errmsg
__attribute__ ((unused
)),
235 int errmsg_len
__attribute__ ((unused
)))
237 __asm__
__volatile__ ("":::"memory");
244 _gfortran_caf_sync_images (int count
__attribute__ ((unused
)),
245 int images
[] __attribute__ ((unused
)),
247 char *errmsg
__attribute__ ((unused
)),
248 int errmsg_len
__attribute__ ((unused
)))
253 for (i
= 0; i
< count
; i
++)
256 fprintf (stderr
, "COARRAY ERROR: Invalid image index %d to SYNC "
257 "IMAGES", images
[i
]);
262 __asm__
__volatile__ ("":::"memory");
269 _gfortran_caf_stop_numeric(int32_t stop_code
)
271 fprintf (stderr
, "STOP %d\n", stop_code
);
277 _gfortran_caf_stop_str(const char *string
, int32_t len
)
279 fputs ("STOP ", stderr
);
281 fputc (*(string
++), stderr
);
282 fputs ("\n", stderr
);
289 _gfortran_caf_error_stop_str (const char *string
, int32_t len
)
291 fputs ("ERROR STOP ", stderr
);
293 fputc (*(string
++), stderr
);
294 fputs ("\n", stderr
);
300 /* Reported that the program terminated because of a fail image issued.
301 Because this is a single image library, nothing else than aborting the whole
302 program can be done. */
304 void _gfortran_caf_fail_image (void)
306 fputs ("IMAGE FAILED!\n", stderr
);
311 /* Get the status of image IMAGE. Because being the single image library all
312 other images are reported to be stopped. */
314 int _gfortran_caf_image_status (int image
,
315 caf_team_t
* team
__attribute__ ((unused
)))
320 return CAF_STAT_STOPPED_IMAGE
;
324 /* Single image library. There can not be any failed images with only one
328 _gfortran_caf_failed_images (gfc_descriptor_t
*array
,
329 caf_team_t
* team
__attribute__ ((unused
)),
332 int local_kind
= kind
!= NULL
? *kind
: 4;
334 array
->base_addr
= NULL
;
335 array
->dtype
= ((BT_INTEGER
<< GFC_DTYPE_TYPE_SHIFT
)
336 | (local_kind
<< GFC_DTYPE_SIZE_SHIFT
));
337 /* Setting lower_bound higher then upper_bound is what the compiler does to
338 indicate an empty array. */
339 array
->dim
[0].lower_bound
= 0;
340 array
->dim
[0]._ubound
= -1;
341 array
->dim
[0]._stride
= 1;
346 /* With only one image available no other images can be stopped. Therefore
347 return an empty array. */
350 _gfortran_caf_stopped_images (gfc_descriptor_t
*array
,
351 caf_team_t
* team
__attribute__ ((unused
)),
354 int local_kind
= kind
!= NULL
? *kind
: 4;
356 array
->base_addr
= NULL
;
357 array
->dtype
= ((BT_INTEGER
<< GFC_DTYPE_TYPE_SHIFT
)
358 | (local_kind
<< GFC_DTYPE_SIZE_SHIFT
));
359 /* Setting lower_bound higher then upper_bound is what the compiler does to
360 indicate an empty array. */
361 array
->dim
[0].lower_bound
= 0;
362 array
->dim
[0]._ubound
= -1;
363 array
->dim
[0]._stride
= 1;
369 _gfortran_caf_error_stop (int32_t error
)
371 fprintf (stderr
, "ERROR STOP %d\n", error
);
377 _gfortran_caf_co_broadcast (gfc_descriptor_t
*a
__attribute__ ((unused
)),
378 int source_image
__attribute__ ((unused
)),
379 int *stat
, char *errmsg
__attribute__ ((unused
)),
380 int errmsg_len
__attribute__ ((unused
)))
387 _gfortran_caf_co_sum (gfc_descriptor_t
*a
__attribute__ ((unused
)),
388 int result_image
__attribute__ ((unused
)),
389 int *stat
, char *errmsg
__attribute__ ((unused
)),
390 int errmsg_len
__attribute__ ((unused
)))
397 _gfortran_caf_co_min (gfc_descriptor_t
*a
__attribute__ ((unused
)),
398 int result_image
__attribute__ ((unused
)),
399 int *stat
, char *errmsg
__attribute__ ((unused
)),
400 int a_len
__attribute__ ((unused
)),
401 int errmsg_len
__attribute__ ((unused
)))
408 _gfortran_caf_co_max (gfc_descriptor_t
*a
__attribute__ ((unused
)),
409 int result_image
__attribute__ ((unused
)),
410 int *stat
, char *errmsg
__attribute__ ((unused
)),
411 int a_len
__attribute__ ((unused
)),
412 int errmsg_len
__attribute__ ((unused
)))
420 _gfortran_caf_co_reduce (gfc_descriptor_t
*a
__attribute__ ((unused
)),
421 void * (*opr
) (void *, void *)
422 __attribute__ ((unused
)),
423 int opr_flags
__attribute__ ((unused
)),
424 int result_image
__attribute__ ((unused
)),
425 int *stat
, char *errmsg
__attribute__ ((unused
)),
426 int a_len
__attribute__ ((unused
)),
427 int errmsg_len
__attribute__ ((unused
)))
435 assign_char4_from_char1 (size_t dst_size
, size_t src_size
, uint32_t *dst
,
439 n
= dst_size
/4 > src_size
? src_size
: dst_size
/4;
440 for (i
= 0; i
< n
; ++i
)
441 dst
[i
] = (int32_t) src
[i
];
442 for (; i
< dst_size
/4; ++i
)
443 dst
[i
] = (int32_t) ' ';
448 assign_char1_from_char4 (size_t dst_size
, size_t src_size
, unsigned char *dst
,
452 n
= dst_size
> src_size
/4 ? src_size
/4 : dst_size
;
453 for (i
= 0; i
< n
; ++i
)
454 dst
[i
] = src
[i
] > UINT8_MAX
? (unsigned char) '?' : (unsigned char) src
[i
];
456 memset (&dst
[n
], ' ', dst_size
- n
);
461 convert_type (void *dst
, int dst_type
, int dst_kind
, void *src
, int src_type
,
462 int src_kind
, int *stat
)
464 #ifdef HAVE_GFC_INTEGER_16
465 typedef __int128 int128t
;
467 typedef int64_t int128t
;
470 #if defined(GFC_REAL_16_IS_LONG_DOUBLE)
471 typedef long double real128t
;
472 typedef _Complex
long double complex128t
;
473 #elif defined(HAVE_GFC_REAL_16)
474 typedef _Complex
float __attribute__((mode(TC
))) __complex128
;
475 typedef __float128 real128t
;
476 typedef __complex128 complex128t
;
477 #elif defined(HAVE_GFC_REAL_10)
478 typedef long double real128t
;
479 typedef long double complex128t
;
481 typedef double real128t
;
482 typedef _Complex
double complex128t
;
486 real128t real_val
= 0;
487 complex128t cmpx_val
= 0;
493 int_val
= *(int8_t*) src
;
494 else if (src_kind
== 2)
495 int_val
= *(int16_t*) src
;
496 else if (src_kind
== 4)
497 int_val
= *(int32_t*) src
;
498 else if (src_kind
== 8)
499 int_val
= *(int64_t*) src
;
500 #ifdef HAVE_GFC_INTEGER_16
501 else if (src_kind
== 16)
502 int_val
= *(int128t
*) src
;
509 real_val
= *(float*) src
;
510 else if (src_kind
== 8)
511 real_val
= *(double*) src
;
512 #ifdef HAVE_GFC_REAL_10
513 else if (src_kind
== 10)
514 real_val
= *(long double*) src
;
516 #ifdef HAVE_GFC_REAL_16
517 else if (src_kind
== 16)
518 real_val
= *(real128t
*) src
;
525 cmpx_val
= *(_Complex
float*) src
;
526 else if (src_kind
== 8)
527 cmpx_val
= *(_Complex
double*) src
;
528 #ifdef HAVE_GFC_REAL_10
529 else if (src_kind
== 10)
530 cmpx_val
= *(_Complex
long double*) src
;
532 #ifdef HAVE_GFC_REAL_16
533 else if (src_kind
== 16)
534 cmpx_val
= *(complex128t
*) src
;
546 if (src_type
== BT_INTEGER
)
549 *(int8_t*) dst
= (int8_t) int_val
;
550 else if (dst_kind
== 2)
551 *(int16_t*) dst
= (int16_t) int_val
;
552 else if (dst_kind
== 4)
553 *(int32_t*) dst
= (int32_t) int_val
;
554 else if (dst_kind
== 8)
555 *(int64_t*) dst
= (int64_t) int_val
;
556 #ifdef HAVE_GFC_INTEGER_16
557 else if (dst_kind
== 16)
558 *(int128t
*) dst
= (int128t
) int_val
;
563 else if (src_type
== BT_REAL
)
566 *(int8_t*) dst
= (int8_t) real_val
;
567 else if (dst_kind
== 2)
568 *(int16_t*) dst
= (int16_t) real_val
;
569 else if (dst_kind
== 4)
570 *(int32_t*) dst
= (int32_t) real_val
;
571 else if (dst_kind
== 8)
572 *(int64_t*) dst
= (int64_t) real_val
;
573 #ifdef HAVE_GFC_INTEGER_16
574 else if (dst_kind
== 16)
575 *(int128t
*) dst
= (int128t
) real_val
;
580 else if (src_type
== BT_COMPLEX
)
583 *(int8_t*) dst
= (int8_t) cmpx_val
;
584 else if (dst_kind
== 2)
585 *(int16_t*) dst
= (int16_t) cmpx_val
;
586 else if (dst_kind
== 4)
587 *(int32_t*) dst
= (int32_t) cmpx_val
;
588 else if (dst_kind
== 8)
589 *(int64_t*) dst
= (int64_t) cmpx_val
;
590 #ifdef HAVE_GFC_INTEGER_16
591 else if (dst_kind
== 16)
592 *(int128t
*) dst
= (int128t
) cmpx_val
;
601 if (src_type
== BT_INTEGER
)
604 *(float*) dst
= (float) int_val
;
605 else if (dst_kind
== 8)
606 *(double*) dst
= (double) int_val
;
607 #ifdef HAVE_GFC_REAL_10
608 else if (dst_kind
== 10)
609 *(long double*) dst
= (long double) int_val
;
611 #ifdef HAVE_GFC_REAL_16
612 else if (dst_kind
== 16)
613 *(real128t
*) dst
= (real128t
) int_val
;
618 else if (src_type
== BT_REAL
)
621 *(float*) dst
= (float) real_val
;
622 else if (dst_kind
== 8)
623 *(double*) dst
= (double) real_val
;
624 #ifdef HAVE_GFC_REAL_10
625 else if (dst_kind
== 10)
626 *(long double*) dst
= (long double) real_val
;
628 #ifdef HAVE_GFC_REAL_16
629 else if (dst_kind
== 16)
630 *(real128t
*) dst
= (real128t
) real_val
;
635 else if (src_type
== BT_COMPLEX
)
638 *(float*) dst
= (float) cmpx_val
;
639 else if (dst_kind
== 8)
640 *(double*) dst
= (double) cmpx_val
;
641 #ifdef HAVE_GFC_REAL_10
642 else if (dst_kind
== 10)
643 *(long double*) dst
= (long double) cmpx_val
;
645 #ifdef HAVE_GFC_REAL_16
646 else if (dst_kind
== 16)
647 *(real128t
*) dst
= (real128t
) cmpx_val
;
654 if (src_type
== BT_INTEGER
)
657 *(_Complex
float*) dst
= (_Complex
float) int_val
;
658 else if (dst_kind
== 8)
659 *(_Complex
double*) dst
= (_Complex
double) int_val
;
660 #ifdef HAVE_GFC_REAL_10
661 else if (dst_kind
== 10)
662 *(_Complex
long double*) dst
= (_Complex
long double) int_val
;
664 #ifdef HAVE_GFC_REAL_16
665 else if (dst_kind
== 16)
666 *(complex128t
*) dst
= (complex128t
) int_val
;
671 else if (src_type
== BT_REAL
)
674 *(_Complex
float*) dst
= (_Complex
float) real_val
;
675 else if (dst_kind
== 8)
676 *(_Complex
double*) dst
= (_Complex
double) real_val
;
677 #ifdef HAVE_GFC_REAL_10
678 else if (dst_kind
== 10)
679 *(_Complex
long double*) dst
= (_Complex
long double) real_val
;
681 #ifdef HAVE_GFC_REAL_16
682 else if (dst_kind
== 16)
683 *(complex128t
*) dst
= (complex128t
) real_val
;
688 else if (src_type
== BT_COMPLEX
)
691 *(_Complex
float*) dst
= (_Complex
float) cmpx_val
;
692 else if (dst_kind
== 8)
693 *(_Complex
double*) dst
= (_Complex
double) cmpx_val
;
694 #ifdef HAVE_GFC_REAL_10
695 else if (dst_kind
== 10)
696 *(_Complex
long double*) dst
= (_Complex
long double) cmpx_val
;
698 #ifdef HAVE_GFC_REAL_16
699 else if (dst_kind
== 16)
700 *(complex128t
*) dst
= (complex128t
) cmpx_val
;
713 fprintf (stderr
, "libcaf_single RUNTIME ERROR: Cannot convert type %d kind "
714 "%d to type %d kind %d\n", src_type
, src_kind
, dst_type
, dst_kind
);
723 _gfortran_caf_get (caf_token_t token
, size_t offset
,
724 int image_index
__attribute__ ((unused
)),
725 gfc_descriptor_t
*src
,
726 caf_vector_t
*src_vector
__attribute__ ((unused
)),
727 gfc_descriptor_t
*dest
, int src_kind
, int dst_kind
,
728 bool may_require_tmp
, int *stat
)
730 /* FIXME: Handle vector subscripts. */
733 int rank
= GFC_DESCRIPTOR_RANK (dest
);
734 size_t src_size
= GFC_DESCRIPTOR_SIZE (src
);
735 size_t dst_size
= GFC_DESCRIPTOR_SIZE (dest
);
742 void *sr
= (void *) ((char *) MEMTOK (token
) + offset
);
743 if (GFC_DESCRIPTOR_TYPE (dest
) == GFC_DESCRIPTOR_TYPE (src
)
744 && dst_kind
== src_kind
)
746 memmove (GFC_DESCRIPTOR_DATA (dest
), sr
,
747 dst_size
> src_size
? src_size
: dst_size
);
748 if (GFC_DESCRIPTOR_TYPE (dest
) == BT_CHARACTER
&& dst_size
> src_size
)
751 memset ((void*)(char*) GFC_DESCRIPTOR_DATA (dest
) + src_size
,
752 ' ', dst_size
- src_size
);
753 else /* dst_kind == 4. */
754 for (i
= src_size
/4; i
< dst_size
/4; i
++)
755 ((int32_t*) GFC_DESCRIPTOR_DATA (dest
))[i
] = (int32_t) ' ';
758 else if (GFC_DESCRIPTOR_TYPE (dest
) == BT_CHARACTER
&& dst_kind
== 1)
759 assign_char1_from_char4 (dst_size
, src_size
, GFC_DESCRIPTOR_DATA (dest
),
761 else if (GFC_DESCRIPTOR_TYPE (dest
) == BT_CHARACTER
)
762 assign_char4_from_char1 (dst_size
, src_size
, GFC_DESCRIPTOR_DATA (dest
),
765 convert_type (GFC_DESCRIPTOR_DATA (dest
), GFC_DESCRIPTOR_TYPE (dest
),
766 dst_kind
, sr
, GFC_DESCRIPTOR_TYPE (src
), src_kind
, stat
);
771 for (j
= 0; j
< rank
; j
++)
773 ptrdiff_t dimextent
= dest
->dim
[j
]._ubound
- dest
->dim
[j
].lower_bound
+ 1;
784 ptrdiff_t array_offset_sr
, array_offset_dst
;
785 void *tmp
= malloc (size
*src_size
);
787 array_offset_dst
= 0;
788 for (i
= 0; i
< size
; i
++)
790 ptrdiff_t array_offset_sr
= 0;
791 ptrdiff_t stride
= 1;
792 ptrdiff_t extent
= 1;
793 for (j
= 0; j
< GFC_DESCRIPTOR_RANK (src
)-1; j
++)
795 array_offset_sr
+= ((i
/ (extent
*stride
))
796 % (src
->dim
[j
]._ubound
797 - src
->dim
[j
].lower_bound
+ 1))
798 * src
->dim
[j
]._stride
;
799 extent
= (src
->dim
[j
]._ubound
- src
->dim
[j
].lower_bound
+ 1);
800 stride
= src
->dim
[j
]._stride
;
802 array_offset_sr
+= (i
/ extent
) * src
->dim
[rank
-1]._stride
;
803 void *sr
= (void *)((char *) MEMTOK (token
) + offset
804 + array_offset_sr
*GFC_DESCRIPTOR_SIZE (src
));
805 memcpy ((void *) ((char *) tmp
+ array_offset_dst
), sr
, src_size
);
806 array_offset_dst
+= src_size
;
810 for (i
= 0; i
< size
; i
++)
812 ptrdiff_t array_offset_dst
= 0;
813 ptrdiff_t stride
= 1;
814 ptrdiff_t extent
= 1;
815 for (j
= 0; j
< rank
-1; j
++)
817 array_offset_dst
+= ((i
/ (extent
*stride
))
818 % (dest
->dim
[j
]._ubound
819 - dest
->dim
[j
].lower_bound
+ 1))
820 * dest
->dim
[j
]._stride
;
821 extent
= (dest
->dim
[j
]._ubound
- dest
->dim
[j
].lower_bound
+ 1);
822 stride
= dest
->dim
[j
]._stride
;
824 array_offset_dst
+= (i
/ extent
) * dest
->dim
[rank
-1]._stride
;
825 void *dst
= dest
->base_addr
826 + array_offset_dst
*GFC_DESCRIPTOR_SIZE (dest
);
827 void *sr
= tmp
+ array_offset_sr
;
829 if (GFC_DESCRIPTOR_TYPE (dest
) == GFC_DESCRIPTOR_TYPE (src
)
830 && dst_kind
== src_kind
)
832 memmove (dst
, sr
, dst_size
> src_size
? src_size
: dst_size
);
833 if (GFC_DESCRIPTOR_TYPE (dest
) == BT_CHARACTER
834 && dst_size
> src_size
)
837 memset ((void*)(char*) dst
+ src_size
, ' ',
839 else /* dst_kind == 4. */
840 for (k
= src_size
/4; k
< dst_size
/4; k
++)
841 ((int32_t*) dst
)[k
] = (int32_t) ' ';
844 else if (GFC_DESCRIPTOR_TYPE (dest
) == BT_CHARACTER
&& dst_kind
== 1)
845 assign_char1_from_char4 (dst_size
, src_size
, dst
, sr
);
846 else if (GFC_DESCRIPTOR_TYPE (dest
) == BT_CHARACTER
)
847 assign_char4_from_char1 (dst_size
, src_size
, dst
, sr
);
849 convert_type (dst
, GFC_DESCRIPTOR_TYPE (dest
), dst_kind
,
850 sr
, GFC_DESCRIPTOR_TYPE (src
), src_kind
, stat
);
851 array_offset_sr
+= src_size
;
858 for (i
= 0; i
< size
; i
++)
860 ptrdiff_t array_offset_dst
= 0;
861 ptrdiff_t stride
= 1;
862 ptrdiff_t extent
= 1;
863 for (j
= 0; j
< rank
-1; j
++)
865 array_offset_dst
+= ((i
/ (extent
*stride
))
866 % (dest
->dim
[j
]._ubound
867 - dest
->dim
[j
].lower_bound
+ 1))
868 * dest
->dim
[j
]._stride
;
869 extent
= (dest
->dim
[j
]._ubound
- dest
->dim
[j
].lower_bound
+ 1);
870 stride
= dest
->dim
[j
]._stride
;
872 array_offset_dst
+= (i
/ extent
) * dest
->dim
[rank
-1]._stride
;
873 void *dst
= dest
->base_addr
+ array_offset_dst
*GFC_DESCRIPTOR_SIZE (dest
);
875 ptrdiff_t array_offset_sr
= 0;
878 for (j
= 0; j
< GFC_DESCRIPTOR_RANK (src
)-1; j
++)
880 array_offset_sr
+= ((i
/ (extent
*stride
))
881 % (src
->dim
[j
]._ubound
882 - src
->dim
[j
].lower_bound
+ 1))
883 * src
->dim
[j
]._stride
;
884 extent
= (src
->dim
[j
]._ubound
- src
->dim
[j
].lower_bound
+ 1);
885 stride
= src
->dim
[j
]._stride
;
887 array_offset_sr
+= (i
/ extent
) * src
->dim
[rank
-1]._stride
;
888 void *sr
= (void *)((char *) MEMTOK (token
) + offset
889 + array_offset_sr
*GFC_DESCRIPTOR_SIZE (src
));
891 if (GFC_DESCRIPTOR_TYPE (dest
) == GFC_DESCRIPTOR_TYPE (src
)
892 && dst_kind
== src_kind
)
894 memmove (dst
, sr
, dst_size
> src_size
? src_size
: dst_size
);
895 if (GFC_DESCRIPTOR_TYPE (dest
) == BT_CHARACTER
&& dst_size
> src_size
)
898 memset ((void*)(char*) dst
+ src_size
, ' ', dst_size
-src_size
);
899 else /* dst_kind == 4. */
900 for (k
= src_size
/4; k
< dst_size
/4; k
++)
901 ((int32_t*) dst
)[k
] = (int32_t) ' ';
904 else if (GFC_DESCRIPTOR_TYPE (dest
) == BT_CHARACTER
&& dst_kind
== 1)
905 assign_char1_from_char4 (dst_size
, src_size
, dst
, sr
);
906 else if (GFC_DESCRIPTOR_TYPE (dest
) == BT_CHARACTER
)
907 assign_char4_from_char1 (dst_size
, src_size
, dst
, sr
);
909 convert_type (dst
, GFC_DESCRIPTOR_TYPE (dest
), dst_kind
,
910 sr
, GFC_DESCRIPTOR_TYPE (src
), src_kind
, stat
);
916 _gfortran_caf_send (caf_token_t token
, size_t offset
,
917 int image_index
__attribute__ ((unused
)),
918 gfc_descriptor_t
*dest
,
919 caf_vector_t
*dst_vector
__attribute__ ((unused
)),
920 gfc_descriptor_t
*src
, int dst_kind
, int src_kind
,
921 bool may_require_tmp
, int *stat
)
923 /* FIXME: Handle vector subscripts. */
926 int rank
= GFC_DESCRIPTOR_RANK (dest
);
927 size_t src_size
= GFC_DESCRIPTOR_SIZE (src
);
928 size_t dst_size
= GFC_DESCRIPTOR_SIZE (dest
);
935 void *dst
= (void *) ((char *) MEMTOK (token
) + offset
);
936 if (GFC_DESCRIPTOR_TYPE (dest
) == GFC_DESCRIPTOR_TYPE (src
)
937 && dst_kind
== src_kind
)
939 memmove (dst
, GFC_DESCRIPTOR_DATA (src
),
940 dst_size
> src_size
? src_size
: dst_size
);
941 if (GFC_DESCRIPTOR_TYPE (dest
) == BT_CHARACTER
&& dst_size
> src_size
)
944 memset ((void*)(char*) dst
+ src_size
, ' ', dst_size
-src_size
);
945 else /* dst_kind == 4. */
946 for (i
= src_size
/4; i
< dst_size
/4; i
++)
947 ((int32_t*) dst
)[i
] = (int32_t) ' ';
950 else if (GFC_DESCRIPTOR_TYPE (dest
) == BT_CHARACTER
&& dst_kind
== 1)
951 assign_char1_from_char4 (dst_size
, src_size
, dst
,
952 GFC_DESCRIPTOR_DATA (src
));
953 else if (GFC_DESCRIPTOR_TYPE (dest
) == BT_CHARACTER
)
954 assign_char4_from_char1 (dst_size
, src_size
, dst
,
955 GFC_DESCRIPTOR_DATA (src
));
957 convert_type (dst
, GFC_DESCRIPTOR_TYPE (dest
), dst_kind
,
958 GFC_DESCRIPTOR_DATA (src
), GFC_DESCRIPTOR_TYPE (src
),
964 for (j
= 0; j
< rank
; j
++)
966 ptrdiff_t dimextent
= dest
->dim
[j
]._ubound
- dest
->dim
[j
].lower_bound
+ 1;
977 ptrdiff_t array_offset_sr
, array_offset_dst
;
980 if (GFC_DESCRIPTOR_RANK (src
) == 0)
982 tmp
= malloc (src_size
);
983 memcpy (tmp
, GFC_DESCRIPTOR_DATA (src
), src_size
);
987 tmp
= malloc (size
*src_size
);
988 array_offset_dst
= 0;
989 for (i
= 0; i
< size
; i
++)
991 ptrdiff_t array_offset_sr
= 0;
992 ptrdiff_t stride
= 1;
993 ptrdiff_t extent
= 1;
994 for (j
= 0; j
< GFC_DESCRIPTOR_RANK (src
)-1; j
++)
996 array_offset_sr
+= ((i
/ (extent
*stride
))
997 % (src
->dim
[j
]._ubound
998 - src
->dim
[j
].lower_bound
+ 1))
999 * src
->dim
[j
]._stride
;
1000 extent
= (src
->dim
[j
]._ubound
- src
->dim
[j
].lower_bound
+ 1);
1001 stride
= src
->dim
[j
]._stride
;
1003 array_offset_sr
+= (i
/ extent
) * src
->dim
[rank
-1]._stride
;
1004 void *sr
= (void *) ((char *) src
->base_addr
1005 + array_offset_sr
*GFC_DESCRIPTOR_SIZE (src
));
1006 memcpy ((void *) ((char *) tmp
+ array_offset_dst
), sr
, src_size
);
1007 array_offset_dst
+= src_size
;
1011 array_offset_sr
= 0;
1012 for (i
= 0; i
< size
; i
++)
1014 ptrdiff_t array_offset_dst
= 0;
1015 ptrdiff_t stride
= 1;
1016 ptrdiff_t extent
= 1;
1017 for (j
= 0; j
< rank
-1; j
++)
1019 array_offset_dst
+= ((i
/ (extent
*stride
))
1020 % (dest
->dim
[j
]._ubound
1021 - dest
->dim
[j
].lower_bound
+ 1))
1022 * dest
->dim
[j
]._stride
;
1023 extent
= (dest
->dim
[j
]._ubound
- dest
->dim
[j
].lower_bound
+ 1);
1024 stride
= dest
->dim
[j
]._stride
;
1026 array_offset_dst
+= (i
/ extent
) * dest
->dim
[rank
-1]._stride
;
1027 void *dst
= (void *)((char *) MEMTOK (token
) + offset
1028 + array_offset_dst
*GFC_DESCRIPTOR_SIZE (dest
));
1029 void *sr
= tmp
+ array_offset_sr
;
1030 if (GFC_DESCRIPTOR_TYPE (dest
) == GFC_DESCRIPTOR_TYPE (src
)
1031 && dst_kind
== src_kind
)
1034 dst_size
> src_size
? src_size
: dst_size
);
1035 if (GFC_DESCRIPTOR_TYPE (dest
) == BT_CHARACTER
1036 && dst_size
> src_size
)
1039 memset ((void*)(char*) dst
+ src_size
, ' ',
1041 else /* dst_kind == 4. */
1042 for (k
= src_size
/4; k
< dst_size
/4; k
++)
1043 ((int32_t*) dst
)[k
] = (int32_t) ' ';
1046 else if (GFC_DESCRIPTOR_TYPE (dest
) == BT_CHARACTER
&& dst_kind
== 1)
1047 assign_char1_from_char4 (dst_size
, src_size
, dst
, sr
);
1048 else if (GFC_DESCRIPTOR_TYPE (dest
) == BT_CHARACTER
)
1049 assign_char4_from_char1 (dst_size
, src_size
, dst
, sr
);
1051 convert_type (dst
, GFC_DESCRIPTOR_TYPE (dest
), dst_kind
,
1052 sr
, GFC_DESCRIPTOR_TYPE (src
), src_kind
, stat
);
1053 if (GFC_DESCRIPTOR_RANK (src
))
1054 array_offset_sr
+= src_size
;
1060 for (i
= 0; i
< size
; i
++)
1062 ptrdiff_t array_offset_dst
= 0;
1063 ptrdiff_t stride
= 1;
1064 ptrdiff_t extent
= 1;
1065 for (j
= 0; j
< rank
-1; j
++)
1067 array_offset_dst
+= ((i
/ (extent
*stride
))
1068 % (dest
->dim
[j
]._ubound
1069 - dest
->dim
[j
].lower_bound
+ 1))
1070 * dest
->dim
[j
]._stride
;
1071 extent
= (dest
->dim
[j
]._ubound
- dest
->dim
[j
].lower_bound
+ 1);
1072 stride
= dest
->dim
[j
]._stride
;
1074 array_offset_dst
+= (i
/ extent
) * dest
->dim
[rank
-1]._stride
;
1075 void *dst
= (void *)((char *) MEMTOK (token
) + offset
1076 + array_offset_dst
*GFC_DESCRIPTOR_SIZE (dest
));
1078 if (GFC_DESCRIPTOR_RANK (src
) != 0)
1080 ptrdiff_t array_offset_sr
= 0;
1083 for (j
= 0; j
< GFC_DESCRIPTOR_RANK (src
)-1; j
++)
1085 array_offset_sr
+= ((i
/ (extent
*stride
))
1086 % (src
->dim
[j
]._ubound
1087 - src
->dim
[j
].lower_bound
+ 1))
1088 * src
->dim
[j
]._stride
;
1089 extent
= (src
->dim
[j
]._ubound
- src
->dim
[j
].lower_bound
+ 1);
1090 stride
= src
->dim
[j
]._stride
;
1092 array_offset_sr
+= (i
/ extent
) * src
->dim
[rank
-1]._stride
;
1093 sr
= (void *)((char *) src
->base_addr
1094 + array_offset_sr
*GFC_DESCRIPTOR_SIZE (src
));
1097 sr
= src
->base_addr
;
1099 if (GFC_DESCRIPTOR_TYPE (dest
) == GFC_DESCRIPTOR_TYPE (src
)
1100 && dst_kind
== src_kind
)
1103 dst_size
> src_size
? src_size
: dst_size
);
1104 if (GFC_DESCRIPTOR_TYPE (dest
) == BT_CHARACTER
&& dst_size
> src_size
)
1107 memset ((void*)(char*) dst
+ src_size
, ' ', dst_size
-src_size
);
1108 else /* dst_kind == 4. */
1109 for (k
= src_size
/4; k
< dst_size
/4; k
++)
1110 ((int32_t*) dst
)[k
] = (int32_t) ' ';
1113 else if (GFC_DESCRIPTOR_TYPE (dest
) == BT_CHARACTER
&& dst_kind
== 1)
1114 assign_char1_from_char4 (dst_size
, src_size
, dst
, sr
);
1115 else if (GFC_DESCRIPTOR_TYPE (dest
) == BT_CHARACTER
)
1116 assign_char4_from_char1 (dst_size
, src_size
, dst
, sr
);
1118 convert_type (dst
, GFC_DESCRIPTOR_TYPE (dest
), dst_kind
,
1119 sr
, GFC_DESCRIPTOR_TYPE (src
), src_kind
, stat
);
1125 _gfortran_caf_sendget (caf_token_t dst_token
, size_t dst_offset
,
1126 int dst_image_index
, gfc_descriptor_t
*dest
,
1127 caf_vector_t
*dst_vector
, caf_token_t src_token
,
1129 int src_image_index
__attribute__ ((unused
)),
1130 gfc_descriptor_t
*src
,
1131 caf_vector_t
*src_vector
__attribute__ ((unused
)),
1132 int dst_kind
, int src_kind
, bool may_require_tmp
)
1134 /* FIXME: Handle vector subscript of 'src_vector'. */
1135 /* For a single image, src->base_addr should be the same as src_token + offset
1136 but to play save, we do it properly. */
1137 void *src_base
= GFC_DESCRIPTOR_DATA (src
);
1138 GFC_DESCRIPTOR_DATA (src
) = (void *) ((char *) MEMTOK (src_token
)
1140 _gfortran_caf_send (dst_token
, dst_offset
, dst_image_index
, dest
, dst_vector
,
1141 src
, dst_kind
, src_kind
, may_require_tmp
, NULL
);
1142 GFC_DESCRIPTOR_DATA (src
) = src_base
;
1146 /* Emitted when a theorectically unreachable part is reached. */
1147 const char unreachable
[] = "Fatal error: unreachable alternative found.\n";
1151 copy_data (void *ds
, void *sr
, int dst_type
, int src_type
,
1152 int dst_kind
, int src_kind
, size_t dst_size
, size_t src_size
,
1153 size_t num
, int *stat
)
1156 if (dst_type
== src_type
&& dst_kind
== src_kind
)
1158 memmove (ds
, sr
, (dst_size
> src_size
? src_size
: dst_size
) * num
);
1159 if ((dst_type
== BT_CHARACTER
|| src_type
== BT_CHARACTER
)
1160 && dst_size
> src_size
)
1163 memset ((void*)(char*) ds
+ src_size
, ' ', dst_size
-src_size
);
1164 else /* dst_kind == 4. */
1165 for (k
= src_size
/4; k
< dst_size
/4; k
++)
1166 ((int32_t*) ds
)[k
] = (int32_t) ' ';
1169 else if (dst_type
== BT_CHARACTER
&& dst_kind
== 1)
1170 assign_char1_from_char4 (dst_size
, src_size
, ds
, sr
);
1171 else if (dst_type
== BT_CHARACTER
)
1172 assign_char4_from_char1 (dst_size
, src_size
, ds
, sr
);
1174 for (k
= 0; k
< num
; ++k
)
1176 convert_type (ds
, dst_type
, dst_kind
, sr
, src_type
, src_kind
, stat
);
1183 #define COMPUTE_NUM_ITEMS(num, stride, lb, ub) \
1185 index_type abs_stride = (stride) > 0 ? (stride) : -(stride); \
1186 num = (stride) > 0 ? (ub) + 1 - (lb) : (lb) + 1 - (ub); \
1187 if (num <= 0 || abs_stride < 1) return; \
1188 num = (abs_stride > 1) ? (1 + (num - 1) / abs_stride) : num; \
1193 get_for_ref (caf_reference_t
*ref
, size_t *i
, size_t *dst_index
,
1194 caf_single_token_t single_token
, gfc_descriptor_t
*dst
,
1195 gfc_descriptor_t
*src
, void *ds
, void *sr
,
1196 int dst_kind
, int src_kind
, size_t dst_dim
, size_t src_dim
,
1197 size_t num
, int *stat
)
1199 ptrdiff_t extent_src
= 1, array_offset_src
= 0, stride_src
;
1200 size_t next_dst_dim
;
1202 if (unlikely (ref
== NULL
))
1203 /* May be we should issue an error here, because this case should not
1207 if (ref
->next
== NULL
)
1209 size_t dst_size
= GFC_DESCRIPTOR_SIZE (dst
);
1210 ptrdiff_t array_offset_dst
= 0;;
1211 size_t dst_rank
= GFC_DESCRIPTOR_RANK (dst
);
1216 case CAF_REF_COMPONENT
:
1217 /* Because the token is always registered after the component, its
1218 offset is always greater zeor. */
1219 if (ref
->u
.c
.caf_token_offset
> 0)
1220 copy_data (ds
, *(void **)(sr
+ ref
->u
.c
.offset
),
1221 GFC_DESCRIPTOR_TYPE (dst
), GFC_DESCRIPTOR_TYPE (dst
),
1222 dst_kind
, src_kind
, dst_size
, ref
->item_size
, 1, stat
);
1224 copy_data (ds
, sr
+ ref
->u
.c
.offset
,
1225 GFC_DESCRIPTOR_TYPE (dst
), GFC_DESCRIPTOR_TYPE (src
),
1226 dst_kind
, src_kind
, dst_size
, ref
->item_size
, 1, stat
);
1229 case CAF_REF_STATIC_ARRAY
:
1230 src_type
= ref
->u
.a
.static_array_type
;
1231 /* Intentionally fall through. */
1233 if (ref
->u
.a
.mode
[src_dim
] == CAF_ARR_REF_NONE
)
1235 for (size_t d
= 0; d
< dst_rank
; ++d
)
1236 array_offset_dst
+= dst_index
[d
];
1237 copy_data (ds
+ array_offset_dst
* dst_size
, sr
,
1238 GFC_DESCRIPTOR_TYPE (dst
),
1239 src_type
== -1 ? GFC_DESCRIPTOR_TYPE (src
) : src_type
,
1240 dst_kind
, src_kind
, dst_size
, ref
->item_size
, num
,
1247 caf_runtime_error (unreachable
);
1253 case CAF_REF_COMPONENT
:
1254 if (ref
->u
.c
.caf_token_offset
> 0)
1255 get_for_ref (ref
->next
, i
, dst_index
,
1256 *(caf_single_token_t
*)(sr
+ ref
->u
.c
.caf_token_offset
), dst
,
1257 (*(caf_single_token_t
*)(sr
+ ref
->u
.c
.caf_token_offset
))->desc
,
1258 ds
, sr
+ ref
->u
.c
.offset
, dst_kind
, src_kind
, dst_dim
, 0,
1261 get_for_ref (ref
->next
, i
, dst_index
, single_token
, dst
,
1262 (gfc_descriptor_t
*)(sr
+ ref
->u
.c
.offset
), ds
,
1263 sr
+ ref
->u
.c
.offset
, dst_kind
, src_kind
, dst_dim
, 0, 1,
1267 if (ref
->u
.a
.mode
[src_dim
] == CAF_ARR_REF_NONE
)
1269 get_for_ref (ref
->next
, i
, dst_index
, single_token
, dst
,
1270 src
, ds
, sr
, dst_kind
, src_kind
,
1271 dst_dim
, 0, 1, stat
);
1274 /* Only when on the left most index switch the data pointer to
1275 the array's data pointer. */
1277 sr
= GFC_DESCRIPTOR_DATA (src
);
1278 switch (ref
->u
.a
.mode
[src_dim
])
1280 case CAF_ARR_REF_VECTOR
:
1281 extent_src
= GFC_DIMENSION_EXTENT (src
->dim
[src_dim
]);
1282 array_offset_src
= 0;
1283 dst_index
[dst_dim
] = 0;
1284 for (size_t idx
= 0; idx
< ref
->u
.a
.dim
[src_dim
].v
.nvec
;
1287 #define KINDCASE(kind, type) case kind: \
1288 array_offset_src = (((index_type) \
1289 ((type *)ref->u.a.dim[src_dim].v.vector)[idx]) \
1290 - GFC_DIMENSION_LBOUND (src->dim[src_dim])) \
1291 * GFC_DIMENSION_STRIDE (src->dim[src_dim]); \
1294 switch (ref
->u
.a
.dim
[src_dim
].v
.kind
)
1296 KINDCASE (1, GFC_INTEGER_1
);
1297 KINDCASE (2, GFC_INTEGER_2
);
1298 KINDCASE (4, GFC_INTEGER_4
);
1299 #ifdef HAVE_GFC_INTEGER_8
1300 KINDCASE (8, GFC_INTEGER_8
);
1302 #ifdef HAVE_GFC_INTEGER_16
1303 KINDCASE (16, GFC_INTEGER_16
);
1306 caf_runtime_error (unreachable
);
1311 get_for_ref (ref
, i
, dst_index
, single_token
, dst
, src
,
1312 ds
, sr
+ array_offset_src
* ref
->item_size
,
1313 dst_kind
, src_kind
, dst_dim
+ 1, src_dim
+ 1,
1316 += GFC_DIMENSION_STRIDE (dst
->dim
[dst_dim
]);
1319 case CAF_ARR_REF_FULL
:
1320 COMPUTE_NUM_ITEMS (extent_src
,
1321 ref
->u
.a
.dim
[src_dim
].s
.stride
,
1322 GFC_DIMENSION_LBOUND (src
->dim
[src_dim
]),
1323 GFC_DIMENSION_UBOUND (src
->dim
[src_dim
]));
1324 stride_src
= src
->dim
[src_dim
]._stride
1325 * ref
->u
.a
.dim
[src_dim
].s
.stride
;
1326 array_offset_src
= 0;
1327 dst_index
[dst_dim
] = 0;
1328 for (index_type idx
= 0; idx
< extent_src
;
1329 ++idx
, array_offset_src
+= stride_src
)
1331 get_for_ref (ref
, i
, dst_index
, single_token
, dst
, src
,
1332 ds
, sr
+ array_offset_src
* ref
->item_size
,
1333 dst_kind
, src_kind
, dst_dim
+ 1, src_dim
+ 1,
1336 += GFC_DIMENSION_STRIDE (dst
->dim
[dst_dim
]);
1339 case CAF_ARR_REF_RANGE
:
1340 COMPUTE_NUM_ITEMS (extent_src
,
1341 ref
->u
.a
.dim
[src_dim
].s
.stride
,
1342 ref
->u
.a
.dim
[src_dim
].s
.start
,
1343 ref
->u
.a
.dim
[src_dim
].s
.end
);
1344 array_offset_src
= (ref
->u
.a
.dim
[src_dim
].s
.start
1345 - GFC_DIMENSION_LBOUND (src
->dim
[src_dim
]))
1346 * GFC_DIMENSION_STRIDE (src
->dim
[src_dim
]);
1347 stride_src
= GFC_DIMENSION_STRIDE (src
->dim
[src_dim
])
1348 * ref
->u
.a
.dim
[src_dim
].s
.stride
;
1349 dst_index
[dst_dim
] = 0;
1350 /* Increase the dst_dim only, when the src_extent is greater one
1351 or src and dst extent are both one. Don't increase when the scalar
1352 source is not present in the dst. */
1353 next_dst_dim
= extent_src
> 1
1354 || (GFC_DIMENSION_EXTENT (dst
->dim
[dst_dim
]) == 1
1355 && extent_src
== 1) ? (dst_dim
+ 1) : dst_dim
;
1356 for (index_type idx
= 0; idx
< extent_src
; ++idx
)
1358 get_for_ref (ref
, i
, dst_index
, single_token
, dst
, src
,
1359 ds
, sr
+ array_offset_src
* ref
->item_size
,
1360 dst_kind
, src_kind
, next_dst_dim
, src_dim
+ 1,
1363 += GFC_DIMENSION_STRIDE (dst
->dim
[dst_dim
]);
1364 array_offset_src
+= stride_src
;
1367 case CAF_ARR_REF_SINGLE
:
1368 array_offset_src
= (ref
->u
.a
.dim
[src_dim
].s
.start
1369 - src
->dim
[src_dim
].lower_bound
)
1370 * GFC_DIMENSION_STRIDE (src
->dim
[src_dim
]);
1371 dst_index
[dst_dim
] = 0;
1372 get_for_ref (ref
, i
, dst_index
, single_token
, dst
, src
, ds
,
1373 sr
+ array_offset_src
* ref
->item_size
,
1374 dst_kind
, src_kind
, dst_dim
, src_dim
+ 1, 1,
1377 case CAF_ARR_REF_OPEN_END
:
1378 COMPUTE_NUM_ITEMS (extent_src
,
1379 ref
->u
.a
.dim
[src_dim
].s
.stride
,
1380 ref
->u
.a
.dim
[src_dim
].s
.start
,
1381 GFC_DIMENSION_UBOUND (src
->dim
[src_dim
]));
1382 stride_src
= GFC_DIMENSION_STRIDE (src
->dim
[src_dim
])
1383 * ref
->u
.a
.dim
[src_dim
].s
.stride
;
1384 array_offset_src
= (ref
->u
.a
.dim
[src_dim
].s
.start
1385 - GFC_DIMENSION_LBOUND (src
->dim
[src_dim
]))
1386 * GFC_DIMENSION_STRIDE (src
->dim
[src_dim
]);
1387 dst_index
[dst_dim
] = 0;
1388 for (index_type idx
= 0; idx
< extent_src
; ++idx
)
1390 get_for_ref (ref
, i
, dst_index
, single_token
, dst
, src
,
1391 ds
, sr
+ array_offset_src
* ref
->item_size
,
1392 dst_kind
, src_kind
, dst_dim
+ 1, src_dim
+ 1,
1395 += GFC_DIMENSION_STRIDE (dst
->dim
[dst_dim
]);
1396 array_offset_src
+= stride_src
;
1399 case CAF_ARR_REF_OPEN_START
:
1400 COMPUTE_NUM_ITEMS (extent_src
,
1401 ref
->u
.a
.dim
[src_dim
].s
.stride
,
1402 GFC_DIMENSION_LBOUND (src
->dim
[src_dim
]),
1403 ref
->u
.a
.dim
[src_dim
].s
.end
);
1404 stride_src
= GFC_DIMENSION_STRIDE (src
->dim
[src_dim
])
1405 * ref
->u
.a
.dim
[src_dim
].s
.stride
;
1406 array_offset_src
= 0;
1407 dst_index
[dst_dim
] = 0;
1408 for (index_type idx
= 0; idx
< extent_src
; ++idx
)
1410 get_for_ref (ref
, i
, dst_index
, single_token
, dst
, src
,
1411 ds
, sr
+ array_offset_src
* ref
->item_size
,
1412 dst_kind
, src_kind
, dst_dim
+ 1, src_dim
+ 1,
1415 += GFC_DIMENSION_STRIDE (dst
->dim
[dst_dim
]);
1416 array_offset_src
+= stride_src
;
1420 caf_runtime_error (unreachable
);
1423 case CAF_REF_STATIC_ARRAY
:
1424 if (ref
->u
.a
.mode
[src_dim
] == CAF_ARR_REF_NONE
)
1426 get_for_ref (ref
->next
, i
, dst_index
, single_token
, dst
,
1427 NULL
, ds
, sr
, dst_kind
, src_kind
,
1428 dst_dim
, 0, 1, stat
);
1431 switch (ref
->u
.a
.mode
[src_dim
])
1433 case CAF_ARR_REF_VECTOR
:
1434 array_offset_src
= 0;
1435 dst_index
[dst_dim
] = 0;
1436 for (size_t idx
= 0; idx
< ref
->u
.a
.dim
[src_dim
].v
.nvec
;
1439 #define KINDCASE(kind, type) case kind: \
1440 array_offset_src = ((type *)ref->u.a.dim[src_dim].v.vector)[idx]; \
1443 switch (ref
->u
.a
.dim
[src_dim
].v
.kind
)
1445 KINDCASE (1, GFC_INTEGER_1
);
1446 KINDCASE (2, GFC_INTEGER_2
);
1447 KINDCASE (4, GFC_INTEGER_4
);
1448 #ifdef HAVE_GFC_INTEGER_8
1449 KINDCASE (8, GFC_INTEGER_8
);
1451 #ifdef HAVE_GFC_INTEGER_16
1452 KINDCASE (16, GFC_INTEGER_16
);
1455 caf_runtime_error (unreachable
);
1460 get_for_ref (ref
, i
, dst_index
, single_token
, dst
, NULL
,
1461 ds
, sr
+ array_offset_src
* ref
->item_size
,
1462 dst_kind
, src_kind
, dst_dim
+ 1, src_dim
+ 1,
1465 += GFC_DIMENSION_STRIDE (dst
->dim
[dst_dim
]);
1468 case CAF_ARR_REF_FULL
:
1469 dst_index
[dst_dim
] = 0;
1470 for (array_offset_src
= 0 ;
1471 array_offset_src
<= ref
->u
.a
.dim
[src_dim
].s
.end
;
1472 array_offset_src
+= ref
->u
.a
.dim
[src_dim
].s
.stride
)
1474 get_for_ref (ref
, i
, dst_index
, single_token
, dst
, NULL
,
1475 ds
, sr
+ array_offset_src
* ref
->item_size
,
1476 dst_kind
, src_kind
, dst_dim
+ 1, src_dim
+ 1,
1479 += GFC_DIMENSION_STRIDE (dst
->dim
[dst_dim
]);
1482 case CAF_ARR_REF_RANGE
:
1483 COMPUTE_NUM_ITEMS (extent_src
,
1484 ref
->u
.a
.dim
[src_dim
].s
.stride
,
1485 ref
->u
.a
.dim
[src_dim
].s
.start
,
1486 ref
->u
.a
.dim
[src_dim
].s
.end
);
1487 array_offset_src
= ref
->u
.a
.dim
[src_dim
].s
.start
;
1488 dst_index
[dst_dim
] = 0;
1489 for (index_type idx
= 0; idx
< extent_src
; ++idx
)
1491 get_for_ref (ref
, i
, dst_index
, single_token
, dst
, NULL
,
1492 ds
, sr
+ array_offset_src
* ref
->item_size
,
1493 dst_kind
, src_kind
, dst_dim
+ 1, src_dim
+ 1,
1496 += GFC_DIMENSION_STRIDE (dst
->dim
[dst_dim
]);
1497 array_offset_src
+= ref
->u
.a
.dim
[src_dim
].s
.stride
;
1500 case CAF_ARR_REF_SINGLE
:
1501 array_offset_src
= ref
->u
.a
.dim
[src_dim
].s
.start
;
1502 get_for_ref (ref
, i
, dst_index
, single_token
, dst
, NULL
, ds
,
1503 sr
+ array_offset_src
* ref
->item_size
,
1504 dst_kind
, src_kind
, dst_dim
, src_dim
+ 1, 1,
1507 /* The OPEN_* are mapped to a RANGE and therefore can not occur. */
1508 case CAF_ARR_REF_OPEN_END
:
1509 case CAF_ARR_REF_OPEN_START
:
1511 caf_runtime_error (unreachable
);
1515 caf_runtime_error (unreachable
);
1521 _gfortran_caf_get_by_ref (caf_token_t token
,
1522 int image_index
__attribute__ ((unused
)),
1523 gfc_descriptor_t
*dst
, caf_reference_t
*refs
,
1524 int dst_kind
, int src_kind
,
1525 bool may_require_tmp
__attribute__ ((unused
)),
1526 bool dst_reallocatable
, int *stat
)
1528 const char vecrefunknownkind
[] = "libcaf_single::caf_get_by_ref(): "
1529 "unknown kind in vector-ref.\n";
1530 const char unknownreftype
[] = "libcaf_single::caf_get_by_ref(): "
1531 "unknown reference type.\n";
1532 const char unknownarrreftype
[] = "libcaf_single::caf_get_by_ref(): "
1533 "unknown array reference type.\n";
1534 const char rankoutofrange
[] = "libcaf_single::caf_get_by_ref(): "
1535 "rank out of range.\n";
1536 const char extentoutofrange
[] = "libcaf_single::caf_get_by_ref(): "
1537 "extent out of range.\n";
1538 const char cannotallocdst
[] = "libcaf_single::caf_get_by_ref(): "
1539 "can not allocate memory.\n";
1540 const char nonallocextentmismatch
[] = "libcaf_single::caf_get_by_ref(): "
1541 "extent of non-allocatable arrays mismatch (%lu != %lu).\n";
1542 const char doublearrayref
[] = "libcaf_single::caf_get_by_ref(): "
1543 "two or more array part references are not supported.\n";
1545 size_t dst_index
[GFC_MAX_DIMENSIONS
];
1546 int dst_rank
= GFC_DESCRIPTOR_RANK (dst
);
1547 int dst_cur_dim
= 0;
1548 size_t src_size
= 0;
1549 caf_single_token_t single_token
= TOKEN (token
);
1550 void *memptr
= single_token
->memptr
;
1551 gfc_descriptor_t
*src
= single_token
->desc
;
1552 caf_reference_t
*riter
= refs
;
1554 /* Reallocation of dst.data is needed (e.g., array to small). */
1555 bool realloc_needed
;
1556 /* Reallocation of dst.data is required, because data is not alloced at
1558 bool realloc_required
;
1559 bool extent_mismatch
= false;
1560 /* Set when the first non-scalar array reference is encountered. */
1561 bool in_array_ref
= false;
1562 bool array_extent_fixed
= false;
1563 realloc_needed
= realloc_required
= GFC_DESCRIPTOR_DATA (dst
) == NULL
;
1565 assert (!realloc_needed
|| dst_reallocatable
);
1570 /* Compute the size of the result. In the beginning size just counts the
1571 number of elements. */
1575 switch (riter
->type
)
1577 case CAF_REF_COMPONENT
:
1578 if (riter
->u
.c
.caf_token_offset
)
1580 single_token
= *(caf_single_token_t
*)
1581 (memptr
+ riter
->u
.c
.caf_token_offset
);
1582 memptr
= single_token
->memptr
;
1583 src
= single_token
->desc
;
1587 memptr
+= riter
->u
.c
.offset
;
1588 src
= (gfc_descriptor_t
*)memptr
;
1592 for (i
= 0; riter
->u
.a
.mode
[i
] != CAF_ARR_REF_NONE
; ++i
)
1594 switch (riter
->u
.a
.mode
[i
])
1596 case CAF_ARR_REF_VECTOR
:
1597 delta
= riter
->u
.a
.dim
[i
].v
.nvec
;
1598 #define KINDCASE(kind, type) case kind: \
1599 memptr += (((index_type) \
1600 ((type *)riter->u.a.dim[i].v.vector)[0]) \
1601 - GFC_DIMENSION_LBOUND (src->dim[i])) \
1602 * GFC_DIMENSION_STRIDE (src->dim[i]) \
1603 * riter->item_size; \
1606 switch (riter
->u
.a
.dim
[i
].v
.kind
)
1608 KINDCASE (1, GFC_INTEGER_1
);
1609 KINDCASE (2, GFC_INTEGER_2
);
1610 KINDCASE (4, GFC_INTEGER_4
);
1611 #ifdef HAVE_GFC_INTEGER_8
1612 KINDCASE (8, GFC_INTEGER_8
);
1614 #ifdef HAVE_GFC_INTEGER_16
1615 KINDCASE (16, GFC_INTEGER_16
);
1618 caf_internal_error (vecrefunknownkind
, stat
, NULL
, 0);
1623 case CAF_ARR_REF_FULL
:
1624 COMPUTE_NUM_ITEMS (delta
,
1625 riter
->u
.a
.dim
[i
].s
.stride
,
1626 GFC_DIMENSION_LBOUND (src
->dim
[i
]),
1627 GFC_DIMENSION_UBOUND (src
->dim
[i
]));
1628 /* The memptr stays unchanged when ref'ing the first element
1631 case CAF_ARR_REF_RANGE
:
1632 COMPUTE_NUM_ITEMS (delta
,
1633 riter
->u
.a
.dim
[i
].s
.stride
,
1634 riter
->u
.a
.dim
[i
].s
.start
,
1635 riter
->u
.a
.dim
[i
].s
.end
);
1636 memptr
+= (riter
->u
.a
.dim
[i
].s
.start
1637 - GFC_DIMENSION_LBOUND (src
->dim
[i
]))
1638 * GFC_DIMENSION_STRIDE (src
->dim
[i
])
1641 case CAF_ARR_REF_SINGLE
:
1643 memptr
+= (riter
->u
.a
.dim
[i
].s
.start
1644 - GFC_DIMENSION_LBOUND (src
->dim
[i
]))
1645 * GFC_DIMENSION_STRIDE (src
->dim
[i
])
1648 case CAF_ARR_REF_OPEN_END
:
1649 COMPUTE_NUM_ITEMS (delta
,
1650 riter
->u
.a
.dim
[i
].s
.stride
,
1651 riter
->u
.a
.dim
[i
].s
.start
,
1652 GFC_DIMENSION_UBOUND (src
->dim
[i
]));
1653 memptr
+= (riter
->u
.a
.dim
[i
].s
.start
1654 - GFC_DIMENSION_LBOUND (src
->dim
[i
]))
1655 * GFC_DIMENSION_STRIDE (src
->dim
[i
])
1658 case CAF_ARR_REF_OPEN_START
:
1659 COMPUTE_NUM_ITEMS (delta
,
1660 riter
->u
.a
.dim
[i
].s
.stride
,
1661 GFC_DIMENSION_LBOUND (src
->dim
[i
]),
1662 riter
->u
.a
.dim
[i
].s
.end
);
1663 /* The memptr stays unchanged when ref'ing the first element
1667 caf_internal_error (unknownarrreftype
, stat
, NULL
, 0);
1672 /* Check the various properties of the destination array.
1673 Is an array expected and present? */
1674 if (delta
> 1 && dst_rank
== 0)
1676 /* No, an array is required, but not provided. */
1677 caf_internal_error (extentoutofrange
, stat
, NULL
, 0);
1680 /* When dst is an array. */
1683 /* Check that dst_cur_dim is valid for dst. Can be
1684 superceeded only by scalar data. */
1685 if (dst_cur_dim
>= dst_rank
&& delta
!= 1)
1687 caf_internal_error (rankoutofrange
, stat
, NULL
, 0);
1690 /* Do further checks, when the source is not scalar. */
1691 else if (delta
!= 1)
1693 /* Check that the extent is not scalar and we are not in
1694 an array ref for the dst side. */
1697 /* Check that this is the non-scalar extent. */
1698 if (!array_extent_fixed
)
1700 /* In an array extent now. */
1701 in_array_ref
= true;
1702 /* Check that we haven't skipped any scalar
1703 dimensions yet and that the dst is
1706 && dst_rank
== GFC_DESCRIPTOR_RANK (src
))
1708 if (dst_reallocatable
)
1710 /* Dst is reallocatable, which means that
1711 the bounds are not set. Set them. */
1712 for (dst_cur_dim
= 0; dst_cur_dim
< (int)i
;
1714 GFC_DIMENSION_SET (dst
->dim
[dst_cur_dim
],
1720 /* Else press thumbs, that there are enough
1721 dimensional refs to come. Checked below. */
1725 caf_internal_error (doublearrayref
, stat
, NULL
,
1730 /* When the realloc is required, then no extent may have
1732 extent_mismatch
= realloc_required
1733 || GFC_DESCRIPTOR_EXTENT (dst
, dst_cur_dim
) != delta
;
1734 /* When it already known, that a realloc is needed or
1735 the extent does not match the needed one. */
1736 if (realloc_required
|| realloc_needed
1739 /* Check whether dst is reallocatable. */
1740 if (unlikely (!dst_reallocatable
))
1742 caf_internal_error (nonallocextentmismatch
, stat
,
1744 GFC_DESCRIPTOR_EXTENT (dst
,
1748 /* Only report an error, when the extent needs to be
1749 modified, which is not allowed. */
1750 else if (!dst_reallocatable
&& extent_mismatch
)
1752 caf_internal_error (extentoutofrange
, stat
, NULL
,
1756 realloc_needed
= true;
1758 /* Only change the extent when it does not match. This is
1759 to prevent resetting given array bounds. */
1760 if (extent_mismatch
)
1761 GFC_DIMENSION_SET (dst
->dim
[dst_cur_dim
], 1, delta
,
1765 /* Only increase the dim counter, when in an array ref. */
1766 if (in_array_ref
&& dst_cur_dim
< dst_rank
)
1769 size
*= (index_type
)delta
;
1773 array_extent_fixed
= true;
1774 in_array_ref
= false;
1775 /* Check, if we got less dimensional refs than the rank of dst
1777 assert (dst_cur_dim
== GFC_DESCRIPTOR_RANK (dst
));
1780 case CAF_REF_STATIC_ARRAY
:
1781 for (i
= 0; riter
->u
.a
.mode
[i
] != CAF_ARR_REF_NONE
; ++i
)
1783 switch (riter
->u
.a
.mode
[i
])
1785 case CAF_ARR_REF_VECTOR
:
1786 delta
= riter
->u
.a
.dim
[i
].v
.nvec
;
1787 #define KINDCASE(kind, type) case kind: \
1788 memptr += ((type *)riter->u.a.dim[i].v.vector)[0] \
1789 * riter->item_size; \
1792 switch (riter
->u
.a
.dim
[i
].v
.kind
)
1794 KINDCASE (1, GFC_INTEGER_1
);
1795 KINDCASE (2, GFC_INTEGER_2
);
1796 KINDCASE (4, GFC_INTEGER_4
);
1797 #ifdef HAVE_GFC_INTEGER_8
1798 KINDCASE (8, GFC_INTEGER_8
);
1800 #ifdef HAVE_GFC_INTEGER_16
1801 KINDCASE (16, GFC_INTEGER_16
);
1804 caf_internal_error (vecrefunknownkind
, stat
, NULL
, 0);
1809 case CAF_ARR_REF_FULL
:
1810 delta
= riter
->u
.a
.dim
[i
].s
.end
/ riter
->u
.a
.dim
[i
].s
.stride
1812 /* The memptr stays unchanged when ref'ing the first element
1815 case CAF_ARR_REF_RANGE
:
1816 COMPUTE_NUM_ITEMS (delta
,
1817 riter
->u
.a
.dim
[i
].s
.stride
,
1818 riter
->u
.a
.dim
[i
].s
.start
,
1819 riter
->u
.a
.dim
[i
].s
.end
);
1820 memptr
+= riter
->u
.a
.dim
[i
].s
.start
1821 * riter
->u
.a
.dim
[i
].s
.stride
1824 case CAF_ARR_REF_SINGLE
:
1826 memptr
+= riter
->u
.a
.dim
[i
].s
.start
1827 * riter
->u
.a
.dim
[i
].s
.stride
1830 case CAF_ARR_REF_OPEN_END
:
1831 /* This and OPEN_START are mapped to a RANGE and therefore
1832 can not occur here. */
1833 case CAF_ARR_REF_OPEN_START
:
1835 caf_internal_error (unknownarrreftype
, stat
, NULL
, 0);
1840 /* Check the various properties of the destination array.
1841 Is an array expected and present? */
1842 if (delta
> 1 && dst_rank
== 0)
1844 /* No, an array is required, but not provided. */
1845 caf_internal_error (extentoutofrange
, stat
, NULL
, 0);
1848 /* When dst is an array. */
1851 /* Check that dst_cur_dim is valid for dst. Can be
1852 superceeded only by scalar data. */
1853 if (dst_cur_dim
>= dst_rank
&& delta
!= 1)
1855 caf_internal_error (rankoutofrange
, stat
, NULL
, 0);
1858 /* Do further checks, when the source is not scalar. */
1859 else if (delta
!= 1)
1861 /* Check that the extent is not scalar and we are not in
1862 an array ref for the dst side. */
1865 /* Check that this is the non-scalar extent. */
1866 if (!array_extent_fixed
)
1868 /* In an array extent now. */
1869 in_array_ref
= true;
1870 /* The dst is not reallocatable, so nothing more
1871 to do, then correct the dim counter. */
1876 caf_internal_error (doublearrayref
, stat
, NULL
,
1881 /* When the realloc is required, then no extent may have
1883 extent_mismatch
= realloc_required
1884 || GFC_DESCRIPTOR_EXTENT (dst
, dst_cur_dim
) != delta
;
1885 /* When it is already known, that a realloc is needed or
1886 the extent does not match the needed one. */
1887 if (realloc_required
|| realloc_needed
1890 /* Check whether dst is reallocatable. */
1891 if (unlikely (!dst_reallocatable
))
1893 caf_internal_error (nonallocextentmismatch
, stat
,
1895 GFC_DESCRIPTOR_EXTENT (dst
,
1899 /* Only report an error, when the extent needs to be
1900 modified, which is not allowed. */
1901 else if (!dst_reallocatable
&& extent_mismatch
)
1903 caf_internal_error (extentoutofrange
, stat
, NULL
,
1907 realloc_needed
= true;
1909 /* Only change the extent when it does not match. This is
1910 to prevent resetting given array bounds. */
1911 if (extent_mismatch
)
1912 GFC_DIMENSION_SET (dst
->dim
[dst_cur_dim
], 1, delta
,
1915 /* Only increase the dim counter, when in an array ref. */
1916 if (in_array_ref
&& dst_cur_dim
< dst_rank
)
1919 size
*= (index_type
)delta
;
1923 array_extent_fixed
= true;
1924 in_array_ref
= false;
1925 /* Check, if we got less dimensional refs than the rank of dst
1927 assert (dst_cur_dim
== GFC_DESCRIPTOR_RANK (dst
));
1931 caf_internal_error (unknownreftype
, stat
, NULL
, 0);
1934 src_size
= riter
->item_size
;
1935 riter
= riter
->next
;
1937 if (size
== 0 || src_size
== 0)
1940 - size contains the number of elements to store in the destination array,
1941 - src_size gives the size in bytes of each item in the destination array.
1946 if (!array_extent_fixed
)
1949 /* This can happen only, when the result is scalar. */
1950 for (dst_cur_dim
= 0; dst_cur_dim
< dst_rank
; ++dst_cur_dim
)
1951 GFC_DIMENSION_SET (dst
->dim
[dst_cur_dim
], 1, 1, 1);
1954 GFC_DESCRIPTOR_DATA (dst
) = malloc (size
* GFC_DESCRIPTOR_SIZE (dst
));
1955 if (unlikely (GFC_DESCRIPTOR_DATA (dst
) == NULL
))
1957 caf_internal_error (cannotallocdst
, stat
, NULL
, 0);
1962 /* Reset the token. */
1963 single_token
= TOKEN (token
);
1964 memptr
= single_token
->memptr
;
1965 src
= single_token
->desc
;
1966 memset(dst_index
, 0, sizeof (dst_index
));
1968 get_for_ref (refs
, &i
, dst_index
, single_token
, dst
, src
,
1969 GFC_DESCRIPTOR_DATA (dst
), memptr
, dst_kind
, src_kind
, 0, 0,
1975 send_by_ref (caf_reference_t
*ref
, size_t *i
, size_t *src_index
,
1976 caf_single_token_t single_token
, gfc_descriptor_t
*dst
,
1977 gfc_descriptor_t
*src
, void *ds
, void *sr
,
1978 int dst_kind
, int src_kind
, size_t dst_dim
, size_t src_dim
,
1979 size_t num
, size_t size
, int *stat
)
1981 const char vecrefunknownkind
[] = "libcaf_single::caf_send_by_ref(): "
1982 "unknown kind in vector-ref.\n";
1983 ptrdiff_t extent_dst
= 1, array_offset_dst
= 0, stride_dst
;
1984 const size_t src_rank
= GFC_DESCRIPTOR_RANK (src
);
1986 if (unlikely (ref
== NULL
))
1987 /* May be we should issue an error here, because this case should not
1991 if (ref
->next
== NULL
)
1993 size_t src_size
= GFC_DESCRIPTOR_SIZE (src
);
1994 ptrdiff_t array_offset_src
= 0;;
1999 case CAF_REF_COMPONENT
:
2000 if (ref
->u
.c
.caf_token_offset
> 0)
2002 if (*(void**)(ds
+ ref
->u
.c
.offset
) == NULL
)
2004 /* Create a scalar temporary array descriptor. */
2005 gfc_descriptor_t static_dst
;
2006 GFC_DESCRIPTOR_DATA (&static_dst
) = NULL
;
2007 GFC_DESCRIPTOR_DTYPE (&static_dst
)
2008 = GFC_DESCRIPTOR_DTYPE (src
);
2009 /* The component can be allocated now, because it is a
2011 _gfortran_caf_register (ref
->item_size
,
2012 CAF_REGTYPE_COARRAY_ALLOC
,
2013 ds
+ ref
->u
.c
.caf_token_offset
,
2014 &static_dst
, stat
, NULL
, 0);
2015 single_token
= *(caf_single_token_t
*)
2016 (ds
+ ref
->u
.c
.caf_token_offset
);
2017 /* In case of an error in allocation return. When stat is
2018 NULL, then register_component() terminates on error. */
2019 if (stat
!= NULL
&& *stat
)
2021 /* Publish the allocated memory. */
2022 *((void **)(ds
+ ref
->u
.c
.offset
))
2023 = GFC_DESCRIPTOR_DATA (&static_dst
);
2024 ds
= GFC_DESCRIPTOR_DATA (&static_dst
);
2025 /* Set the type from the src. */
2026 dst_type
= GFC_DESCRIPTOR_TYPE (src
);
2030 single_token
= *(caf_single_token_t
*)
2031 (ds
+ ref
->u
.c
.caf_token_offset
);
2032 dst
= single_token
->desc
;
2035 ds
= GFC_DESCRIPTOR_DATA (dst
);
2036 dst_type
= GFC_DESCRIPTOR_TYPE (dst
);
2040 /* When no destination descriptor is present, assume that
2041 source and dest type are identical. */
2042 dst_type
= GFC_DESCRIPTOR_TYPE (src
);
2043 ds
= *(void **)(ds
+ ref
->u
.c
.offset
);
2046 copy_data (ds
, sr
, dst_type
, GFC_DESCRIPTOR_TYPE (src
),
2047 dst_kind
, src_kind
, ref
->item_size
, src_size
, 1, stat
);
2050 copy_data (ds
+ ref
->u
.c
.offset
, sr
,
2051 dst
!= NULL
? GFC_DESCRIPTOR_TYPE (dst
)
2052 : GFC_DESCRIPTOR_TYPE (src
),
2053 GFC_DESCRIPTOR_TYPE (src
),
2054 dst_kind
, src_kind
, ref
->item_size
, src_size
, 1, stat
);
2057 case CAF_REF_STATIC_ARRAY
:
2058 dst_type
= ref
->u
.a
.static_array_type
;
2059 /* Intentionally fall through. */
2061 if (ref
->u
.a
.mode
[dst_dim
] == CAF_ARR_REF_NONE
)
2065 for (size_t d
= 0; d
< src_rank
; ++d
)
2066 array_offset_src
+= src_index
[d
];
2067 copy_data (ds
, sr
+ array_offset_src
* ref
->item_size
,
2068 dst_type
== -1 ? GFC_DESCRIPTOR_TYPE (dst
)
2070 GFC_DESCRIPTOR_TYPE (src
), dst_kind
, src_kind
,
2071 ref
->item_size
, src_size
, num
, stat
);
2075 dst_type
== -1 ? GFC_DESCRIPTOR_TYPE (dst
)
2077 GFC_DESCRIPTOR_TYPE (src
), dst_kind
, src_kind
,
2078 ref
->item_size
, src_size
, num
, stat
);
2084 caf_runtime_error (unreachable
);
2090 case CAF_REF_COMPONENT
:
2091 if (ref
->u
.c
.caf_token_offset
> 0)
2093 if (*(void**)(ds
+ ref
->u
.c
.offset
) == NULL
)
2095 /* This component refs an unallocated array. Non-arrays are
2096 caught in the if (!ref->next) above. */
2097 dst
= (gfc_descriptor_t
*)(ds
+ ref
->u
.c
.offset
);
2098 /* Assume that the rank and the dimensions fit for copying src
2100 GFC_DESCRIPTOR_DTYPE (dst
) = GFC_DESCRIPTOR_DTYPE (src
);
2103 for (size_t d
= 0; d
< src_rank
; ++d
)
2105 extent_dst
= GFC_DIMENSION_EXTENT (src
->dim
[d
]);
2106 GFC_DIMENSION_LBOUND (dst
->dim
[d
]) = 0;
2107 GFC_DIMENSION_UBOUND (dst
->dim
[d
]) = extent_dst
- 1;
2108 GFC_DIMENSION_STRIDE (dst
->dim
[d
]) = stride_dst
;
2109 stride_dst
*= extent_dst
;
2111 /* Null the data-pointer to make register_component allocate
2113 GFC_DESCRIPTOR_DATA (dst
) = NULL
;
2115 /* The size of the array is given by size. */
2116 _gfortran_caf_register (size
* ref
->item_size
,
2117 CAF_REGTYPE_COARRAY_ALLOC
,
2118 ds
+ ref
->u
.c
.caf_token_offset
,
2119 dst
, stat
, NULL
, 0);
2120 /* In case of an error in allocation return. When stat is
2121 NULL, then register_component() terminates on error. */
2122 if (stat
!= NULL
&& *stat
)
2125 single_token
= *(caf_single_token_t
*)(ds
+ ref
->u
.c
.caf_token_offset
);
2126 send_by_ref (ref
->next
, i
, src_index
, single_token
,
2127 single_token
->desc
, src
, ds
+ ref
->u
.c
.offset
, sr
,
2128 dst_kind
, src_kind
, 0, src_dim
, 1, size
, stat
);
2131 send_by_ref (ref
->next
, i
, src_index
, single_token
,
2132 (gfc_descriptor_t
*)(ds
+ ref
->u
.c
.offset
), src
,
2133 ds
+ ref
->u
.c
.offset
, sr
, dst_kind
, src_kind
, 0, src_dim
,
2137 if (ref
->u
.a
.mode
[dst_dim
] == CAF_ARR_REF_NONE
)
2139 send_by_ref (ref
->next
, i
, src_index
, single_token
,
2140 (gfc_descriptor_t
*)ds
, src
, ds
, sr
, dst_kind
, src_kind
,
2141 0, src_dim
, 1, size
, stat
);
2144 /* Only when on the left most index switch the data pointer to
2145 the array's data pointer. And only for non-static arrays. */
2146 if (dst_dim
== 0 && ref
->type
!= CAF_REF_STATIC_ARRAY
)
2147 ds
= GFC_DESCRIPTOR_DATA (dst
);
2148 switch (ref
->u
.a
.mode
[dst_dim
])
2150 case CAF_ARR_REF_VECTOR
:
2151 array_offset_dst
= 0;
2152 src_index
[src_dim
] = 0;
2153 for (size_t idx
= 0; idx
< ref
->u
.a
.dim
[dst_dim
].v
.nvec
;
2156 #define KINDCASE(kind, type) case kind: \
2157 array_offset_dst = (((index_type) \
2158 ((type *)ref->u.a.dim[dst_dim].v.vector)[idx]) \
2159 - GFC_DIMENSION_LBOUND (dst->dim[dst_dim])) \
2160 * GFC_DIMENSION_STRIDE (dst->dim[dst_dim]); \
2163 switch (ref
->u
.a
.dim
[dst_dim
].v
.kind
)
2165 KINDCASE (1, GFC_INTEGER_1
);
2166 KINDCASE (2, GFC_INTEGER_2
);
2167 KINDCASE (4, GFC_INTEGER_4
);
2168 #ifdef HAVE_GFC_INTEGER_8
2169 KINDCASE (8, GFC_INTEGER_8
);
2171 #ifdef HAVE_GFC_INTEGER_16
2172 KINDCASE (16, GFC_INTEGER_16
);
2175 caf_internal_error (vecrefunknownkind
, stat
, NULL
, 0);
2180 send_by_ref (ref
, i
, src_index
, single_token
, dst
, src
,
2181 ds
+ array_offset_dst
* ref
->item_size
, sr
,
2182 dst_kind
, src_kind
, dst_dim
+ 1, src_dim
+ 1,
2186 += GFC_DIMENSION_STRIDE (src
->dim
[src_dim
]);
2189 case CAF_ARR_REF_FULL
:
2190 COMPUTE_NUM_ITEMS (extent_dst
,
2191 ref
->u
.a
.dim
[dst_dim
].s
.stride
,
2192 GFC_DIMENSION_LBOUND (dst
->dim
[dst_dim
]),
2193 GFC_DIMENSION_UBOUND (dst
->dim
[dst_dim
]));
2194 array_offset_dst
= 0;
2195 stride_dst
= GFC_DIMENSION_STRIDE (dst
->dim
[dst_dim
])
2196 * ref
->u
.a
.dim
[dst_dim
].s
.stride
;
2197 src_index
[src_dim
] = 0;
2198 for (index_type idx
= 0; idx
< extent_dst
;
2199 ++idx
, array_offset_dst
+= stride_dst
)
2201 send_by_ref (ref
, i
, src_index
, single_token
, dst
, src
,
2202 ds
+ array_offset_dst
* ref
->item_size
, sr
,
2203 dst_kind
, src_kind
, dst_dim
+ 1, src_dim
+ 1,
2207 += GFC_DIMENSION_STRIDE (src
->dim
[src_dim
]);
2210 case CAF_ARR_REF_RANGE
:
2211 COMPUTE_NUM_ITEMS (extent_dst
,
2212 ref
->u
.a
.dim
[dst_dim
].s
.stride
,
2213 ref
->u
.a
.dim
[dst_dim
].s
.start
,
2214 ref
->u
.a
.dim
[dst_dim
].s
.end
);
2215 array_offset_dst
= ref
->u
.a
.dim
[dst_dim
].s
.start
2216 - GFC_DIMENSION_LBOUND (dst
->dim
[dst_dim
]);
2217 stride_dst
= GFC_DIMENSION_STRIDE (dst
->dim
[dst_dim
])
2218 * ref
->u
.a
.dim
[dst_dim
].s
.stride
;
2219 src_index
[src_dim
] = 0;
2220 for (index_type idx
= 0; idx
< extent_dst
; ++idx
)
2222 send_by_ref (ref
, i
, src_index
, single_token
, dst
, src
,
2223 ds
+ array_offset_dst
* ref
->item_size
, sr
,
2224 dst_kind
, src_kind
, dst_dim
+ 1, src_dim
+ 1,
2228 += GFC_DIMENSION_STRIDE (src
->dim
[src_dim
]);
2229 array_offset_dst
+= stride_dst
;
2232 case CAF_ARR_REF_SINGLE
:
2233 array_offset_dst
= (ref
->u
.a
.dim
[dst_dim
].s
.start
2234 - GFC_DIMENSION_LBOUND (dst
->dim
[dst_dim
]))
2235 * GFC_DIMENSION_STRIDE (dst
->dim
[dst_dim
]);
2236 send_by_ref (ref
, i
, src_index
, single_token
, dst
, src
, ds
2237 + array_offset_dst
* ref
->item_size
, sr
,
2238 dst_kind
, src_kind
, dst_dim
+ 1, src_dim
, 1,
2241 case CAF_ARR_REF_OPEN_END
:
2242 COMPUTE_NUM_ITEMS (extent_dst
,
2243 ref
->u
.a
.dim
[dst_dim
].s
.stride
,
2244 ref
->u
.a
.dim
[dst_dim
].s
.start
,
2245 GFC_DIMENSION_UBOUND (dst
->dim
[dst_dim
]));
2246 array_offset_dst
= ref
->u
.a
.dim
[dst_dim
].s
.start
2247 - GFC_DIMENSION_LBOUND (dst
->dim
[dst_dim
]);
2248 stride_dst
= GFC_DIMENSION_STRIDE (dst
->dim
[dst_dim
])
2249 * ref
->u
.a
.dim
[dst_dim
].s
.stride
;
2250 src_index
[src_dim
] = 0;
2251 for (index_type idx
= 0; idx
< extent_dst
; ++idx
)
2253 send_by_ref (ref
, i
, src_index
, single_token
, dst
, src
,
2254 ds
+ array_offset_dst
* ref
->item_size
, sr
,
2255 dst_kind
, src_kind
, dst_dim
+ 1, src_dim
+ 1,
2259 += GFC_DIMENSION_STRIDE (src
->dim
[src_dim
]);
2260 array_offset_dst
+= stride_dst
;
2263 case CAF_ARR_REF_OPEN_START
:
2264 COMPUTE_NUM_ITEMS (extent_dst
,
2265 ref
->u
.a
.dim
[dst_dim
].s
.stride
,
2266 GFC_DIMENSION_LBOUND (dst
->dim
[dst_dim
]),
2267 ref
->u
.a
.dim
[dst_dim
].s
.end
);
2268 array_offset_dst
= 0;
2269 stride_dst
= GFC_DIMENSION_STRIDE (dst
->dim
[dst_dim
])
2270 * ref
->u
.a
.dim
[dst_dim
].s
.stride
;
2271 src_index
[src_dim
] = 0;
2272 for (index_type idx
= 0; idx
< extent_dst
; ++idx
)
2274 send_by_ref (ref
, i
, src_index
, single_token
, dst
, src
,
2275 ds
+ array_offset_dst
* ref
->item_size
, sr
,
2276 dst_kind
, src_kind
, dst_dim
+ 1, src_dim
+ 1,
2280 += GFC_DIMENSION_STRIDE (src
->dim
[src_dim
]);
2281 array_offset_dst
+= stride_dst
;
2285 caf_runtime_error (unreachable
);
2288 case CAF_REF_STATIC_ARRAY
:
2289 if (ref
->u
.a
.mode
[dst_dim
] == CAF_ARR_REF_NONE
)
2291 send_by_ref (ref
->next
, i
, src_index
, single_token
, NULL
,
2292 src
, ds
, sr
, dst_kind
, src_kind
,
2293 0, src_dim
, 1, size
, stat
);
2296 switch (ref
->u
.a
.mode
[dst_dim
])
2298 case CAF_ARR_REF_VECTOR
:
2299 array_offset_dst
= 0;
2300 src_index
[src_dim
] = 0;
2301 for (size_t idx
= 0; idx
< ref
->u
.a
.dim
[dst_dim
].v
.nvec
;
2304 #define KINDCASE(kind, type) case kind: \
2305 array_offset_dst = ((type *)ref->u.a.dim[dst_dim].v.vector)[idx]; \
2308 switch (ref
->u
.a
.dim
[dst_dim
].v
.kind
)
2310 KINDCASE (1, GFC_INTEGER_1
);
2311 KINDCASE (2, GFC_INTEGER_2
);
2312 KINDCASE (4, GFC_INTEGER_4
);
2313 #ifdef HAVE_GFC_INTEGER_8
2314 KINDCASE (8, GFC_INTEGER_8
);
2316 #ifdef HAVE_GFC_INTEGER_16
2317 KINDCASE (16, GFC_INTEGER_16
);
2320 caf_runtime_error (unreachable
);
2325 send_by_ref (ref
, i
, src_index
, single_token
, NULL
, src
,
2326 ds
+ array_offset_dst
* ref
->item_size
, sr
,
2327 dst_kind
, src_kind
, dst_dim
+ 1, src_dim
+ 1,
2330 += GFC_DIMENSION_STRIDE (src
->dim
[src_dim
]);
2333 case CAF_ARR_REF_FULL
:
2334 src_index
[src_dim
] = 0;
2335 for (array_offset_dst
= 0 ;
2336 array_offset_dst
<= ref
->u
.a
.dim
[dst_dim
].s
.end
;
2337 array_offset_dst
+= ref
->u
.a
.dim
[dst_dim
].s
.stride
)
2339 send_by_ref (ref
, i
, src_index
, single_token
, NULL
, src
,
2340 ds
+ array_offset_dst
* ref
->item_size
, sr
,
2341 dst_kind
, src_kind
, dst_dim
+ 1, src_dim
+ 1,
2345 += GFC_DIMENSION_STRIDE (src
->dim
[src_dim
]);
2348 case CAF_ARR_REF_RANGE
:
2349 COMPUTE_NUM_ITEMS (extent_dst
,
2350 ref
->u
.a
.dim
[dst_dim
].s
.stride
,
2351 ref
->u
.a
.dim
[dst_dim
].s
.start
,
2352 ref
->u
.a
.dim
[dst_dim
].s
.end
);
2353 array_offset_dst
= ref
->u
.a
.dim
[dst_dim
].s
.start
;
2354 src_index
[src_dim
] = 0;
2355 for (index_type idx
= 0; idx
< extent_dst
; ++idx
)
2357 send_by_ref (ref
, i
, src_index
, single_token
, NULL
, src
,
2358 ds
+ array_offset_dst
* ref
->item_size
, sr
,
2359 dst_kind
, src_kind
, dst_dim
+ 1, src_dim
+ 1,
2363 += GFC_DIMENSION_STRIDE (src
->dim
[src_dim
]);
2364 array_offset_dst
+= ref
->u
.a
.dim
[dst_dim
].s
.stride
;
2367 case CAF_ARR_REF_SINGLE
:
2368 array_offset_dst
= ref
->u
.a
.dim
[dst_dim
].s
.start
;
2369 send_by_ref (ref
, i
, src_index
, single_token
, NULL
, src
,
2370 ds
+ array_offset_dst
* ref
->item_size
, sr
,
2371 dst_kind
, src_kind
, dst_dim
+ 1, src_dim
, 1,
2374 /* The OPEN_* are mapped to a RANGE and therefore can not occur. */
2375 case CAF_ARR_REF_OPEN_END
:
2376 case CAF_ARR_REF_OPEN_START
:
2378 caf_runtime_error (unreachable
);
2382 caf_runtime_error (unreachable
);
2388 _gfortran_caf_send_by_ref (caf_token_t token
,
2389 int image_index
__attribute__ ((unused
)),
2390 gfc_descriptor_t
*src
, caf_reference_t
*refs
,
2391 int dst_kind
, int src_kind
,
2392 bool may_require_tmp
__attribute__ ((unused
)),
2393 bool dst_reallocatable
, int *stat
)
2395 const char vecrefunknownkind
[] = "libcaf_single::caf_get_by_ref(): "
2396 "unknown kind in vector-ref.\n";
2397 const char unknownreftype
[] = "libcaf_single::caf_send_by_ref(): "
2398 "unknown reference type.\n";
2399 const char unknownarrreftype
[] = "libcaf_single::caf_send_by_ref(): "
2400 "unknown array reference type.\n";
2401 const char rankoutofrange
[] = "libcaf_single::caf_send_by_ref(): "
2402 "rank out of range.\n";
2403 const char realloconinnerref
[] = "libcaf_single::caf_send_by_ref(): "
2404 "reallocation of array followed by component ref not allowed.\n";
2405 const char cannotallocdst
[] = "libcaf_single::caf_send_by_ref(): "
2406 "can not allocate memory.\n";
2407 const char nonallocextentmismatch
[] = "libcaf_single::caf_send_by_ref(): "
2408 "extent of non-allocatable array mismatch.\n";
2409 const char innercompref
[] = "libcaf_single::caf_send_by_ref(): "
2410 "inner unallocated component detected.\n";
2412 size_t dst_index
[GFC_MAX_DIMENSIONS
];
2413 int src_rank
= GFC_DESCRIPTOR_RANK (src
);
2414 int src_cur_dim
= 0;
2415 size_t src_size
= 0;
2416 caf_single_token_t single_token
= TOKEN (token
);
2417 void *memptr
= single_token
->memptr
;
2418 gfc_descriptor_t
*dst
= single_token
->desc
;
2419 caf_reference_t
*riter
= refs
;
2421 bool extent_mismatch
;
2422 /* Note that the component is not allocated yet. */
2423 index_type new_component_idx
= -1;
2428 /* Compute the size of the result. In the beginning size just counts the
2429 number of elements. */
2433 switch (riter
->type
)
2435 case CAF_REF_COMPONENT
:
2436 if (unlikely (new_component_idx
!= -1))
2438 /* Allocating a component in the middle of a component ref is not
2439 support. We don't know the type to allocate. */
2440 caf_internal_error (innercompref
, stat
, NULL
, 0);
2443 if (riter
->u
.c
.caf_token_offset
> 0)
2445 /* Check whether the allocatable component is zero, then no
2446 token is present, too. The token's pointer is not cleared
2447 when the structure is initialized. */
2448 if (*(void**)(memptr
+ riter
->u
.c
.offset
) == NULL
)
2450 /* This component is not yet allocated. Check that it is
2451 allocatable here. */
2452 if (!dst_reallocatable
)
2454 caf_internal_error (cannotallocdst
, stat
, NULL
, 0);
2457 single_token
= NULL
;
2462 single_token
= *(caf_single_token_t
*)
2463 (memptr
+ riter
->u
.c
.caf_token_offset
);
2464 memptr
+= riter
->u
.c
.offset
;
2465 dst
= single_token
->desc
;
2469 /* Regular component. */
2470 memptr
+= riter
->u
.c
.offset
;
2471 dst
= (gfc_descriptor_t
*)memptr
;
2476 memptr
= GFC_DESCRIPTOR_DATA (dst
);
2479 /* When the dst array needs to be allocated, then look at the
2480 extent of the source array in the dimension dst_cur_dim. */
2481 for (i
= 0; riter
->u
.a
.mode
[i
] != CAF_ARR_REF_NONE
; ++i
)
2483 switch (riter
->u
.a
.mode
[i
])
2485 case CAF_ARR_REF_VECTOR
:
2486 delta
= riter
->u
.a
.dim
[i
].v
.nvec
;
2487 #define KINDCASE(kind, type) case kind: \
2488 memptr += (((index_type) \
2489 ((type *)riter->u.a.dim[i].v.vector)[0]) \
2490 - GFC_DIMENSION_LBOUND (dst->dim[i])) \
2491 * GFC_DIMENSION_STRIDE (dst->dim[i]) \
2492 * riter->item_size; \
2495 switch (riter
->u
.a
.dim
[i
].v
.kind
)
2497 KINDCASE (1, GFC_INTEGER_1
);
2498 KINDCASE (2, GFC_INTEGER_2
);
2499 KINDCASE (4, GFC_INTEGER_4
);
2500 #ifdef HAVE_GFC_INTEGER_8
2501 KINDCASE (8, GFC_INTEGER_8
);
2503 #ifdef HAVE_GFC_INTEGER_16
2504 KINDCASE (16, GFC_INTEGER_16
);
2507 caf_internal_error (vecrefunknownkind
, stat
, NULL
, 0);
2512 case CAF_ARR_REF_FULL
:
2514 COMPUTE_NUM_ITEMS (delta
,
2515 riter
->u
.a
.dim
[i
].s
.stride
,
2516 GFC_DIMENSION_LBOUND (dst
->dim
[i
]),
2517 GFC_DIMENSION_UBOUND (dst
->dim
[i
]));
2519 COMPUTE_NUM_ITEMS (delta
,
2520 riter
->u
.a
.dim
[i
].s
.stride
,
2521 GFC_DIMENSION_LBOUND (src
->dim
[src_cur_dim
]),
2522 GFC_DIMENSION_UBOUND (src
->dim
[src_cur_dim
]));
2524 case CAF_ARR_REF_RANGE
:
2525 COMPUTE_NUM_ITEMS (delta
,
2526 riter
->u
.a
.dim
[i
].s
.stride
,
2527 riter
->u
.a
.dim
[i
].s
.start
,
2528 riter
->u
.a
.dim
[i
].s
.end
);
2529 memptr
+= (riter
->u
.a
.dim
[i
].s
.start
2530 - dst
->dim
[i
].lower_bound
)
2531 * GFC_DIMENSION_STRIDE (dst
->dim
[i
])
2534 case CAF_ARR_REF_SINGLE
:
2536 memptr
+= (riter
->u
.a
.dim
[i
].s
.start
2537 - dst
->dim
[i
].lower_bound
)
2538 * GFC_DIMENSION_STRIDE (dst
->dim
[i
])
2541 case CAF_ARR_REF_OPEN_END
:
2543 COMPUTE_NUM_ITEMS (delta
,
2544 riter
->u
.a
.dim
[i
].s
.stride
,
2545 riter
->u
.a
.dim
[i
].s
.start
,
2546 GFC_DIMENSION_UBOUND (dst
->dim
[i
]));
2548 COMPUTE_NUM_ITEMS (delta
,
2549 riter
->u
.a
.dim
[i
].s
.stride
,
2550 riter
->u
.a
.dim
[i
].s
.start
,
2551 GFC_DIMENSION_UBOUND (src
->dim
[src_cur_dim
]));
2552 memptr
+= (riter
->u
.a
.dim
[i
].s
.start
2553 - dst
->dim
[i
].lower_bound
)
2554 * GFC_DIMENSION_STRIDE (dst
->dim
[i
])
2557 case CAF_ARR_REF_OPEN_START
:
2559 COMPUTE_NUM_ITEMS (delta
,
2560 riter
->u
.a
.dim
[i
].s
.stride
,
2561 GFC_DIMENSION_LBOUND (dst
->dim
[i
]),
2562 riter
->u
.a
.dim
[i
].s
.end
);
2564 COMPUTE_NUM_ITEMS (delta
,
2565 riter
->u
.a
.dim
[i
].s
.stride
,
2566 GFC_DIMENSION_LBOUND (src
->dim
[src_cur_dim
]),
2567 riter
->u
.a
.dim
[i
].s
.end
);
2568 /* The memptr stays unchanged when ref'ing the first element
2572 caf_internal_error (unknownarrreftype
, stat
, NULL
, 0);
2578 /* Check the various properties of the source array.
2579 When src is an array. */
2580 if (delta
> 1 && src_rank
> 0)
2582 /* Check that src_cur_dim is valid for src. Can be
2583 superceeded only by scalar data. */
2584 if (src_cur_dim
>= src_rank
)
2586 caf_internal_error (rankoutofrange
, stat
, NULL
, 0);
2589 /* Do further checks, when the source is not scalar. */
2592 /* When the realloc is required, then no extent may have
2594 extent_mismatch
= memptr
== NULL
2596 && GFC_DESCRIPTOR_EXTENT (dst
, src_cur_dim
)
2598 /* When it already known, that a realloc is needed or
2599 the extent does not match the needed one. */
2600 if (extent_mismatch
)
2602 /* Check whether dst is reallocatable. */
2603 if (unlikely (!dst_reallocatable
))
2605 caf_internal_error (nonallocextentmismatch
, stat
,
2607 GFC_DESCRIPTOR_EXTENT (dst
,
2611 /* Report error on allocatable but missing inner
2613 else if (riter
->next
!= NULL
)
2615 caf_internal_error (realloconinnerref
, stat
, NULL
,
2620 /* Only change the extent when it does not match. This is
2621 to prevent resetting given array bounds. */
2622 if (extent_mismatch
)
2623 GFC_DIMENSION_SET (dst
->dim
[src_cur_dim
], 1, delta
,
2626 /* Increase the dim-counter of the src only when the extent
2628 if (src_cur_dim
< src_rank
2629 && GFC_DESCRIPTOR_EXTENT (src
, src_cur_dim
) == delta
)
2632 size
*= (index_type
)delta
;
2635 case CAF_REF_STATIC_ARRAY
:
2636 for (i
= 0; riter
->u
.a
.mode
[i
] != CAF_ARR_REF_NONE
; ++i
)
2638 switch (riter
->u
.a
.mode
[i
])
2640 case CAF_ARR_REF_VECTOR
:
2641 delta
= riter
->u
.a
.dim
[i
].v
.nvec
;
2642 #define KINDCASE(kind, type) case kind: \
2643 memptr += ((type *)riter->u.a.dim[i].v.vector)[0] \
2644 * riter->item_size; \
2647 switch (riter
->u
.a
.dim
[i
].v
.kind
)
2649 KINDCASE (1, GFC_INTEGER_1
);
2650 KINDCASE (2, GFC_INTEGER_2
);
2651 KINDCASE (4, GFC_INTEGER_4
);
2652 #ifdef HAVE_GFC_INTEGER_8
2653 KINDCASE (8, GFC_INTEGER_8
);
2655 #ifdef HAVE_GFC_INTEGER_16
2656 KINDCASE (16, GFC_INTEGER_16
);
2659 caf_internal_error (vecrefunknownkind
, stat
, NULL
, 0);
2664 case CAF_ARR_REF_FULL
:
2665 delta
= riter
->u
.a
.dim
[i
].s
.end
/ riter
->u
.a
.dim
[i
].s
.stride
2667 /* The memptr stays unchanged when ref'ing the first element
2670 case CAF_ARR_REF_RANGE
:
2671 COMPUTE_NUM_ITEMS (delta
,
2672 riter
->u
.a
.dim
[i
].s
.stride
,
2673 riter
->u
.a
.dim
[i
].s
.start
,
2674 riter
->u
.a
.dim
[i
].s
.end
);
2675 memptr
+= riter
->u
.a
.dim
[i
].s
.start
2676 * riter
->u
.a
.dim
[i
].s
.stride
2679 case CAF_ARR_REF_SINGLE
:
2681 memptr
+= riter
->u
.a
.dim
[i
].s
.start
2682 * riter
->u
.a
.dim
[i
].s
.stride
2685 case CAF_ARR_REF_OPEN_END
:
2686 /* This and OPEN_START are mapped to a RANGE and therefore
2687 can not occur here. */
2688 case CAF_ARR_REF_OPEN_START
:
2690 caf_internal_error (unknownarrreftype
, stat
, NULL
, 0);
2695 /* Check the various properties of the source array.
2696 Only when the source array is not scalar examine its
2698 if (delta
> 1 && src_rank
> 0)
2700 /* Check that src_cur_dim is valid for src. Can be
2701 superceeded only by scalar data. */
2702 if (src_cur_dim
>= src_rank
)
2704 caf_internal_error (rankoutofrange
, stat
, NULL
, 0);
2709 /* We will not be able to realloc the dst, because that's
2710 a fixed size array. */
2711 extent_mismatch
= GFC_DESCRIPTOR_EXTENT (src
, src_cur_dim
)
2713 /* When the extent does not match the needed one we can
2715 if (extent_mismatch
)
2717 caf_internal_error (nonallocextentmismatch
, stat
,
2719 GFC_DESCRIPTOR_EXTENT (src
,
2726 size
*= (index_type
)delta
;
2730 caf_internal_error (unknownreftype
, stat
, NULL
, 0);
2733 src_size
= riter
->item_size
;
2734 riter
= riter
->next
;
2736 if (size
== 0 || src_size
== 0)
2739 - size contains the number of elements to store in the destination array,
2740 - src_size gives the size in bytes of each item in the destination array.
2743 /* Reset the token. */
2744 single_token
= TOKEN (token
);
2745 memptr
= single_token
->memptr
;
2746 dst
= single_token
->desc
;
2747 memset (dst_index
, 0, sizeof (dst_index
));
2749 send_by_ref (refs
, &i
, dst_index
, single_token
, dst
, src
,
2750 memptr
, GFC_DESCRIPTOR_DATA (src
), dst_kind
, src_kind
, 0, 0,
2757 _gfortran_caf_sendget_by_ref (caf_token_t dst_token
, int dst_image_index
,
2758 caf_reference_t
*dst_refs
, caf_token_t src_token
,
2759 int src_image_index
,
2760 caf_reference_t
*src_refs
, int dst_kind
,
2761 int src_kind
, bool may_require_tmp
, int *dst_stat
,
2764 gfc_array_void temp
;
2766 _gfortran_caf_get_by_ref (src_token
, src_image_index
, &temp
, src_refs
,
2767 dst_kind
, src_kind
, may_require_tmp
, true,
2770 if (src_stat
&& *src_stat
!= 0)
2773 _gfortran_caf_send_by_ref (dst_token
, dst_image_index
, &temp
, dst_refs
,
2774 dst_kind
, src_kind
, may_require_tmp
, true,
2776 if (GFC_DESCRIPTOR_DATA (&temp
))
2777 free (GFC_DESCRIPTOR_DATA (&temp
));
2782 _gfortran_caf_atomic_define (caf_token_t token
, size_t offset
,
2783 int image_index
__attribute__ ((unused
)),
2784 void *value
, int *stat
,
2785 int type
__attribute__ ((unused
)), int kind
)
2789 uint32_t *atom
= (uint32_t *) ((char *) MEMTOK (token
) + offset
);
2791 __atomic_store (atom
, (uint32_t *) value
, __ATOMIC_RELAXED
);
2798 _gfortran_caf_atomic_ref (caf_token_t token
, size_t offset
,
2799 int image_index
__attribute__ ((unused
)),
2800 void *value
, int *stat
,
2801 int type
__attribute__ ((unused
)), int kind
)
2805 uint32_t *atom
= (uint32_t *) ((char *) MEMTOK (token
) + offset
);
2807 __atomic_load (atom
, (uint32_t *) value
, __ATOMIC_RELAXED
);
2815 _gfortran_caf_atomic_cas (caf_token_t token
, size_t offset
,
2816 int image_index
__attribute__ ((unused
)),
2817 void *old
, void *compare
, void *new_val
, int *stat
,
2818 int type
__attribute__ ((unused
)), int kind
)
2822 uint32_t *atom
= (uint32_t *) ((char *) MEMTOK (token
) + offset
);
2824 *(uint32_t *) old
= *(uint32_t *) compare
;
2825 (void) __atomic_compare_exchange_n (atom
, (uint32_t *) old
,
2826 *(uint32_t *) new_val
, false,
2827 __ATOMIC_RELAXED
, __ATOMIC_RELAXED
);
2834 _gfortran_caf_atomic_op (int op
, caf_token_t token
, size_t offset
,
2835 int image_index
__attribute__ ((unused
)),
2836 void *value
, void *old
, int *stat
,
2837 int type
__attribute__ ((unused
)), int kind
)
2842 uint32_t *atom
= (uint32_t *) ((char *) MEMTOK (token
) + offset
);
2846 case GFC_CAF_ATOMIC_ADD
:
2847 res
= __atomic_fetch_add (atom
, *(uint32_t *) value
, __ATOMIC_RELAXED
);
2849 case GFC_CAF_ATOMIC_AND
:
2850 res
= __atomic_fetch_and (atom
, *(uint32_t *) value
, __ATOMIC_RELAXED
);
2852 case GFC_CAF_ATOMIC_OR
:
2853 res
= __atomic_fetch_or (atom
, *(uint32_t *) value
, __ATOMIC_RELAXED
);
2855 case GFC_CAF_ATOMIC_XOR
:
2856 res
= __atomic_fetch_xor (atom
, *(uint32_t *) value
, __ATOMIC_RELAXED
);
2859 __builtin_unreachable();
2863 *(uint32_t *) old
= res
;
2870 _gfortran_caf_event_post (caf_token_t token
, size_t index
,
2871 int image_index
__attribute__ ((unused
)),
2872 int *stat
, char *errmsg
__attribute__ ((unused
)),
2873 int errmsg_len
__attribute__ ((unused
)))
2876 uint32_t *event
= (uint32_t *) ((char *) MEMTOK (token
) + index
2877 * sizeof (uint32_t));
2878 __atomic_fetch_add (event
, (uint32_t) value
, __ATOMIC_RELAXED
);
2885 _gfortran_caf_event_wait (caf_token_t token
, size_t index
,
2886 int until_count
, int *stat
,
2887 char *errmsg
__attribute__ ((unused
)),
2888 int errmsg_len
__attribute__ ((unused
)))
2890 uint32_t *event
= (uint32_t *) ((char *) MEMTOK (token
) + index
2891 * sizeof (uint32_t));
2892 uint32_t value
= (uint32_t)-until_count
;
2893 __atomic_fetch_add (event
, (uint32_t) value
, __ATOMIC_RELAXED
);
2900 _gfortran_caf_event_query (caf_token_t token
, size_t index
,
2901 int image_index
__attribute__ ((unused
)),
2902 int *count
, int *stat
)
2904 uint32_t *event
= (uint32_t *) ((char *) MEMTOK (token
) + index
2905 * sizeof (uint32_t));
2906 __atomic_load (event
, (uint32_t *) count
, __ATOMIC_RELAXED
);
2913 _gfortran_caf_lock (caf_token_t token
, size_t index
,
2914 int image_index
__attribute__ ((unused
)),
2915 int *aquired_lock
, int *stat
, char *errmsg
, int errmsg_len
)
2917 const char *msg
= "Already locked";
2918 bool *lock
= &((bool *) MEMTOK (token
))[index
];
2924 *aquired_lock
= (int) true;
2932 *aquired_lock
= (int) false;
2944 int len
= ((int) sizeof (msg
) > errmsg_len
) ? errmsg_len
2945 : (int) sizeof (msg
);
2946 memcpy (errmsg
, msg
, len
);
2947 if (errmsg_len
> len
)
2948 memset (&errmsg
[len
], ' ', errmsg_len
-len
);
2952 _gfortran_caf_error_stop_str (msg
, (int32_t) strlen (msg
));
2957 _gfortran_caf_unlock (caf_token_t token
, size_t index
,
2958 int image_index
__attribute__ ((unused
)),
2959 int *stat
, char *errmsg
, int errmsg_len
)
2961 const char *msg
= "Variable is not locked";
2962 bool *lock
= &((bool *) MEMTOK (token
))[index
];
2977 int len
= ((int) sizeof (msg
) > errmsg_len
) ? errmsg_len
2978 : (int) sizeof (msg
);
2979 memcpy (errmsg
, msg
, len
);
2980 if (errmsg_len
> len
)
2981 memset (&errmsg
[len
], ' ', errmsg_len
-len
);
2985 _gfortran_caf_error_stop_str (msg
, (int32_t) strlen (msg
));
2989 _gfortran_caf_is_present (caf_token_t token
,
2990 int image_index
__attribute__ ((unused
)),
2991 caf_reference_t
*refs
)
2993 const char arraddressingnotallowed
[] = "libcaf_single::caf_is_present(): "
2994 "only scalar indexes allowed.\n";
2995 const char unknownreftype
[] = "libcaf_single::caf_get_by_ref(): "
2996 "unknown reference type.\n";
2997 const char unknownarrreftype
[] = "libcaf_single::caf_get_by_ref(): "
2998 "unknown array reference type.\n";
3000 caf_single_token_t single_token
= TOKEN (token
);
3001 void *memptr
= single_token
->memptr
;
3002 gfc_descriptor_t
*src
= single_token
->desc
;
3003 caf_reference_t
*riter
= refs
;
3007 switch (riter
->type
)
3009 case CAF_REF_COMPONENT
:
3010 if (riter
->u
.c
.caf_token_offset
)
3012 single_token
= *(caf_single_token_t
*)
3013 (memptr
+ riter
->u
.c
.caf_token_offset
);
3014 memptr
= single_token
->memptr
;
3015 src
= single_token
->desc
;
3019 memptr
+= riter
->u
.c
.offset
;
3020 src
= (gfc_descriptor_t
*)memptr
;
3024 for (i
= 0; riter
->u
.a
.mode
[i
] != CAF_ARR_REF_NONE
; ++i
)
3026 switch (riter
->u
.a
.mode
[i
])
3028 case CAF_ARR_REF_SINGLE
:
3029 memptr
+= (riter
->u
.a
.dim
[i
].s
.start
3030 - GFC_DIMENSION_LBOUND (src
->dim
[i
]))
3031 * GFC_DIMENSION_STRIDE (src
->dim
[i
])
3034 case CAF_ARR_REF_FULL
:
3035 /* A full array ref is allowed on the last reference only. */
3036 if (riter
->next
== NULL
)
3038 /* else fall through reporting an error. */
3040 case CAF_ARR_REF_VECTOR
:
3041 case CAF_ARR_REF_RANGE
:
3042 case CAF_ARR_REF_OPEN_END
:
3043 case CAF_ARR_REF_OPEN_START
:
3044 caf_internal_error (arraddressingnotallowed
, 0, NULL
, 0);
3047 caf_internal_error (unknownarrreftype
, 0, NULL
, 0);
3052 case CAF_REF_STATIC_ARRAY
:
3053 for (i
= 0; riter
->u
.a
.mode
[i
] != CAF_ARR_REF_NONE
; ++i
)
3055 switch (riter
->u
.a
.mode
[i
])
3057 case CAF_ARR_REF_SINGLE
:
3058 memptr
+= riter
->u
.a
.dim
[i
].s
.start
3059 * riter
->u
.a
.dim
[i
].s
.stride
3062 case CAF_ARR_REF_FULL
:
3063 /* A full array ref is allowed on the last reference only. */
3064 if (riter
->next
== NULL
)
3066 /* else fall through reporting an error. */
3068 case CAF_ARR_REF_VECTOR
:
3069 case CAF_ARR_REF_RANGE
:
3070 case CAF_ARR_REF_OPEN_END
:
3071 case CAF_ARR_REF_OPEN_START
:
3072 caf_internal_error (arraddressingnotallowed
, 0, NULL
, 0);
3075 caf_internal_error (unknownarrreftype
, 0, NULL
, 0);
3081 caf_internal_error (unknownreftype
, 0, NULL
, 0);
3084 riter
= riter
->next
;
3086 return memptr
!= NULL
;