1 /* Single-image implementation of GNU Fortran Coarray Library
2 Copyright (C) 2011-2021 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. */
34 /* Define GFC_CAF_CHECK to enable run-time checking. */
35 /* #define GFC_CAF_CHECK 1 */
37 struct caf_single_token
39 /* The pointer to the memory registered. For arrays this is the data member
40 in the descriptor. For components it's the pure data pointer. */
42 /* The descriptor when this token is associated to an allocatable array. */
43 gfc_descriptor_t
*desc
;
44 /* Set when the caf lib has allocated the memory in memptr and is responsible
45 for freeing it on deregister. */
48 typedef struct caf_single_token
*caf_single_token_t
;
50 #define TOKEN(X) ((caf_single_token_t) (X))
51 #define MEMTOK(X) ((caf_single_token_t) (X))->memptr
53 /* Single-image implementation of the CAF library.
54 Note: For performance reasons -fcoarry=single should be used
55 rather than this library. */
57 /* Global variables. */
58 caf_static_t
*caf_static_list
= NULL
;
60 /* Keep in sync with mpi.c. */
62 caf_runtime_error (const char *message
, ...)
65 fprintf (stderr
, "Fortran runtime error: ");
66 va_start (ap
, message
);
67 vfprintf (stderr
, message
, ap
);
69 fprintf (stderr
, "\n");
71 /* FIXME: Shutdown the Fortran RTL to flush the buffer. PR 43849. */
75 /* Error handling is similar everytime. */
77 caf_internal_error (const char *msg
, int *stat
, char *errmsg
,
78 size_t errmsg_len
, ...)
81 va_start (args
, errmsg_len
);
87 int len
= snprintf (errmsg
, errmsg_len
, msg
, args
);
88 if (len
>= 0 && errmsg_len
> (size_t) len
)
89 memset (&errmsg
[len
], ' ', errmsg_len
- len
);
95 caf_runtime_error (msg
, args
);
101 _gfortran_caf_init (int *argc
__attribute__ ((unused
)),
102 char ***argv
__attribute__ ((unused
)))
108 _gfortran_caf_finalize (void)
110 while (caf_static_list
!= NULL
)
112 caf_static_t
*tmp
= caf_static_list
->prev
;
113 free (caf_static_list
->token
);
114 free (caf_static_list
);
115 caf_static_list
= tmp
;
121 _gfortran_caf_this_image (int distance
__attribute__ ((unused
)))
128 _gfortran_caf_num_images (int distance
__attribute__ ((unused
)),
129 int failed
__attribute__ ((unused
)))
136 _gfortran_caf_register (size_t size
, caf_register_t type
, caf_token_t
*token
,
137 gfc_descriptor_t
*data
, int *stat
, char *errmsg
,
140 const char alloc_fail_msg
[] = "Failed to allocate coarray";
142 caf_single_token_t single_token
;
144 if (type
== CAF_REGTYPE_LOCK_STATIC
|| type
== CAF_REGTYPE_LOCK_ALLOC
145 || type
== CAF_REGTYPE_CRITICAL
)
146 local
= calloc (size
, sizeof (bool));
147 else if (type
== CAF_REGTYPE_EVENT_STATIC
|| type
== CAF_REGTYPE_EVENT_ALLOC
)
148 /* In the event_(wait|post) function the counter for events is a uint32,
149 so better allocate enough memory here. */
150 local
= calloc (size
, sizeof (uint32_t));
151 else if (type
== CAF_REGTYPE_COARRAY_ALLOC_REGISTER_ONLY
)
154 local
= malloc (size
);
156 if (type
!= CAF_REGTYPE_COARRAY_ALLOC_ALLOCATE_ONLY
)
157 *token
= malloc (sizeof (struct caf_single_token
));
159 if (unlikely (*token
== NULL
161 && type
!= CAF_REGTYPE_COARRAY_ALLOC_REGISTER_ONLY
)))
163 /* Freeing the memory conditionally seems pointless, but
164 caf_internal_error () may return, when a stat is given and then the
165 memory may be lost. */
170 caf_internal_error (alloc_fail_msg
, stat
, errmsg
, errmsg_len
);
174 single_token
= TOKEN (*token
);
175 single_token
->memptr
= local
;
176 single_token
->owning_memory
= type
!= CAF_REGTYPE_COARRAY_ALLOC_REGISTER_ONLY
;
177 single_token
->desc
= GFC_DESCRIPTOR_RANK (data
) > 0 ? data
: NULL
;
183 if (type
== CAF_REGTYPE_COARRAY_STATIC
|| type
== CAF_REGTYPE_LOCK_STATIC
184 || type
== CAF_REGTYPE_CRITICAL
|| type
== CAF_REGTYPE_EVENT_STATIC
185 || type
== CAF_REGTYPE_EVENT_ALLOC
)
187 caf_static_t
*tmp
= malloc (sizeof (caf_static_t
));
188 tmp
->prev
= caf_static_list
;
190 caf_static_list
= tmp
;
192 GFC_DESCRIPTOR_DATA (data
) = local
;
197 _gfortran_caf_deregister (caf_token_t
*token
, caf_deregister_t type
, int *stat
,
198 char *errmsg
__attribute__ ((unused
)),
199 size_t errmsg_len
__attribute__ ((unused
)))
201 caf_single_token_t single_token
= TOKEN (*token
);
203 if (single_token
->owning_memory
&& single_token
->memptr
)
204 free (single_token
->memptr
);
206 if (type
!= CAF_DEREGTYPE_COARRAY_DEALLOCATE_ONLY
)
208 free (TOKEN (*token
));
213 single_token
->memptr
= NULL
;
214 single_token
->owning_memory
= false;
223 _gfortran_caf_sync_all (int *stat
,
224 char *errmsg
__attribute__ ((unused
)),
225 size_t errmsg_len
__attribute__ ((unused
)))
227 __asm__
__volatile__ ("":::"memory");
234 _gfortran_caf_sync_memory (int *stat
,
235 char *errmsg
__attribute__ ((unused
)),
236 size_t errmsg_len
__attribute__ ((unused
)))
238 __asm__
__volatile__ ("":::"memory");
245 _gfortran_caf_sync_images (int count
__attribute__ ((unused
)),
246 int images
[] __attribute__ ((unused
)),
248 char *errmsg
__attribute__ ((unused
)),
249 size_t errmsg_len
__attribute__ ((unused
)))
254 for (i
= 0; i
< count
; i
++)
257 fprintf (stderr
, "COARRAY ERROR: Invalid image index %d to SYNC "
258 "IMAGES", images
[i
]);
263 __asm__
__volatile__ ("":::"memory");
270 _gfortran_caf_stop_numeric(int stop_code
, bool quiet
)
273 fprintf (stderr
, "STOP %d\n", stop_code
);
279 _gfortran_caf_stop_str(const char *string
, size_t len
, bool quiet
)
283 fputs ("STOP ", stderr
);
285 fputc (*(string
++), stderr
);
286 fputs ("\n", stderr
);
293 _gfortran_caf_error_stop_str (const char *string
, size_t len
, bool quiet
)
297 fputs ("ERROR STOP ", stderr
);
299 fputc (*(string
++), stderr
);
300 fputs ("\n", stderr
);
306 /* Reported that the program terminated because of a fail image issued.
307 Because this is a single image library, nothing else than aborting the whole
308 program can be done. */
310 void _gfortran_caf_fail_image (void)
312 fputs ("IMAGE FAILED!\n", stderr
);
317 /* Get the status of image IMAGE. Because being the single image library all
318 other images are reported to be stopped. */
320 int _gfortran_caf_image_status (int image
,
321 caf_team_t
* team
__attribute__ ((unused
)))
326 return CAF_STAT_STOPPED_IMAGE
;
330 /* Single image library. There cannot be any failed images with only one
334 _gfortran_caf_failed_images (gfc_descriptor_t
*array
,
335 caf_team_t
* team
__attribute__ ((unused
)),
338 int local_kind
= kind
!= NULL
? *kind
: 4;
340 array
->base_addr
= NULL
;
341 array
->dtype
.type
= BT_INTEGER
;
342 array
->dtype
.elem_len
= local_kind
;
343 /* Setting lower_bound higher then upper_bound is what the compiler does to
344 indicate an empty array. */
345 array
->dim
[0].lower_bound
= 0;
346 array
->dim
[0]._ubound
= -1;
347 array
->dim
[0]._stride
= 1;
352 /* With only one image available no other images can be stopped. Therefore
353 return an empty array. */
356 _gfortran_caf_stopped_images (gfc_descriptor_t
*array
,
357 caf_team_t
* team
__attribute__ ((unused
)),
360 int local_kind
= kind
!= NULL
? *kind
: 4;
362 array
->base_addr
= NULL
;
363 array
->dtype
.type
= BT_INTEGER
;
364 array
->dtype
.elem_len
= local_kind
;
365 /* Setting lower_bound higher then upper_bound is what the compiler does to
366 indicate an empty array. */
367 array
->dim
[0].lower_bound
= 0;
368 array
->dim
[0]._ubound
= -1;
369 array
->dim
[0]._stride
= 1;
375 _gfortran_caf_error_stop (int error
, bool quiet
)
378 fprintf (stderr
, "ERROR STOP %d\n", error
);
384 _gfortran_caf_co_broadcast (gfc_descriptor_t
*a
__attribute__ ((unused
)),
385 int source_image
__attribute__ ((unused
)),
386 int *stat
, char *errmsg
__attribute__ ((unused
)),
387 size_t errmsg_len
__attribute__ ((unused
)))
394 _gfortran_caf_co_sum (gfc_descriptor_t
*a
__attribute__ ((unused
)),
395 int result_image
__attribute__ ((unused
)),
396 int *stat
, char *errmsg
__attribute__ ((unused
)),
397 size_t errmsg_len
__attribute__ ((unused
)))
404 _gfortran_caf_co_min (gfc_descriptor_t
*a
__attribute__ ((unused
)),
405 int result_image
__attribute__ ((unused
)),
406 int *stat
, char *errmsg
__attribute__ ((unused
)),
407 int a_len
__attribute__ ((unused
)),
408 size_t errmsg_len
__attribute__ ((unused
)))
415 _gfortran_caf_co_max (gfc_descriptor_t
*a
__attribute__ ((unused
)),
416 int result_image
__attribute__ ((unused
)),
417 int *stat
, char *errmsg
__attribute__ ((unused
)),
418 int a_len
__attribute__ ((unused
)),
419 size_t errmsg_len
__attribute__ ((unused
)))
427 _gfortran_caf_co_reduce (gfc_descriptor_t
*a
__attribute__ ((unused
)),
428 void * (*opr
) (void *, void *)
429 __attribute__ ((unused
)),
430 int opr_flags
__attribute__ ((unused
)),
431 int result_image
__attribute__ ((unused
)),
432 int *stat
, char *errmsg
__attribute__ ((unused
)),
433 int a_len
__attribute__ ((unused
)),
434 size_t errmsg_len
__attribute__ ((unused
)))
442 assign_char4_from_char1 (size_t dst_size
, size_t src_size
, uint32_t *dst
,
446 n
= dst_size
/4 > src_size
? src_size
: dst_size
/4;
447 for (i
= 0; i
< n
; ++i
)
448 dst
[i
] = (int32_t) src
[i
];
449 for (; i
< dst_size
/4; ++i
)
450 dst
[i
] = (int32_t) ' ';
455 assign_char1_from_char4 (size_t dst_size
, size_t src_size
, unsigned char *dst
,
459 n
= dst_size
> src_size
/4 ? src_size
/4 : dst_size
;
460 for (i
= 0; i
< n
; ++i
)
461 dst
[i
] = src
[i
] > UINT8_MAX
? (unsigned char) '?' : (unsigned char) src
[i
];
463 memset (&dst
[n
], ' ', dst_size
- n
);
468 convert_type (void *dst
, int dst_type
, int dst_kind
, void *src
, int src_type
,
469 int src_kind
, int *stat
)
471 #ifdef HAVE_GFC_INTEGER_16
472 typedef __int128 int128t
;
474 typedef int64_t int128t
;
477 #if defined(GFC_REAL_16_IS_LONG_DOUBLE)
478 typedef long double real128t
;
479 typedef _Complex
long double complex128t
;
480 #elif defined(HAVE_GFC_REAL_16)
481 typedef _Complex
float __attribute__((mode(TC
))) __complex128
;
482 typedef __float128 real128t
;
483 typedef __complex128 complex128t
;
484 #elif defined(HAVE_GFC_REAL_10)
485 typedef long double real128t
;
486 typedef long double complex128t
;
488 typedef double real128t
;
489 typedef _Complex
double complex128t
;
493 real128t real_val
= 0;
494 complex128t cmpx_val
= 0;
500 int_val
= *(int8_t*) src
;
501 else if (src_kind
== 2)
502 int_val
= *(int16_t*) src
;
503 else if (src_kind
== 4)
504 int_val
= *(int32_t*) src
;
505 else if (src_kind
== 8)
506 int_val
= *(int64_t*) src
;
507 #ifdef HAVE_GFC_INTEGER_16
508 else if (src_kind
== 16)
509 int_val
= *(int128t
*) src
;
516 real_val
= *(float*) src
;
517 else if (src_kind
== 8)
518 real_val
= *(double*) src
;
519 #ifdef HAVE_GFC_REAL_10
520 else if (src_kind
== 10)
521 real_val
= *(long double*) src
;
523 #ifdef HAVE_GFC_REAL_16
524 else if (src_kind
== 16)
525 real_val
= *(real128t
*) src
;
532 cmpx_val
= *(_Complex
float*) src
;
533 else if (src_kind
== 8)
534 cmpx_val
= *(_Complex
double*) src
;
535 #ifdef HAVE_GFC_REAL_10
536 else if (src_kind
== 10)
537 cmpx_val
= *(_Complex
long double*) src
;
539 #ifdef HAVE_GFC_REAL_16
540 else if (src_kind
== 16)
541 cmpx_val
= *(complex128t
*) src
;
553 if (src_type
== BT_INTEGER
)
556 *(int8_t*) dst
= (int8_t) int_val
;
557 else if (dst_kind
== 2)
558 *(int16_t*) dst
= (int16_t) int_val
;
559 else if (dst_kind
== 4)
560 *(int32_t*) dst
= (int32_t) int_val
;
561 else if (dst_kind
== 8)
562 *(int64_t*) dst
= (int64_t) int_val
;
563 #ifdef HAVE_GFC_INTEGER_16
564 else if (dst_kind
== 16)
565 *(int128t
*) dst
= (int128t
) int_val
;
570 else if (src_type
== BT_REAL
)
573 *(int8_t*) dst
= (int8_t) real_val
;
574 else if (dst_kind
== 2)
575 *(int16_t*) dst
= (int16_t) real_val
;
576 else if (dst_kind
== 4)
577 *(int32_t*) dst
= (int32_t) real_val
;
578 else if (dst_kind
== 8)
579 *(int64_t*) dst
= (int64_t) real_val
;
580 #ifdef HAVE_GFC_INTEGER_16
581 else if (dst_kind
== 16)
582 *(int128t
*) dst
= (int128t
) real_val
;
587 else if (src_type
== BT_COMPLEX
)
590 *(int8_t*) dst
= (int8_t) cmpx_val
;
591 else if (dst_kind
== 2)
592 *(int16_t*) dst
= (int16_t) cmpx_val
;
593 else if (dst_kind
== 4)
594 *(int32_t*) dst
= (int32_t) cmpx_val
;
595 else if (dst_kind
== 8)
596 *(int64_t*) dst
= (int64_t) cmpx_val
;
597 #ifdef HAVE_GFC_INTEGER_16
598 else if (dst_kind
== 16)
599 *(int128t
*) dst
= (int128t
) cmpx_val
;
608 if (src_type
== BT_INTEGER
)
611 *(float*) dst
= (float) int_val
;
612 else if (dst_kind
== 8)
613 *(double*) dst
= (double) int_val
;
614 #ifdef HAVE_GFC_REAL_10
615 else if (dst_kind
== 10)
616 *(long double*) dst
= (long double) int_val
;
618 #ifdef HAVE_GFC_REAL_16
619 else if (dst_kind
== 16)
620 *(real128t
*) dst
= (real128t
) int_val
;
625 else if (src_type
== BT_REAL
)
628 *(float*) dst
= (float) real_val
;
629 else if (dst_kind
== 8)
630 *(double*) dst
= (double) real_val
;
631 #ifdef HAVE_GFC_REAL_10
632 else if (dst_kind
== 10)
633 *(long double*) dst
= (long double) real_val
;
635 #ifdef HAVE_GFC_REAL_16
636 else if (dst_kind
== 16)
637 *(real128t
*) dst
= (real128t
) real_val
;
642 else if (src_type
== BT_COMPLEX
)
645 *(float*) dst
= (float) cmpx_val
;
646 else if (dst_kind
== 8)
647 *(double*) dst
= (double) cmpx_val
;
648 #ifdef HAVE_GFC_REAL_10
649 else if (dst_kind
== 10)
650 *(long double*) dst
= (long double) cmpx_val
;
652 #ifdef HAVE_GFC_REAL_16
653 else if (dst_kind
== 16)
654 *(real128t
*) dst
= (real128t
) cmpx_val
;
661 if (src_type
== BT_INTEGER
)
664 *(_Complex
float*) dst
= (_Complex
float) int_val
;
665 else if (dst_kind
== 8)
666 *(_Complex
double*) dst
= (_Complex
double) int_val
;
667 #ifdef HAVE_GFC_REAL_10
668 else if (dst_kind
== 10)
669 *(_Complex
long double*) dst
= (_Complex
long double) int_val
;
671 #ifdef HAVE_GFC_REAL_16
672 else if (dst_kind
== 16)
673 *(complex128t
*) dst
= (complex128t
) int_val
;
678 else if (src_type
== BT_REAL
)
681 *(_Complex
float*) dst
= (_Complex
float) real_val
;
682 else if (dst_kind
== 8)
683 *(_Complex
double*) dst
= (_Complex
double) real_val
;
684 #ifdef HAVE_GFC_REAL_10
685 else if (dst_kind
== 10)
686 *(_Complex
long double*) dst
= (_Complex
long double) real_val
;
688 #ifdef HAVE_GFC_REAL_16
689 else if (dst_kind
== 16)
690 *(complex128t
*) dst
= (complex128t
) real_val
;
695 else if (src_type
== BT_COMPLEX
)
698 *(_Complex
float*) dst
= (_Complex
float) cmpx_val
;
699 else if (dst_kind
== 8)
700 *(_Complex
double*) dst
= (_Complex
double) cmpx_val
;
701 #ifdef HAVE_GFC_REAL_10
702 else if (dst_kind
== 10)
703 *(_Complex
long double*) dst
= (_Complex
long double) cmpx_val
;
705 #ifdef HAVE_GFC_REAL_16
706 else if (dst_kind
== 16)
707 *(complex128t
*) dst
= (complex128t
) cmpx_val
;
720 fprintf (stderr
, "libcaf_single RUNTIME ERROR: Cannot convert type %d kind "
721 "%d to type %d kind %d\n", src_type
, src_kind
, dst_type
, dst_kind
);
730 _gfortran_caf_get (caf_token_t token
, size_t offset
,
731 int image_index
__attribute__ ((unused
)),
732 gfc_descriptor_t
*src
,
733 caf_vector_t
*src_vector
__attribute__ ((unused
)),
734 gfc_descriptor_t
*dest
, int src_kind
, int dst_kind
,
735 bool may_require_tmp
, int *stat
)
737 /* FIXME: Handle vector subscripts. */
740 int rank
= GFC_DESCRIPTOR_RANK (dest
);
741 size_t src_size
= GFC_DESCRIPTOR_SIZE (src
);
742 size_t dst_size
= GFC_DESCRIPTOR_SIZE (dest
);
749 void *sr
= (void *) ((char *) MEMTOK (token
) + offset
);
750 if (GFC_DESCRIPTOR_TYPE (dest
) == GFC_DESCRIPTOR_TYPE (src
)
751 && dst_kind
== src_kind
)
753 memmove (GFC_DESCRIPTOR_DATA (dest
), sr
,
754 dst_size
> src_size
? src_size
: dst_size
);
755 if (GFC_DESCRIPTOR_TYPE (dest
) == BT_CHARACTER
&& dst_size
> src_size
)
758 memset ((void*)(char*) GFC_DESCRIPTOR_DATA (dest
) + src_size
,
759 ' ', dst_size
- src_size
);
760 else /* dst_kind == 4. */
761 for (i
= src_size
/4; i
< dst_size
/4; i
++)
762 ((int32_t*) GFC_DESCRIPTOR_DATA (dest
))[i
] = (int32_t) ' ';
765 else if (GFC_DESCRIPTOR_TYPE (dest
) == BT_CHARACTER
&& dst_kind
== 1)
766 assign_char1_from_char4 (dst_size
, src_size
, GFC_DESCRIPTOR_DATA (dest
),
768 else if (GFC_DESCRIPTOR_TYPE (dest
) == BT_CHARACTER
)
769 assign_char4_from_char1 (dst_size
, src_size
, GFC_DESCRIPTOR_DATA (dest
),
772 convert_type (GFC_DESCRIPTOR_DATA (dest
), GFC_DESCRIPTOR_TYPE (dest
),
773 dst_kind
, sr
, GFC_DESCRIPTOR_TYPE (src
), src_kind
, stat
);
778 for (j
= 0; j
< rank
; j
++)
780 ptrdiff_t dimextent
= dest
->dim
[j
]._ubound
- dest
->dim
[j
].lower_bound
+ 1;
791 ptrdiff_t array_offset_sr
, array_offset_dst
;
792 void *tmp
= malloc (size
*src_size
);
794 array_offset_dst
= 0;
795 for (i
= 0; i
< size
; i
++)
797 ptrdiff_t array_offset_sr
= 0;
798 ptrdiff_t stride
= 1;
799 ptrdiff_t extent
= 1;
800 for (j
= 0; j
< GFC_DESCRIPTOR_RANK (src
)-1; j
++)
802 array_offset_sr
+= ((i
/ (extent
*stride
))
803 % (src
->dim
[j
]._ubound
804 - src
->dim
[j
].lower_bound
+ 1))
805 * src
->dim
[j
]._stride
;
806 extent
= (src
->dim
[j
]._ubound
- src
->dim
[j
].lower_bound
+ 1);
807 stride
= src
->dim
[j
]._stride
;
809 array_offset_sr
+= (i
/ extent
) * src
->dim
[rank
-1]._stride
;
810 void *sr
= (void *)((char *) MEMTOK (token
) + offset
811 + array_offset_sr
*GFC_DESCRIPTOR_SIZE (src
));
812 memcpy ((void *) ((char *) tmp
+ array_offset_dst
), sr
, src_size
);
813 array_offset_dst
+= src_size
;
817 for (i
= 0; i
< size
; i
++)
819 ptrdiff_t array_offset_dst
= 0;
820 ptrdiff_t stride
= 1;
821 ptrdiff_t extent
= 1;
822 for (j
= 0; j
< rank
-1; j
++)
824 array_offset_dst
+= ((i
/ (extent
*stride
))
825 % (dest
->dim
[j
]._ubound
826 - dest
->dim
[j
].lower_bound
+ 1))
827 * dest
->dim
[j
]._stride
;
828 extent
= (dest
->dim
[j
]._ubound
- dest
->dim
[j
].lower_bound
+ 1);
829 stride
= dest
->dim
[j
]._stride
;
831 array_offset_dst
+= (i
/ extent
) * dest
->dim
[rank
-1]._stride
;
832 void *dst
= dest
->base_addr
833 + array_offset_dst
*GFC_DESCRIPTOR_SIZE (dest
);
834 void *sr
= tmp
+ array_offset_sr
;
836 if (GFC_DESCRIPTOR_TYPE (dest
) == GFC_DESCRIPTOR_TYPE (src
)
837 && dst_kind
== src_kind
)
839 memmove (dst
, sr
, dst_size
> src_size
? src_size
: dst_size
);
840 if (GFC_DESCRIPTOR_TYPE (dest
) == BT_CHARACTER
841 && dst_size
> src_size
)
844 memset ((void*)(char*) dst
+ src_size
, ' ',
846 else /* dst_kind == 4. */
847 for (k
= src_size
/4; k
< dst_size
/4; k
++)
848 ((int32_t*) dst
)[k
] = (int32_t) ' ';
851 else if (GFC_DESCRIPTOR_TYPE (dest
) == BT_CHARACTER
&& dst_kind
== 1)
852 assign_char1_from_char4 (dst_size
, src_size
, dst
, sr
);
853 else if (GFC_DESCRIPTOR_TYPE (dest
) == BT_CHARACTER
)
854 assign_char4_from_char1 (dst_size
, src_size
, dst
, sr
);
856 convert_type (dst
, GFC_DESCRIPTOR_TYPE (dest
), dst_kind
,
857 sr
, GFC_DESCRIPTOR_TYPE (src
), src_kind
, stat
);
858 array_offset_sr
+= src_size
;
865 for (i
= 0; i
< size
; i
++)
867 ptrdiff_t array_offset_dst
= 0;
868 ptrdiff_t stride
= 1;
869 ptrdiff_t extent
= 1;
870 for (j
= 0; j
< rank
-1; j
++)
872 array_offset_dst
+= ((i
/ (extent
*stride
))
873 % (dest
->dim
[j
]._ubound
874 - dest
->dim
[j
].lower_bound
+ 1))
875 * dest
->dim
[j
]._stride
;
876 extent
= (dest
->dim
[j
]._ubound
- dest
->dim
[j
].lower_bound
+ 1);
877 stride
= dest
->dim
[j
]._stride
;
879 array_offset_dst
+= (i
/ extent
) * dest
->dim
[rank
-1]._stride
;
880 void *dst
= dest
->base_addr
+ array_offset_dst
*GFC_DESCRIPTOR_SIZE (dest
);
882 ptrdiff_t array_offset_sr
= 0;
885 for (j
= 0; j
< GFC_DESCRIPTOR_RANK (src
)-1; j
++)
887 array_offset_sr
+= ((i
/ (extent
*stride
))
888 % (src
->dim
[j
]._ubound
889 - src
->dim
[j
].lower_bound
+ 1))
890 * src
->dim
[j
]._stride
;
891 extent
= (src
->dim
[j
]._ubound
- src
->dim
[j
].lower_bound
+ 1);
892 stride
= src
->dim
[j
]._stride
;
894 array_offset_sr
+= (i
/ extent
) * src
->dim
[rank
-1]._stride
;
895 void *sr
= (void *)((char *) MEMTOK (token
) + offset
896 + array_offset_sr
*GFC_DESCRIPTOR_SIZE (src
));
898 if (GFC_DESCRIPTOR_TYPE (dest
) == GFC_DESCRIPTOR_TYPE (src
)
899 && dst_kind
== src_kind
)
901 memmove (dst
, sr
, dst_size
> src_size
? src_size
: dst_size
);
902 if (GFC_DESCRIPTOR_TYPE (dest
) == BT_CHARACTER
&& dst_size
> src_size
)
905 memset ((void*)(char*) dst
+ src_size
, ' ', dst_size
-src_size
);
906 else /* dst_kind == 4. */
907 for (k
= src_size
/4; k
< dst_size
/4; k
++)
908 ((int32_t*) dst
)[k
] = (int32_t) ' ';
911 else if (GFC_DESCRIPTOR_TYPE (dest
) == BT_CHARACTER
&& dst_kind
== 1)
912 assign_char1_from_char4 (dst_size
, src_size
, dst
, sr
);
913 else if (GFC_DESCRIPTOR_TYPE (dest
) == BT_CHARACTER
)
914 assign_char4_from_char1 (dst_size
, src_size
, dst
, sr
);
916 convert_type (dst
, GFC_DESCRIPTOR_TYPE (dest
), dst_kind
,
917 sr
, GFC_DESCRIPTOR_TYPE (src
), src_kind
, stat
);
923 _gfortran_caf_send (caf_token_t token
, size_t offset
,
924 int image_index
__attribute__ ((unused
)),
925 gfc_descriptor_t
*dest
,
926 caf_vector_t
*dst_vector
__attribute__ ((unused
)),
927 gfc_descriptor_t
*src
, int dst_kind
, int src_kind
,
928 bool may_require_tmp
, int *stat
)
930 /* FIXME: Handle vector subscripts. */
933 int rank
= GFC_DESCRIPTOR_RANK (dest
);
934 size_t src_size
= GFC_DESCRIPTOR_SIZE (src
);
935 size_t dst_size
= GFC_DESCRIPTOR_SIZE (dest
);
942 void *dst
= (void *) ((char *) MEMTOK (token
) + offset
);
943 if (GFC_DESCRIPTOR_TYPE (dest
) == GFC_DESCRIPTOR_TYPE (src
)
944 && dst_kind
== src_kind
)
946 memmove (dst
, GFC_DESCRIPTOR_DATA (src
),
947 dst_size
> src_size
? src_size
: dst_size
);
948 if (GFC_DESCRIPTOR_TYPE (dest
) == BT_CHARACTER
&& dst_size
> src_size
)
951 memset ((void*)(char*) dst
+ src_size
, ' ', dst_size
-src_size
);
952 else /* dst_kind == 4. */
953 for (i
= src_size
/4; i
< dst_size
/4; i
++)
954 ((int32_t*) dst
)[i
] = (int32_t) ' ';
957 else if (GFC_DESCRIPTOR_TYPE (dest
) == BT_CHARACTER
&& dst_kind
== 1)
958 assign_char1_from_char4 (dst_size
, src_size
, dst
,
959 GFC_DESCRIPTOR_DATA (src
));
960 else if (GFC_DESCRIPTOR_TYPE (dest
) == BT_CHARACTER
)
961 assign_char4_from_char1 (dst_size
, src_size
, dst
,
962 GFC_DESCRIPTOR_DATA (src
));
964 convert_type (dst
, GFC_DESCRIPTOR_TYPE (dest
), dst_kind
,
965 GFC_DESCRIPTOR_DATA (src
), GFC_DESCRIPTOR_TYPE (src
),
971 for (j
= 0; j
< rank
; j
++)
973 ptrdiff_t dimextent
= dest
->dim
[j
]._ubound
- dest
->dim
[j
].lower_bound
+ 1;
984 ptrdiff_t array_offset_sr
, array_offset_dst
;
987 if (GFC_DESCRIPTOR_RANK (src
) == 0)
989 tmp
= malloc (src_size
);
990 memcpy (tmp
, GFC_DESCRIPTOR_DATA (src
), src_size
);
994 tmp
= malloc (size
*src_size
);
995 array_offset_dst
= 0;
996 for (i
= 0; i
< size
; i
++)
998 ptrdiff_t array_offset_sr
= 0;
999 ptrdiff_t stride
= 1;
1000 ptrdiff_t extent
= 1;
1001 for (j
= 0; j
< GFC_DESCRIPTOR_RANK (src
)-1; j
++)
1003 array_offset_sr
+= ((i
/ (extent
*stride
))
1004 % (src
->dim
[j
]._ubound
1005 - src
->dim
[j
].lower_bound
+ 1))
1006 * src
->dim
[j
]._stride
;
1007 extent
= (src
->dim
[j
]._ubound
- src
->dim
[j
].lower_bound
+ 1);
1008 stride
= src
->dim
[j
]._stride
;
1010 array_offset_sr
+= (i
/ extent
) * src
->dim
[rank
-1]._stride
;
1011 void *sr
= (void *) ((char *) src
->base_addr
1012 + array_offset_sr
*GFC_DESCRIPTOR_SIZE (src
));
1013 memcpy ((void *) ((char *) tmp
+ array_offset_dst
), sr
, src_size
);
1014 array_offset_dst
+= src_size
;
1018 array_offset_sr
= 0;
1019 for (i
= 0; i
< size
; i
++)
1021 ptrdiff_t array_offset_dst
= 0;
1022 ptrdiff_t stride
= 1;
1023 ptrdiff_t extent
= 1;
1024 for (j
= 0; j
< rank
-1; j
++)
1026 array_offset_dst
+= ((i
/ (extent
*stride
))
1027 % (dest
->dim
[j
]._ubound
1028 - dest
->dim
[j
].lower_bound
+ 1))
1029 * dest
->dim
[j
]._stride
;
1030 extent
= (dest
->dim
[j
]._ubound
- dest
->dim
[j
].lower_bound
+ 1);
1031 stride
= dest
->dim
[j
]._stride
;
1033 array_offset_dst
+= (i
/ extent
) * dest
->dim
[rank
-1]._stride
;
1034 void *dst
= (void *)((char *) MEMTOK (token
) + offset
1035 + array_offset_dst
*GFC_DESCRIPTOR_SIZE (dest
));
1036 void *sr
= tmp
+ array_offset_sr
;
1037 if (GFC_DESCRIPTOR_TYPE (dest
) == GFC_DESCRIPTOR_TYPE (src
)
1038 && dst_kind
== src_kind
)
1041 dst_size
> src_size
? src_size
: dst_size
);
1042 if (GFC_DESCRIPTOR_TYPE (dest
) == BT_CHARACTER
1043 && dst_size
> src_size
)
1046 memset ((void*)(char*) dst
+ src_size
, ' ',
1048 else /* dst_kind == 4. */
1049 for (k
= src_size
/4; k
< dst_size
/4; k
++)
1050 ((int32_t*) dst
)[k
] = (int32_t) ' ';
1053 else if (GFC_DESCRIPTOR_TYPE (dest
) == BT_CHARACTER
&& dst_kind
== 1)
1054 assign_char1_from_char4 (dst_size
, src_size
, dst
, sr
);
1055 else if (GFC_DESCRIPTOR_TYPE (dest
) == BT_CHARACTER
)
1056 assign_char4_from_char1 (dst_size
, src_size
, dst
, sr
);
1058 convert_type (dst
, GFC_DESCRIPTOR_TYPE (dest
), dst_kind
,
1059 sr
, GFC_DESCRIPTOR_TYPE (src
), src_kind
, stat
);
1060 if (GFC_DESCRIPTOR_RANK (src
))
1061 array_offset_sr
+= src_size
;
1067 for (i
= 0; i
< size
; i
++)
1069 ptrdiff_t array_offset_dst
= 0;
1070 ptrdiff_t stride
= 1;
1071 ptrdiff_t extent
= 1;
1072 for (j
= 0; j
< rank
-1; j
++)
1074 array_offset_dst
+= ((i
/ (extent
*stride
))
1075 % (dest
->dim
[j
]._ubound
1076 - dest
->dim
[j
].lower_bound
+ 1))
1077 * dest
->dim
[j
]._stride
;
1078 extent
= (dest
->dim
[j
]._ubound
- dest
->dim
[j
].lower_bound
+ 1);
1079 stride
= dest
->dim
[j
]._stride
;
1081 array_offset_dst
+= (i
/ extent
) * dest
->dim
[rank
-1]._stride
;
1082 void *dst
= (void *)((char *) MEMTOK (token
) + offset
1083 + array_offset_dst
*GFC_DESCRIPTOR_SIZE (dest
));
1085 if (GFC_DESCRIPTOR_RANK (src
) != 0)
1087 ptrdiff_t array_offset_sr
= 0;
1090 for (j
= 0; j
< GFC_DESCRIPTOR_RANK (src
)-1; j
++)
1092 array_offset_sr
+= ((i
/ (extent
*stride
))
1093 % (src
->dim
[j
]._ubound
1094 - src
->dim
[j
].lower_bound
+ 1))
1095 * src
->dim
[j
]._stride
;
1096 extent
= (src
->dim
[j
]._ubound
- src
->dim
[j
].lower_bound
+ 1);
1097 stride
= src
->dim
[j
]._stride
;
1099 array_offset_sr
+= (i
/ extent
) * src
->dim
[rank
-1]._stride
;
1100 sr
= (void *)((char *) src
->base_addr
1101 + array_offset_sr
*GFC_DESCRIPTOR_SIZE (src
));
1104 sr
= src
->base_addr
;
1106 if (GFC_DESCRIPTOR_TYPE (dest
) == GFC_DESCRIPTOR_TYPE (src
)
1107 && dst_kind
== src_kind
)
1110 dst_size
> src_size
? src_size
: dst_size
);
1111 if (GFC_DESCRIPTOR_TYPE (dest
) == BT_CHARACTER
&& dst_size
> src_size
)
1114 memset ((void*)(char*) dst
+ src_size
, ' ', dst_size
-src_size
);
1115 else /* dst_kind == 4. */
1116 for (k
= src_size
/4; k
< dst_size
/4; k
++)
1117 ((int32_t*) dst
)[k
] = (int32_t) ' ';
1120 else if (GFC_DESCRIPTOR_TYPE (dest
) == BT_CHARACTER
&& dst_kind
== 1)
1121 assign_char1_from_char4 (dst_size
, src_size
, dst
, sr
);
1122 else if (GFC_DESCRIPTOR_TYPE (dest
) == BT_CHARACTER
)
1123 assign_char4_from_char1 (dst_size
, src_size
, dst
, sr
);
1125 convert_type (dst
, GFC_DESCRIPTOR_TYPE (dest
), dst_kind
,
1126 sr
, GFC_DESCRIPTOR_TYPE (src
), src_kind
, stat
);
1132 _gfortran_caf_sendget (caf_token_t dst_token
, size_t dst_offset
,
1133 int dst_image_index
, gfc_descriptor_t
*dest
,
1134 caf_vector_t
*dst_vector
, caf_token_t src_token
,
1136 int src_image_index
__attribute__ ((unused
)),
1137 gfc_descriptor_t
*src
,
1138 caf_vector_t
*src_vector
__attribute__ ((unused
)),
1139 int dst_kind
, int src_kind
, bool may_require_tmp
)
1141 /* FIXME: Handle vector subscript of 'src_vector'. */
1142 /* For a single image, src->base_addr should be the same as src_token + offset
1143 but to play save, we do it properly. */
1144 void *src_base
= GFC_DESCRIPTOR_DATA (src
);
1145 GFC_DESCRIPTOR_DATA (src
) = (void *) ((char *) MEMTOK (src_token
)
1147 _gfortran_caf_send (dst_token
, dst_offset
, dst_image_index
, dest
, dst_vector
,
1148 src
, dst_kind
, src_kind
, may_require_tmp
, NULL
);
1149 GFC_DESCRIPTOR_DATA (src
) = src_base
;
1153 /* Emitted when a theorectically unreachable part is reached. */
1154 const char unreachable
[] = "Fatal error: unreachable alternative found.\n";
1158 copy_data (void *ds
, void *sr
, int dst_type
, int src_type
,
1159 int dst_kind
, int src_kind
, size_t dst_size
, size_t src_size
,
1160 size_t num
, int *stat
)
1163 if (dst_type
== src_type
&& dst_kind
== src_kind
)
1165 memmove (ds
, sr
, (dst_size
> src_size
? src_size
: dst_size
) * num
);
1166 if ((dst_type
== BT_CHARACTER
|| src_type
== BT_CHARACTER
)
1167 && dst_size
> src_size
)
1170 memset ((void*)(char*) ds
+ src_size
, ' ', dst_size
-src_size
);
1171 else /* dst_kind == 4. */
1172 for (k
= src_size
/4; k
< dst_size
/4; k
++)
1173 ((int32_t*) ds
)[k
] = (int32_t) ' ';
1176 else if (dst_type
== BT_CHARACTER
&& dst_kind
== 1)
1177 assign_char1_from_char4 (dst_size
, src_size
, ds
, sr
);
1178 else if (dst_type
== BT_CHARACTER
)
1179 assign_char4_from_char1 (dst_size
, src_size
, ds
, sr
);
1181 for (k
= 0; k
< num
; ++k
)
1183 convert_type (ds
, dst_type
, dst_kind
, sr
, src_type
, src_kind
, stat
);
1190 #define COMPUTE_NUM_ITEMS(num, stride, lb, ub) \
1192 index_type abs_stride = (stride) > 0 ? (stride) : -(stride); \
1193 num = (stride) > 0 ? (ub) + 1 - (lb) : (lb) + 1 - (ub); \
1194 if (num <= 0 || abs_stride < 1) return; \
1195 num = (abs_stride > 1) ? (1 + (num - 1) / abs_stride) : num; \
1200 get_for_ref (caf_reference_t
*ref
, size_t *i
, size_t *dst_index
,
1201 caf_single_token_t single_token
, gfc_descriptor_t
*dst
,
1202 gfc_descriptor_t
*src
, void *ds
, void *sr
,
1203 int dst_kind
, int src_kind
, size_t dst_dim
, size_t src_dim
,
1204 size_t num
, int *stat
, int src_type
)
1206 ptrdiff_t extent_src
= 1, array_offset_src
= 0, stride_src
;
1207 size_t next_dst_dim
;
1209 if (unlikely (ref
== NULL
))
1210 /* May be we should issue an error here, because this case should not
1214 if (ref
->next
== NULL
)
1216 size_t dst_size
= GFC_DESCRIPTOR_SIZE (dst
);
1217 ptrdiff_t array_offset_dst
= 0;;
1218 size_t dst_rank
= GFC_DESCRIPTOR_RANK (dst
);
1222 case CAF_REF_COMPONENT
:
1223 /* Because the token is always registered after the component, its
1224 offset is always greater zero. */
1225 if (ref
->u
.c
.caf_token_offset
> 0)
1226 /* Note, that sr is dereffed here. */
1227 copy_data (ds
, *(void **)(sr
+ ref
->u
.c
.offset
),
1228 GFC_DESCRIPTOR_TYPE (dst
), src_type
,
1229 dst_kind
, src_kind
, dst_size
, ref
->item_size
, 1, stat
);
1231 copy_data (ds
, sr
+ ref
->u
.c
.offset
,
1232 GFC_DESCRIPTOR_TYPE (dst
), src_type
,
1233 dst_kind
, src_kind
, dst_size
, ref
->item_size
, 1, stat
);
1236 case CAF_REF_STATIC_ARRAY
:
1237 /* Intentionally fall through. */
1239 if (ref
->u
.a
.mode
[src_dim
] == CAF_ARR_REF_NONE
)
1241 for (size_t d
= 0; d
< dst_rank
; ++d
)
1242 array_offset_dst
+= dst_index
[d
];
1243 copy_data (ds
+ array_offset_dst
* dst_size
, sr
,
1244 GFC_DESCRIPTOR_TYPE (dst
), src_type
,
1245 dst_kind
, src_kind
, dst_size
, ref
->item_size
, num
,
1252 caf_runtime_error (unreachable
);
1258 case CAF_REF_COMPONENT
:
1259 if (ref
->u
.c
.caf_token_offset
> 0)
1261 single_token
= *(caf_single_token_t
*)(sr
+ ref
->u
.c
.caf_token_offset
);
1263 if (ref
->next
&& ref
->next
->type
== CAF_REF_ARRAY
)
1264 src
= single_token
->desc
;
1268 if (ref
->next
&& ref
->next
->type
== CAF_REF_COMPONENT
)
1269 /* The currently ref'ed component was allocatabe (caf_token_offset
1270 > 0) and the next ref is a component, too, then the new sr has to
1271 be dereffed. (static arrays cannot be allocatable or they
1272 become an array with descriptor. */
1273 sr
= *(void **)(sr
+ ref
->u
.c
.offset
);
1275 sr
+= ref
->u
.c
.offset
;
1277 get_for_ref (ref
->next
, i
, dst_index
, single_token
, dst
, src
,
1278 ds
, sr
, dst_kind
, src_kind
, dst_dim
, 0,
1282 get_for_ref (ref
->next
, i
, dst_index
, single_token
, dst
,
1283 (gfc_descriptor_t
*)(sr
+ ref
->u
.c
.offset
), ds
,
1284 sr
+ ref
->u
.c
.offset
, dst_kind
, src_kind
, dst_dim
, 0, 1,
1288 if (ref
->u
.a
.mode
[src_dim
] == CAF_ARR_REF_NONE
)
1290 get_for_ref (ref
->next
, i
, dst_index
, single_token
, dst
,
1291 src
, ds
, sr
, dst_kind
, src_kind
,
1292 dst_dim
, 0, 1, stat
, src_type
);
1295 /* Only when on the left most index switch the data pointer to
1296 the array's data pointer. */
1298 sr
= GFC_DESCRIPTOR_DATA (src
);
1299 switch (ref
->u
.a
.mode
[src_dim
])
1301 case CAF_ARR_REF_VECTOR
:
1302 extent_src
= GFC_DIMENSION_EXTENT (src
->dim
[src_dim
]);
1303 array_offset_src
= 0;
1304 dst_index
[dst_dim
] = 0;
1305 for (size_t idx
= 0; idx
< ref
->u
.a
.dim
[src_dim
].v
.nvec
;
1308 #define KINDCASE(kind, type) case kind: \
1309 array_offset_src = (((index_type) \
1310 ((type *)ref->u.a.dim[src_dim].v.vector)[idx]) \
1311 - GFC_DIMENSION_LBOUND (src->dim[src_dim])) \
1312 * GFC_DIMENSION_STRIDE (src->dim[src_dim]); \
1315 switch (ref
->u
.a
.dim
[src_dim
].v
.kind
)
1317 KINDCASE (1, GFC_INTEGER_1
);
1318 KINDCASE (2, GFC_INTEGER_2
);
1319 KINDCASE (4, GFC_INTEGER_4
);
1320 #ifdef HAVE_GFC_INTEGER_8
1321 KINDCASE (8, GFC_INTEGER_8
);
1323 #ifdef HAVE_GFC_INTEGER_16
1324 KINDCASE (16, GFC_INTEGER_16
);
1327 caf_runtime_error (unreachable
);
1332 get_for_ref (ref
, i
, dst_index
, single_token
, dst
, src
,
1333 ds
, sr
+ array_offset_src
* ref
->item_size
,
1334 dst_kind
, src_kind
, dst_dim
+ 1, src_dim
+ 1,
1337 += GFC_DIMENSION_STRIDE (dst
->dim
[dst_dim
]);
1340 case CAF_ARR_REF_FULL
:
1341 COMPUTE_NUM_ITEMS (extent_src
,
1342 ref
->u
.a
.dim
[src_dim
].s
.stride
,
1343 GFC_DIMENSION_LBOUND (src
->dim
[src_dim
]),
1344 GFC_DIMENSION_UBOUND (src
->dim
[src_dim
]));
1345 stride_src
= src
->dim
[src_dim
]._stride
1346 * ref
->u
.a
.dim
[src_dim
].s
.stride
;
1347 array_offset_src
= 0;
1348 dst_index
[dst_dim
] = 0;
1349 for (index_type idx
= 0; idx
< extent_src
;
1350 ++idx
, array_offset_src
+= stride_src
)
1352 get_for_ref (ref
, i
, dst_index
, single_token
, dst
, src
,
1353 ds
, sr
+ array_offset_src
* ref
->item_size
,
1354 dst_kind
, src_kind
, dst_dim
+ 1, src_dim
+ 1,
1357 += GFC_DIMENSION_STRIDE (dst
->dim
[dst_dim
]);
1360 case CAF_ARR_REF_RANGE
:
1361 COMPUTE_NUM_ITEMS (extent_src
,
1362 ref
->u
.a
.dim
[src_dim
].s
.stride
,
1363 ref
->u
.a
.dim
[src_dim
].s
.start
,
1364 ref
->u
.a
.dim
[src_dim
].s
.end
);
1365 array_offset_src
= (ref
->u
.a
.dim
[src_dim
].s
.start
1366 - GFC_DIMENSION_LBOUND (src
->dim
[src_dim
]))
1367 * GFC_DIMENSION_STRIDE (src
->dim
[src_dim
]);
1368 stride_src
= GFC_DIMENSION_STRIDE (src
->dim
[src_dim
])
1369 * ref
->u
.a
.dim
[src_dim
].s
.stride
;
1370 dst_index
[dst_dim
] = 0;
1371 /* Increase the dst_dim only, when the src_extent is greater one
1372 or src and dst extent are both one. Don't increase when the scalar
1373 source is not present in the dst. */
1374 next_dst_dim
= extent_src
> 1
1375 || (GFC_DIMENSION_EXTENT (dst
->dim
[dst_dim
]) == 1
1376 && extent_src
== 1) ? (dst_dim
+ 1) : dst_dim
;
1377 for (index_type idx
= 0; idx
< extent_src
; ++idx
)
1379 get_for_ref (ref
, i
, dst_index
, single_token
, dst
, src
,
1380 ds
, sr
+ array_offset_src
* ref
->item_size
,
1381 dst_kind
, src_kind
, next_dst_dim
, src_dim
+ 1,
1384 += GFC_DIMENSION_STRIDE (dst
->dim
[dst_dim
]);
1385 array_offset_src
+= stride_src
;
1388 case CAF_ARR_REF_SINGLE
:
1389 array_offset_src
= (ref
->u
.a
.dim
[src_dim
].s
.start
1390 - src
->dim
[src_dim
].lower_bound
)
1391 * GFC_DIMENSION_STRIDE (src
->dim
[src_dim
]);
1392 dst_index
[dst_dim
] = 0;
1393 get_for_ref (ref
, i
, dst_index
, single_token
, dst
, src
, ds
,
1394 sr
+ array_offset_src
* ref
->item_size
,
1395 dst_kind
, src_kind
, dst_dim
, src_dim
+ 1, 1,
1398 case CAF_ARR_REF_OPEN_END
:
1399 COMPUTE_NUM_ITEMS (extent_src
,
1400 ref
->u
.a
.dim
[src_dim
].s
.stride
,
1401 ref
->u
.a
.dim
[src_dim
].s
.start
,
1402 GFC_DIMENSION_UBOUND (src
->dim
[src_dim
]));
1403 stride_src
= GFC_DIMENSION_STRIDE (src
->dim
[src_dim
])
1404 * ref
->u
.a
.dim
[src_dim
].s
.stride
;
1405 array_offset_src
= (ref
->u
.a
.dim
[src_dim
].s
.start
1406 - GFC_DIMENSION_LBOUND (src
->dim
[src_dim
]))
1407 * GFC_DIMENSION_STRIDE (src
->dim
[src_dim
]);
1408 dst_index
[dst_dim
] = 0;
1409 for (index_type idx
= 0; idx
< extent_src
; ++idx
)
1411 get_for_ref (ref
, i
, dst_index
, single_token
, dst
, src
,
1412 ds
, sr
+ array_offset_src
* ref
->item_size
,
1413 dst_kind
, src_kind
, dst_dim
+ 1, src_dim
+ 1,
1416 += GFC_DIMENSION_STRIDE (dst
->dim
[dst_dim
]);
1417 array_offset_src
+= stride_src
;
1420 case CAF_ARR_REF_OPEN_START
:
1421 COMPUTE_NUM_ITEMS (extent_src
,
1422 ref
->u
.a
.dim
[src_dim
].s
.stride
,
1423 GFC_DIMENSION_LBOUND (src
->dim
[src_dim
]),
1424 ref
->u
.a
.dim
[src_dim
].s
.end
);
1425 stride_src
= GFC_DIMENSION_STRIDE (src
->dim
[src_dim
])
1426 * ref
->u
.a
.dim
[src_dim
].s
.stride
;
1427 array_offset_src
= 0;
1428 dst_index
[dst_dim
] = 0;
1429 for (index_type idx
= 0; idx
< extent_src
; ++idx
)
1431 get_for_ref (ref
, i
, dst_index
, single_token
, dst
, src
,
1432 ds
, sr
+ array_offset_src
* ref
->item_size
,
1433 dst_kind
, src_kind
, dst_dim
+ 1, src_dim
+ 1,
1436 += GFC_DIMENSION_STRIDE (dst
->dim
[dst_dim
]);
1437 array_offset_src
+= stride_src
;
1441 caf_runtime_error (unreachable
);
1444 case CAF_REF_STATIC_ARRAY
:
1445 if (ref
->u
.a
.mode
[src_dim
] == CAF_ARR_REF_NONE
)
1447 get_for_ref (ref
->next
, i
, dst_index
, single_token
, dst
,
1448 NULL
, ds
, sr
, dst_kind
, src_kind
,
1449 dst_dim
, 0, 1, stat
, src_type
);
1452 switch (ref
->u
.a
.mode
[src_dim
])
1454 case CAF_ARR_REF_VECTOR
:
1455 array_offset_src
= 0;
1456 dst_index
[dst_dim
] = 0;
1457 for (size_t idx
= 0; idx
< ref
->u
.a
.dim
[src_dim
].v
.nvec
;
1460 #define KINDCASE(kind, type) case kind: \
1461 array_offset_src = ((type *)ref->u.a.dim[src_dim].v.vector)[idx]; \
1464 switch (ref
->u
.a
.dim
[src_dim
].v
.kind
)
1466 KINDCASE (1, GFC_INTEGER_1
);
1467 KINDCASE (2, GFC_INTEGER_2
);
1468 KINDCASE (4, GFC_INTEGER_4
);
1469 #ifdef HAVE_GFC_INTEGER_8
1470 KINDCASE (8, GFC_INTEGER_8
);
1472 #ifdef HAVE_GFC_INTEGER_16
1473 KINDCASE (16, GFC_INTEGER_16
);
1476 caf_runtime_error (unreachable
);
1481 get_for_ref (ref
, i
, dst_index
, single_token
, dst
, NULL
,
1482 ds
, sr
+ array_offset_src
* ref
->item_size
,
1483 dst_kind
, src_kind
, dst_dim
+ 1, src_dim
+ 1,
1486 += GFC_DIMENSION_STRIDE (dst
->dim
[dst_dim
]);
1489 case CAF_ARR_REF_FULL
:
1490 dst_index
[dst_dim
] = 0;
1491 for (array_offset_src
= 0 ;
1492 array_offset_src
<= ref
->u
.a
.dim
[src_dim
].s
.end
;
1493 array_offset_src
+= ref
->u
.a
.dim
[src_dim
].s
.stride
)
1495 get_for_ref (ref
, i
, dst_index
, single_token
, dst
, NULL
,
1496 ds
, sr
+ array_offset_src
* ref
->item_size
,
1497 dst_kind
, src_kind
, dst_dim
+ 1, src_dim
+ 1,
1500 += GFC_DIMENSION_STRIDE (dst
->dim
[dst_dim
]);
1503 case CAF_ARR_REF_RANGE
:
1504 COMPUTE_NUM_ITEMS (extent_src
,
1505 ref
->u
.a
.dim
[src_dim
].s
.stride
,
1506 ref
->u
.a
.dim
[src_dim
].s
.start
,
1507 ref
->u
.a
.dim
[src_dim
].s
.end
);
1508 array_offset_src
= ref
->u
.a
.dim
[src_dim
].s
.start
;
1509 dst_index
[dst_dim
] = 0;
1510 for (index_type idx
= 0; idx
< extent_src
; ++idx
)
1512 get_for_ref (ref
, i
, dst_index
, single_token
, dst
, NULL
,
1513 ds
, sr
+ array_offset_src
* ref
->item_size
,
1514 dst_kind
, src_kind
, dst_dim
+ 1, src_dim
+ 1,
1517 += GFC_DIMENSION_STRIDE (dst
->dim
[dst_dim
]);
1518 array_offset_src
+= ref
->u
.a
.dim
[src_dim
].s
.stride
;
1521 case CAF_ARR_REF_SINGLE
:
1522 array_offset_src
= ref
->u
.a
.dim
[src_dim
].s
.start
;
1523 get_for_ref (ref
, i
, dst_index
, single_token
, dst
, NULL
, ds
,
1524 sr
+ array_offset_src
* ref
->item_size
,
1525 dst_kind
, src_kind
, dst_dim
, src_dim
+ 1, 1,
1528 /* The OPEN_* are mapped to a RANGE and therefore cannot occur. */
1529 case CAF_ARR_REF_OPEN_END
:
1530 case CAF_ARR_REF_OPEN_START
:
1532 caf_runtime_error (unreachable
);
1536 caf_runtime_error (unreachable
);
1542 _gfortran_caf_get_by_ref (caf_token_t token
,
1543 int image_index
__attribute__ ((unused
)),
1544 gfc_descriptor_t
*dst
, caf_reference_t
*refs
,
1545 int dst_kind
, int src_kind
,
1546 bool may_require_tmp
__attribute__ ((unused
)),
1547 bool dst_reallocatable
, int *stat
,
1550 const char vecrefunknownkind
[] = "libcaf_single::caf_get_by_ref(): "
1551 "unknown kind in vector-ref.\n";
1552 const char unknownreftype
[] = "libcaf_single::caf_get_by_ref(): "
1553 "unknown reference type.\n";
1554 const char unknownarrreftype
[] = "libcaf_single::caf_get_by_ref(): "
1555 "unknown array reference type.\n";
1556 const char rankoutofrange
[] = "libcaf_single::caf_get_by_ref(): "
1557 "rank out of range.\n";
1558 const char extentoutofrange
[] = "libcaf_single::caf_get_by_ref(): "
1559 "extent out of range.\n";
1560 const char cannotallocdst
[] = "libcaf_single::caf_get_by_ref(): "
1561 "cannot allocate memory.\n";
1562 const char nonallocextentmismatch
[] = "libcaf_single::caf_get_by_ref(): "
1563 "extent of non-allocatable arrays mismatch (%lu != %lu).\n";
1564 const char doublearrayref
[] = "libcaf_single::caf_get_by_ref(): "
1565 "two or more array part references are not supported.\n";
1567 size_t dst_index
[GFC_MAX_DIMENSIONS
];
1568 int dst_rank
= GFC_DESCRIPTOR_RANK (dst
);
1569 int dst_cur_dim
= 0;
1570 size_t src_size
= 0;
1571 caf_single_token_t single_token
= TOKEN (token
);
1572 void *memptr
= single_token
->memptr
;
1573 gfc_descriptor_t
*src
= single_token
->desc
;
1574 caf_reference_t
*riter
= refs
;
1576 /* Reallocation of dst.data is needed (e.g., array to small). */
1577 bool realloc_needed
;
1578 /* Reallocation of dst.data is required, because data is not alloced at
1580 bool realloc_required
;
1581 bool extent_mismatch
= false;
1582 /* Set when the first non-scalar array reference is encountered. */
1583 bool in_array_ref
= false;
1584 bool array_extent_fixed
= false;
1585 realloc_needed
= realloc_required
= GFC_DESCRIPTOR_DATA (dst
) == NULL
;
1587 assert (!realloc_needed
|| dst_reallocatable
);
1592 /* Compute the size of the result. In the beginning size just counts the
1593 number of elements. */
1597 switch (riter
->type
)
1599 case CAF_REF_COMPONENT
:
1600 if (riter
->u
.c
.caf_token_offset
)
1602 single_token
= *(caf_single_token_t
*)
1603 (memptr
+ riter
->u
.c
.caf_token_offset
);
1604 memptr
= single_token
->memptr
;
1605 src
= single_token
->desc
;
1609 memptr
+= riter
->u
.c
.offset
;
1610 /* When the next ref is an array ref, assume there is an
1611 array descriptor at memptr. Note, static arrays do not have
1613 if (riter
->next
&& riter
->next
->type
== CAF_REF_ARRAY
)
1614 src
= (gfc_descriptor_t
*)memptr
;
1620 for (i
= 0; riter
->u
.a
.mode
[i
] != CAF_ARR_REF_NONE
; ++i
)
1622 switch (riter
->u
.a
.mode
[i
])
1624 case CAF_ARR_REF_VECTOR
:
1625 delta
= riter
->u
.a
.dim
[i
].v
.nvec
;
1626 #define KINDCASE(kind, type) case kind: \
1627 memptr += (((index_type) \
1628 ((type *)riter->u.a.dim[i].v.vector)[0]) \
1629 - GFC_DIMENSION_LBOUND (src->dim[i])) \
1630 * GFC_DIMENSION_STRIDE (src->dim[i]) \
1631 * riter->item_size; \
1634 switch (riter
->u
.a
.dim
[i
].v
.kind
)
1636 KINDCASE (1, GFC_INTEGER_1
);
1637 KINDCASE (2, GFC_INTEGER_2
);
1638 KINDCASE (4, GFC_INTEGER_4
);
1639 #ifdef HAVE_GFC_INTEGER_8
1640 KINDCASE (8, GFC_INTEGER_8
);
1642 #ifdef HAVE_GFC_INTEGER_16
1643 KINDCASE (16, GFC_INTEGER_16
);
1646 caf_internal_error (vecrefunknownkind
, stat
, NULL
, 0);
1651 case CAF_ARR_REF_FULL
:
1652 COMPUTE_NUM_ITEMS (delta
,
1653 riter
->u
.a
.dim
[i
].s
.stride
,
1654 GFC_DIMENSION_LBOUND (src
->dim
[i
]),
1655 GFC_DIMENSION_UBOUND (src
->dim
[i
]));
1656 /* The memptr stays unchanged when ref'ing the first element
1659 case CAF_ARR_REF_RANGE
:
1660 COMPUTE_NUM_ITEMS (delta
,
1661 riter
->u
.a
.dim
[i
].s
.stride
,
1662 riter
->u
.a
.dim
[i
].s
.start
,
1663 riter
->u
.a
.dim
[i
].s
.end
);
1664 memptr
+= (riter
->u
.a
.dim
[i
].s
.start
1665 - GFC_DIMENSION_LBOUND (src
->dim
[i
]))
1666 * GFC_DIMENSION_STRIDE (src
->dim
[i
])
1669 case CAF_ARR_REF_SINGLE
:
1671 memptr
+= (riter
->u
.a
.dim
[i
].s
.start
1672 - GFC_DIMENSION_LBOUND (src
->dim
[i
]))
1673 * GFC_DIMENSION_STRIDE (src
->dim
[i
])
1676 case CAF_ARR_REF_OPEN_END
:
1677 COMPUTE_NUM_ITEMS (delta
,
1678 riter
->u
.a
.dim
[i
].s
.stride
,
1679 riter
->u
.a
.dim
[i
].s
.start
,
1680 GFC_DIMENSION_UBOUND (src
->dim
[i
]));
1681 memptr
+= (riter
->u
.a
.dim
[i
].s
.start
1682 - GFC_DIMENSION_LBOUND (src
->dim
[i
]))
1683 * GFC_DIMENSION_STRIDE (src
->dim
[i
])
1686 case CAF_ARR_REF_OPEN_START
:
1687 COMPUTE_NUM_ITEMS (delta
,
1688 riter
->u
.a
.dim
[i
].s
.stride
,
1689 GFC_DIMENSION_LBOUND (src
->dim
[i
]),
1690 riter
->u
.a
.dim
[i
].s
.end
);
1691 /* The memptr stays unchanged when ref'ing the first element
1695 caf_internal_error (unknownarrreftype
, stat
, NULL
, 0);
1700 /* Check the various properties of the destination array.
1701 Is an array expected and present? */
1702 if (delta
> 1 && dst_rank
== 0)
1704 /* No, an array is required, but not provided. */
1705 caf_internal_error (extentoutofrange
, stat
, NULL
, 0);
1708 /* Special mode when called by __caf_sendget_by_ref (). */
1709 if (dst_rank
== -1 && GFC_DESCRIPTOR_DATA (dst
) == NULL
)
1711 dst_rank
= dst_cur_dim
+ 1;
1712 GFC_DESCRIPTOR_RANK (dst
) = dst_rank
;
1713 GFC_DESCRIPTOR_SIZE (dst
) = dst_kind
;
1715 /* When dst is an array. */
1718 /* Check that dst_cur_dim is valid for dst. Can be
1719 superceeded only by scalar data. */
1720 if (dst_cur_dim
>= dst_rank
&& delta
!= 1)
1722 caf_internal_error (rankoutofrange
, stat
, NULL
, 0);
1725 /* Do further checks, when the source is not scalar. */
1726 else if (delta
!= 1)
1728 /* Check that the extent is not scalar and we are not in
1729 an array ref for the dst side. */
1732 /* Check that this is the non-scalar extent. */
1733 if (!array_extent_fixed
)
1735 /* In an array extent now. */
1736 in_array_ref
= true;
1737 /* Check that we haven't skipped any scalar
1738 dimensions yet and that the dst is
1741 && dst_rank
== GFC_DESCRIPTOR_RANK (src
))
1743 if (dst_reallocatable
)
1745 /* Dst is reallocatable, which means that
1746 the bounds are not set. Set them. */
1747 for (dst_cur_dim
= 0; dst_cur_dim
< (int)i
;
1749 GFC_DIMENSION_SET (dst
->dim
[dst_cur_dim
],
1755 /* Else press thumbs, that there are enough
1756 dimensional refs to come. Checked below. */
1760 caf_internal_error (doublearrayref
, stat
, NULL
,
1765 /* When the realloc is required, then no extent may have
1767 extent_mismatch
= realloc_required
1768 || GFC_DESCRIPTOR_EXTENT (dst
, dst_cur_dim
) != delta
;
1769 /* When it already known, that a realloc is needed or
1770 the extent does not match the needed one. */
1771 if (realloc_required
|| realloc_needed
1774 /* Check whether dst is reallocatable. */
1775 if (unlikely (!dst_reallocatable
))
1777 caf_internal_error (nonallocextentmismatch
, stat
,
1779 GFC_DESCRIPTOR_EXTENT (dst
,
1783 /* Only report an error, when the extent needs to be
1784 modified, which is not allowed. */
1785 else if (!dst_reallocatable
&& extent_mismatch
)
1787 caf_internal_error (extentoutofrange
, stat
, NULL
,
1791 realloc_needed
= true;
1793 /* Only change the extent when it does not match. This is
1794 to prevent resetting given array bounds. */
1795 if (extent_mismatch
)
1796 GFC_DIMENSION_SET (dst
->dim
[dst_cur_dim
], 1, delta
,
1800 /* Only increase the dim counter, when in an array ref. */
1801 if (in_array_ref
&& dst_cur_dim
< dst_rank
)
1804 size
*= (index_type
)delta
;
1808 array_extent_fixed
= true;
1809 in_array_ref
= false;
1810 /* Check, if we got less dimensional refs than the rank of dst
1812 assert (dst_cur_dim
== GFC_DESCRIPTOR_RANK (dst
));
1815 case CAF_REF_STATIC_ARRAY
:
1816 for (i
= 0; riter
->u
.a
.mode
[i
] != CAF_ARR_REF_NONE
; ++i
)
1818 switch (riter
->u
.a
.mode
[i
])
1820 case CAF_ARR_REF_VECTOR
:
1821 delta
= riter
->u
.a
.dim
[i
].v
.nvec
;
1822 #define KINDCASE(kind, type) case kind: \
1823 memptr += ((type *)riter->u.a.dim[i].v.vector)[0] \
1824 * riter->item_size; \
1827 switch (riter
->u
.a
.dim
[i
].v
.kind
)
1829 KINDCASE (1, GFC_INTEGER_1
);
1830 KINDCASE (2, GFC_INTEGER_2
);
1831 KINDCASE (4, GFC_INTEGER_4
);
1832 #ifdef HAVE_GFC_INTEGER_8
1833 KINDCASE (8, GFC_INTEGER_8
);
1835 #ifdef HAVE_GFC_INTEGER_16
1836 KINDCASE (16, GFC_INTEGER_16
);
1839 caf_internal_error (vecrefunknownkind
, stat
, NULL
, 0);
1844 case CAF_ARR_REF_FULL
:
1845 delta
= riter
->u
.a
.dim
[i
].s
.end
/ riter
->u
.a
.dim
[i
].s
.stride
1847 /* The memptr stays unchanged when ref'ing the first element
1850 case CAF_ARR_REF_RANGE
:
1851 COMPUTE_NUM_ITEMS (delta
,
1852 riter
->u
.a
.dim
[i
].s
.stride
,
1853 riter
->u
.a
.dim
[i
].s
.start
,
1854 riter
->u
.a
.dim
[i
].s
.end
);
1855 memptr
+= riter
->u
.a
.dim
[i
].s
.start
1856 * riter
->u
.a
.dim
[i
].s
.stride
1859 case CAF_ARR_REF_SINGLE
:
1861 memptr
+= riter
->u
.a
.dim
[i
].s
.start
1862 * riter
->u
.a
.dim
[i
].s
.stride
1865 case CAF_ARR_REF_OPEN_END
:
1866 /* This and OPEN_START are mapped to a RANGE and therefore
1867 cannot occur here. */
1868 case CAF_ARR_REF_OPEN_START
:
1870 caf_internal_error (unknownarrreftype
, stat
, NULL
, 0);
1875 /* Check the various properties of the destination array.
1876 Is an array expected and present? */
1877 if (delta
> 1 && dst_rank
== 0)
1879 /* No, an array is required, but not provided. */
1880 caf_internal_error (extentoutofrange
, stat
, NULL
, 0);
1883 /* Special mode when called by __caf_sendget_by_ref (). */
1884 if (dst_rank
== -1 && GFC_DESCRIPTOR_DATA (dst
) == NULL
)
1886 dst_rank
= dst_cur_dim
+ 1;
1887 GFC_DESCRIPTOR_RANK (dst
) = dst_rank
;
1888 GFC_DESCRIPTOR_SIZE (dst
) = dst_kind
;
1890 /* When dst is an array. */
1893 /* Check that dst_cur_dim is valid for dst. Can be
1894 superceeded only by scalar data. */
1895 if (dst_cur_dim
>= dst_rank
&& delta
!= 1)
1897 caf_internal_error (rankoutofrange
, stat
, NULL
, 0);
1900 /* Do further checks, when the source is not scalar. */
1901 else if (delta
!= 1)
1903 /* Check that the extent is not scalar and we are not in
1904 an array ref for the dst side. */
1907 /* Check that this is the non-scalar extent. */
1908 if (!array_extent_fixed
)
1910 /* In an array extent now. */
1911 in_array_ref
= true;
1912 /* The dst is not reallocatable, so nothing more
1913 to do, then correct the dim counter. */
1918 caf_internal_error (doublearrayref
, stat
, NULL
,
1923 /* When the realloc is required, then no extent may have
1925 extent_mismatch
= realloc_required
1926 || GFC_DESCRIPTOR_EXTENT (dst
, dst_cur_dim
) != delta
;
1927 /* When it is already known, that a realloc is needed or
1928 the extent does not match the needed one. */
1929 if (realloc_required
|| realloc_needed
1932 /* Check whether dst is reallocatable. */
1933 if (unlikely (!dst_reallocatable
))
1935 caf_internal_error (nonallocextentmismatch
, stat
,
1937 GFC_DESCRIPTOR_EXTENT (dst
,
1941 /* Only report an error, when the extent needs to be
1942 modified, which is not allowed. */
1943 else if (!dst_reallocatable
&& extent_mismatch
)
1945 caf_internal_error (extentoutofrange
, stat
, NULL
,
1949 realloc_needed
= true;
1951 /* Only change the extent when it does not match. This is
1952 to prevent resetting given array bounds. */
1953 if (extent_mismatch
)
1954 GFC_DIMENSION_SET (dst
->dim
[dst_cur_dim
], 1, delta
,
1957 /* Only increase the dim counter, when in an array ref. */
1958 if (in_array_ref
&& dst_cur_dim
< dst_rank
)
1961 size
*= (index_type
)delta
;
1965 array_extent_fixed
= true;
1966 in_array_ref
= false;
1967 /* Check, if we got less dimensional refs than the rank of dst
1969 assert (dst_cur_dim
== GFC_DESCRIPTOR_RANK (dst
));
1973 caf_internal_error (unknownreftype
, stat
, NULL
, 0);
1976 src_size
= riter
->item_size
;
1977 riter
= riter
->next
;
1979 if (size
== 0 || src_size
== 0)
1982 - size contains the number of elements to store in the destination array,
1983 - src_size gives the size in bytes of each item in the destination array.
1988 if (!array_extent_fixed
)
1991 /* Special mode when called by __caf_sendget_by_ref (). */
1992 if (dst_rank
== -1 && GFC_DESCRIPTOR_DATA (dst
) == NULL
)
1994 dst_rank
= dst_cur_dim
+ 1;
1995 GFC_DESCRIPTOR_RANK (dst
) = dst_rank
;
1996 GFC_DESCRIPTOR_SIZE (dst
) = dst_kind
;
1998 /* This can happen only, when the result is scalar. */
1999 for (dst_cur_dim
= 0; dst_cur_dim
< dst_rank
; ++dst_cur_dim
)
2000 GFC_DIMENSION_SET (dst
->dim
[dst_cur_dim
], 1, 1, 1);
2003 GFC_DESCRIPTOR_DATA (dst
) = malloc (size
* GFC_DESCRIPTOR_SIZE (dst
));
2004 if (unlikely (GFC_DESCRIPTOR_DATA (dst
) == NULL
))
2006 caf_internal_error (cannotallocdst
, stat
, NULL
, 0);
2011 /* Reset the token. */
2012 single_token
= TOKEN (token
);
2013 memptr
= single_token
->memptr
;
2014 src
= single_token
->desc
;
2015 memset(dst_index
, 0, sizeof (dst_index
));
2017 get_for_ref (refs
, &i
, dst_index
, single_token
, dst
, src
,
2018 GFC_DESCRIPTOR_DATA (dst
), memptr
, dst_kind
, src_kind
, 0, 0,
2024 send_by_ref (caf_reference_t
*ref
, size_t *i
, size_t *src_index
,
2025 caf_single_token_t single_token
, gfc_descriptor_t
*dst
,
2026 gfc_descriptor_t
*src
, void *ds
, void *sr
,
2027 int dst_kind
, int src_kind
, size_t dst_dim
, size_t src_dim
,
2028 size_t num
, size_t size
, int *stat
, int dst_type
)
2030 const char vecrefunknownkind
[] = "libcaf_single::caf_send_by_ref(): "
2031 "unknown kind in vector-ref.\n";
2032 ptrdiff_t extent_dst
= 1, array_offset_dst
= 0, stride_dst
;
2033 const size_t src_rank
= GFC_DESCRIPTOR_RANK (src
);
2035 if (unlikely (ref
== NULL
))
2036 /* May be we should issue an error here, because this case should not
2040 if (ref
->next
== NULL
)
2042 size_t src_size
= GFC_DESCRIPTOR_SIZE (src
);
2043 ptrdiff_t array_offset_src
= 0;;
2047 case CAF_REF_COMPONENT
:
2048 if (ref
->u
.c
.caf_token_offset
> 0)
2050 if (*(void**)(ds
+ ref
->u
.c
.offset
) == NULL
)
2052 /* Create a scalar temporary array descriptor. */
2053 gfc_descriptor_t static_dst
;
2054 GFC_DESCRIPTOR_DATA (&static_dst
) = NULL
;
2055 GFC_DESCRIPTOR_DTYPE (&static_dst
)
2056 = GFC_DESCRIPTOR_DTYPE (src
);
2057 /* The component can be allocated now, because it is a
2059 _gfortran_caf_register (ref
->item_size
,
2060 CAF_REGTYPE_COARRAY_ALLOC
,
2061 ds
+ ref
->u
.c
.caf_token_offset
,
2062 &static_dst
, stat
, NULL
, 0);
2063 single_token
= *(caf_single_token_t
*)
2064 (ds
+ ref
->u
.c
.caf_token_offset
);
2065 /* In case of an error in allocation return. When stat is
2066 NULL, then register_component() terminates on error. */
2067 if (stat
!= NULL
&& *stat
)
2069 /* Publish the allocated memory. */
2070 *((void **)(ds
+ ref
->u
.c
.offset
))
2071 = GFC_DESCRIPTOR_DATA (&static_dst
);
2072 ds
= GFC_DESCRIPTOR_DATA (&static_dst
);
2073 /* Set the type from the src. */
2074 dst_type
= GFC_DESCRIPTOR_TYPE (src
);
2078 single_token
= *(caf_single_token_t
*)
2079 (ds
+ ref
->u
.c
.caf_token_offset
);
2080 dst
= single_token
->desc
;
2083 ds
= GFC_DESCRIPTOR_DATA (dst
);
2084 dst_type
= GFC_DESCRIPTOR_TYPE (dst
);
2087 ds
= *(void **)(ds
+ ref
->u
.c
.offset
);
2089 copy_data (ds
, sr
, dst_type
, GFC_DESCRIPTOR_TYPE (src
),
2090 dst_kind
, src_kind
, ref
->item_size
, src_size
, 1, stat
);
2093 copy_data (ds
+ ref
->u
.c
.offset
, sr
, dst_type
,
2094 GFC_DESCRIPTOR_TYPE (src
),
2095 dst_kind
, src_kind
, ref
->item_size
, src_size
, 1, stat
);
2098 case CAF_REF_STATIC_ARRAY
:
2099 /* Intentionally fall through. */
2101 if (ref
->u
.a
.mode
[dst_dim
] == CAF_ARR_REF_NONE
)
2105 for (size_t d
= 0; d
< src_rank
; ++d
)
2106 array_offset_src
+= src_index
[d
];
2107 copy_data (ds
, sr
+ array_offset_src
* src_size
,
2108 dst_type
, GFC_DESCRIPTOR_TYPE (src
), dst_kind
,
2109 src_kind
, ref
->item_size
, src_size
, num
, stat
);
2112 copy_data (ds
, sr
, dst_type
, GFC_DESCRIPTOR_TYPE (src
),
2113 dst_kind
, src_kind
, ref
->item_size
, src_size
, num
,
2120 caf_runtime_error (unreachable
);
2126 case CAF_REF_COMPONENT
:
2127 if (ref
->u
.c
.caf_token_offset
> 0)
2129 if (*(void**)(ds
+ ref
->u
.c
.offset
) == NULL
)
2131 /* This component refs an unallocated array. Non-arrays are
2132 caught in the if (!ref->next) above. */
2133 dst
= (gfc_descriptor_t
*)(ds
+ ref
->u
.c
.offset
);
2134 /* Assume that the rank and the dimensions fit for copying src
2136 GFC_DESCRIPTOR_DTYPE (dst
) = GFC_DESCRIPTOR_DTYPE (src
);
2139 for (size_t d
= 0; d
< src_rank
; ++d
)
2141 extent_dst
= GFC_DIMENSION_EXTENT (src
->dim
[d
]);
2142 GFC_DIMENSION_LBOUND (dst
->dim
[d
]) = 0;
2143 GFC_DIMENSION_UBOUND (dst
->dim
[d
]) = extent_dst
- 1;
2144 GFC_DIMENSION_STRIDE (dst
->dim
[d
]) = stride_dst
;
2145 stride_dst
*= extent_dst
;
2147 /* Null the data-pointer to make register_component allocate
2149 GFC_DESCRIPTOR_DATA (dst
) = NULL
;
2151 /* The size of the array is given by size. */
2152 _gfortran_caf_register (size
* ref
->item_size
,
2153 CAF_REGTYPE_COARRAY_ALLOC
,
2154 ds
+ ref
->u
.c
.caf_token_offset
,
2155 dst
, stat
, NULL
, 0);
2156 /* In case of an error in allocation return. When stat is
2157 NULL, then register_component() terminates on error. */
2158 if (stat
!= NULL
&& *stat
)
2161 single_token
= *(caf_single_token_t
*)(ds
+ ref
->u
.c
.caf_token_offset
);
2162 /* When a component is allocatable (caf_token_offset != 0) and not an
2163 array (ref->next->type == CAF_REF_COMPONENT), then ds has to be
2165 if (ref
->next
&& ref
->next
->type
== CAF_REF_COMPONENT
)
2166 ds
= *(void **)(ds
+ ref
->u
.c
.offset
);
2168 ds
+= ref
->u
.c
.offset
;
2170 send_by_ref (ref
->next
, i
, src_index
, single_token
,
2171 single_token
->desc
, src
, ds
, sr
,
2172 dst_kind
, src_kind
, 0, src_dim
, 1, size
, stat
, dst_type
);
2175 send_by_ref (ref
->next
, i
, src_index
, single_token
,
2176 (gfc_descriptor_t
*)(ds
+ ref
->u
.c
.offset
), src
,
2177 ds
+ ref
->u
.c
.offset
, sr
, dst_kind
, src_kind
, 0, src_dim
,
2178 1, size
, stat
, dst_type
);
2181 if (ref
->u
.a
.mode
[dst_dim
] == CAF_ARR_REF_NONE
)
2183 send_by_ref (ref
->next
, i
, src_index
, single_token
,
2184 (gfc_descriptor_t
*)ds
, src
, ds
, sr
, dst_kind
, src_kind
,
2185 0, src_dim
, 1, size
, stat
, dst_type
);
2188 /* Only when on the left most index switch the data pointer to
2189 the array's data pointer. And only for non-static arrays. */
2190 if (dst_dim
== 0 && ref
->type
!= CAF_REF_STATIC_ARRAY
)
2191 ds
= GFC_DESCRIPTOR_DATA (dst
);
2192 switch (ref
->u
.a
.mode
[dst_dim
])
2194 case CAF_ARR_REF_VECTOR
:
2195 array_offset_dst
= 0;
2196 src_index
[src_dim
] = 0;
2197 for (size_t idx
= 0; idx
< ref
->u
.a
.dim
[dst_dim
].v
.nvec
;
2200 #define KINDCASE(kind, type) case kind: \
2201 array_offset_dst = (((index_type) \
2202 ((type *)ref->u.a.dim[dst_dim].v.vector)[idx]) \
2203 - GFC_DIMENSION_LBOUND (dst->dim[dst_dim])) \
2204 * GFC_DIMENSION_STRIDE (dst->dim[dst_dim]); \
2207 switch (ref
->u
.a
.dim
[dst_dim
].v
.kind
)
2209 KINDCASE (1, GFC_INTEGER_1
);
2210 KINDCASE (2, GFC_INTEGER_2
);
2211 KINDCASE (4, GFC_INTEGER_4
);
2212 #ifdef HAVE_GFC_INTEGER_8
2213 KINDCASE (8, GFC_INTEGER_8
);
2215 #ifdef HAVE_GFC_INTEGER_16
2216 KINDCASE (16, GFC_INTEGER_16
);
2219 caf_internal_error (vecrefunknownkind
, stat
, NULL
, 0);
2224 send_by_ref (ref
, i
, src_index
, single_token
, dst
, src
,
2225 ds
+ array_offset_dst
* ref
->item_size
, sr
,
2226 dst_kind
, src_kind
, dst_dim
+ 1, src_dim
+ 1,
2227 1, size
, stat
, dst_type
);
2230 += GFC_DIMENSION_STRIDE (src
->dim
[src_dim
]);
2233 case CAF_ARR_REF_FULL
:
2234 COMPUTE_NUM_ITEMS (extent_dst
,
2235 ref
->u
.a
.dim
[dst_dim
].s
.stride
,
2236 GFC_DIMENSION_LBOUND (dst
->dim
[dst_dim
]),
2237 GFC_DIMENSION_UBOUND (dst
->dim
[dst_dim
]));
2238 array_offset_dst
= 0;
2239 stride_dst
= GFC_DIMENSION_STRIDE (dst
->dim
[dst_dim
])
2240 * ref
->u
.a
.dim
[dst_dim
].s
.stride
;
2241 src_index
[src_dim
] = 0;
2242 for (index_type idx
= 0; idx
< extent_dst
;
2243 ++idx
, array_offset_dst
+= stride_dst
)
2245 send_by_ref (ref
, i
, src_index
, single_token
, dst
, src
,
2246 ds
+ array_offset_dst
* ref
->item_size
, sr
,
2247 dst_kind
, src_kind
, dst_dim
+ 1, src_dim
+ 1,
2248 1, size
, stat
, dst_type
);
2251 += GFC_DIMENSION_STRIDE (src
->dim
[src_dim
]);
2254 case CAF_ARR_REF_RANGE
:
2255 COMPUTE_NUM_ITEMS (extent_dst
,
2256 ref
->u
.a
.dim
[dst_dim
].s
.stride
,
2257 ref
->u
.a
.dim
[dst_dim
].s
.start
,
2258 ref
->u
.a
.dim
[dst_dim
].s
.end
);
2259 array_offset_dst
= ref
->u
.a
.dim
[dst_dim
].s
.start
2260 - GFC_DIMENSION_LBOUND (dst
->dim
[dst_dim
]);
2261 stride_dst
= GFC_DIMENSION_STRIDE (dst
->dim
[dst_dim
])
2262 * ref
->u
.a
.dim
[dst_dim
].s
.stride
;
2263 src_index
[src_dim
] = 0;
2264 for (index_type idx
= 0; idx
< extent_dst
; ++idx
)
2266 send_by_ref (ref
, i
, src_index
, single_token
, dst
, src
,
2267 ds
+ array_offset_dst
* ref
->item_size
, sr
,
2268 dst_kind
, src_kind
, dst_dim
+ 1, src_dim
+ 1,
2269 1, size
, stat
, dst_type
);
2272 += GFC_DIMENSION_STRIDE (src
->dim
[src_dim
]);
2273 array_offset_dst
+= stride_dst
;
2276 case CAF_ARR_REF_SINGLE
:
2277 array_offset_dst
= (ref
->u
.a
.dim
[dst_dim
].s
.start
2278 - GFC_DIMENSION_LBOUND (dst
->dim
[dst_dim
]))
2279 * GFC_DIMENSION_STRIDE (dst
->dim
[dst_dim
]);
2280 send_by_ref (ref
, i
, src_index
, single_token
, dst
, src
, ds
2281 + array_offset_dst
* ref
->item_size
, sr
,
2282 dst_kind
, src_kind
, dst_dim
+ 1, src_dim
, 1,
2283 size
, stat
, dst_type
);
2285 case CAF_ARR_REF_OPEN_END
:
2286 COMPUTE_NUM_ITEMS (extent_dst
,
2287 ref
->u
.a
.dim
[dst_dim
].s
.stride
,
2288 ref
->u
.a
.dim
[dst_dim
].s
.start
,
2289 GFC_DIMENSION_UBOUND (dst
->dim
[dst_dim
]));
2290 array_offset_dst
= ref
->u
.a
.dim
[dst_dim
].s
.start
2291 - GFC_DIMENSION_LBOUND (dst
->dim
[dst_dim
]);
2292 stride_dst
= GFC_DIMENSION_STRIDE (dst
->dim
[dst_dim
])
2293 * ref
->u
.a
.dim
[dst_dim
].s
.stride
;
2294 src_index
[src_dim
] = 0;
2295 for (index_type idx
= 0; idx
< extent_dst
; ++idx
)
2297 send_by_ref (ref
, i
, src_index
, single_token
, dst
, src
,
2298 ds
+ array_offset_dst
* ref
->item_size
, sr
,
2299 dst_kind
, src_kind
, dst_dim
+ 1, src_dim
+ 1,
2300 1, size
, stat
, dst_type
);
2303 += GFC_DIMENSION_STRIDE (src
->dim
[src_dim
]);
2304 array_offset_dst
+= stride_dst
;
2307 case CAF_ARR_REF_OPEN_START
:
2308 COMPUTE_NUM_ITEMS (extent_dst
,
2309 ref
->u
.a
.dim
[dst_dim
].s
.stride
,
2310 GFC_DIMENSION_LBOUND (dst
->dim
[dst_dim
]),
2311 ref
->u
.a
.dim
[dst_dim
].s
.end
);
2312 array_offset_dst
= 0;
2313 stride_dst
= GFC_DIMENSION_STRIDE (dst
->dim
[dst_dim
])
2314 * ref
->u
.a
.dim
[dst_dim
].s
.stride
;
2315 src_index
[src_dim
] = 0;
2316 for (index_type idx
= 0; idx
< extent_dst
; ++idx
)
2318 send_by_ref (ref
, i
, src_index
, single_token
, dst
, src
,
2319 ds
+ array_offset_dst
* ref
->item_size
, sr
,
2320 dst_kind
, src_kind
, dst_dim
+ 1, src_dim
+ 1,
2321 1, size
, stat
, dst_type
);
2324 += GFC_DIMENSION_STRIDE (src
->dim
[src_dim
]);
2325 array_offset_dst
+= stride_dst
;
2329 caf_runtime_error (unreachable
);
2332 case CAF_REF_STATIC_ARRAY
:
2333 if (ref
->u
.a
.mode
[dst_dim
] == CAF_ARR_REF_NONE
)
2335 send_by_ref (ref
->next
, i
, src_index
, single_token
, NULL
,
2336 src
, ds
, sr
, dst_kind
, src_kind
,
2337 0, src_dim
, 1, size
, stat
, dst_type
);
2340 switch (ref
->u
.a
.mode
[dst_dim
])
2342 case CAF_ARR_REF_VECTOR
:
2343 array_offset_dst
= 0;
2344 src_index
[src_dim
] = 0;
2345 for (size_t idx
= 0; idx
< ref
->u
.a
.dim
[dst_dim
].v
.nvec
;
2348 #define KINDCASE(kind, type) case kind: \
2349 array_offset_dst = ((type *)ref->u.a.dim[dst_dim].v.vector)[idx]; \
2352 switch (ref
->u
.a
.dim
[dst_dim
].v
.kind
)
2354 KINDCASE (1, GFC_INTEGER_1
);
2355 KINDCASE (2, GFC_INTEGER_2
);
2356 KINDCASE (4, GFC_INTEGER_4
);
2357 #ifdef HAVE_GFC_INTEGER_8
2358 KINDCASE (8, GFC_INTEGER_8
);
2360 #ifdef HAVE_GFC_INTEGER_16
2361 KINDCASE (16, GFC_INTEGER_16
);
2364 caf_runtime_error (unreachable
);
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,
2372 1, size
, stat
, dst_type
);
2374 += GFC_DIMENSION_STRIDE (src
->dim
[src_dim
]);
2377 case CAF_ARR_REF_FULL
:
2378 src_index
[src_dim
] = 0;
2379 for (array_offset_dst
= 0 ;
2380 array_offset_dst
<= ref
->u
.a
.dim
[dst_dim
].s
.end
;
2381 array_offset_dst
+= ref
->u
.a
.dim
[dst_dim
].s
.stride
)
2383 send_by_ref (ref
, i
, src_index
, single_token
, NULL
, src
,
2384 ds
+ array_offset_dst
* ref
->item_size
, sr
,
2385 dst_kind
, src_kind
, dst_dim
+ 1, src_dim
+ 1,
2386 1, size
, stat
, dst_type
);
2389 += GFC_DIMENSION_STRIDE (src
->dim
[src_dim
]);
2392 case CAF_ARR_REF_RANGE
:
2393 COMPUTE_NUM_ITEMS (extent_dst
,
2394 ref
->u
.a
.dim
[dst_dim
].s
.stride
,
2395 ref
->u
.a
.dim
[dst_dim
].s
.start
,
2396 ref
->u
.a
.dim
[dst_dim
].s
.end
);
2397 array_offset_dst
= ref
->u
.a
.dim
[dst_dim
].s
.start
;
2398 src_index
[src_dim
] = 0;
2399 for (index_type idx
= 0; idx
< extent_dst
; ++idx
)
2401 send_by_ref (ref
, i
, src_index
, single_token
, NULL
, src
,
2402 ds
+ array_offset_dst
* ref
->item_size
, sr
,
2403 dst_kind
, src_kind
, dst_dim
+ 1, src_dim
+ 1,
2404 1, size
, stat
, dst_type
);
2407 += GFC_DIMENSION_STRIDE (src
->dim
[src_dim
]);
2408 array_offset_dst
+= ref
->u
.a
.dim
[dst_dim
].s
.stride
;
2411 case CAF_ARR_REF_SINGLE
:
2412 array_offset_dst
= ref
->u
.a
.dim
[dst_dim
].s
.start
;
2413 send_by_ref (ref
, i
, src_index
, single_token
, NULL
, src
,
2414 ds
+ array_offset_dst
* ref
->item_size
, sr
,
2415 dst_kind
, src_kind
, dst_dim
+ 1, src_dim
, 1,
2416 size
, stat
, dst_type
);
2418 /* The OPEN_* are mapped to a RANGE and therefore cannot occur. */
2419 case CAF_ARR_REF_OPEN_END
:
2420 case CAF_ARR_REF_OPEN_START
:
2422 caf_runtime_error (unreachable
);
2426 caf_runtime_error (unreachable
);
2432 _gfortran_caf_send_by_ref (caf_token_t token
,
2433 int image_index
__attribute__ ((unused
)),
2434 gfc_descriptor_t
*src
, caf_reference_t
*refs
,
2435 int dst_kind
, int src_kind
,
2436 bool may_require_tmp
__attribute__ ((unused
)),
2437 bool dst_reallocatable
, int *stat
, int dst_type
)
2439 const char vecrefunknownkind
[] = "libcaf_single::caf_get_by_ref(): "
2440 "unknown kind in vector-ref.\n";
2441 const char unknownreftype
[] = "libcaf_single::caf_send_by_ref(): "
2442 "unknown reference type.\n";
2443 const char unknownarrreftype
[] = "libcaf_single::caf_send_by_ref(): "
2444 "unknown array reference type.\n";
2445 const char rankoutofrange
[] = "libcaf_single::caf_send_by_ref(): "
2446 "rank out of range.\n";
2447 const char realloconinnerref
[] = "libcaf_single::caf_send_by_ref(): "
2448 "reallocation of array followed by component ref not allowed.\n";
2449 const char cannotallocdst
[] = "libcaf_single::caf_send_by_ref(): "
2450 "cannot allocate memory.\n";
2451 const char nonallocextentmismatch
[] = "libcaf_single::caf_send_by_ref(): "
2452 "extent of non-allocatable array mismatch.\n";
2453 const char innercompref
[] = "libcaf_single::caf_send_by_ref(): "
2454 "inner unallocated component detected.\n";
2456 size_t dst_index
[GFC_MAX_DIMENSIONS
];
2457 int src_rank
= GFC_DESCRIPTOR_RANK (src
);
2458 int src_cur_dim
= 0;
2459 size_t src_size
= 0;
2460 caf_single_token_t single_token
= TOKEN (token
);
2461 void *memptr
= single_token
->memptr
;
2462 gfc_descriptor_t
*dst
= single_token
->desc
;
2463 caf_reference_t
*riter
= refs
;
2465 bool extent_mismatch
;
2466 /* Note that the component is not allocated yet. */
2467 index_type new_component_idx
= -1;
2472 /* Compute the size of the result. In the beginning size just counts the
2473 number of elements. */
2477 switch (riter
->type
)
2479 case CAF_REF_COMPONENT
:
2480 if (unlikely (new_component_idx
!= -1))
2482 /* Allocating a component in the middle of a component ref is not
2483 support. We don't know the type to allocate. */
2484 caf_internal_error (innercompref
, stat
, NULL
, 0);
2487 if (riter
->u
.c
.caf_token_offset
> 0)
2489 /* Check whether the allocatable component is zero, then no
2490 token is present, too. The token's pointer is not cleared
2491 when the structure is initialized. */
2492 if (*(void**)(memptr
+ riter
->u
.c
.offset
) == NULL
)
2494 /* This component is not yet allocated. Check that it is
2495 allocatable here. */
2496 if (!dst_reallocatable
)
2498 caf_internal_error (cannotallocdst
, stat
, NULL
, 0);
2501 single_token
= NULL
;
2506 single_token
= *(caf_single_token_t
*)
2507 (memptr
+ riter
->u
.c
.caf_token_offset
);
2508 memptr
+= riter
->u
.c
.offset
;
2509 dst
= single_token
->desc
;
2513 /* Regular component. */
2514 memptr
+= riter
->u
.c
.offset
;
2515 dst
= (gfc_descriptor_t
*)memptr
;
2520 memptr
= GFC_DESCRIPTOR_DATA (dst
);
2523 /* When the dst array needs to be allocated, then look at the
2524 extent of the source array in the dimension dst_cur_dim. */
2525 for (i
= 0; riter
->u
.a
.mode
[i
] != CAF_ARR_REF_NONE
; ++i
)
2527 switch (riter
->u
.a
.mode
[i
])
2529 case CAF_ARR_REF_VECTOR
:
2530 delta
= riter
->u
.a
.dim
[i
].v
.nvec
;
2531 #define KINDCASE(kind, type) case kind: \
2532 memptr += (((index_type) \
2533 ((type *)riter->u.a.dim[i].v.vector)[0]) \
2534 - GFC_DIMENSION_LBOUND (dst->dim[i])) \
2535 * GFC_DIMENSION_STRIDE (dst->dim[i]) \
2536 * riter->item_size; \
2539 switch (riter
->u
.a
.dim
[i
].v
.kind
)
2541 KINDCASE (1, GFC_INTEGER_1
);
2542 KINDCASE (2, GFC_INTEGER_2
);
2543 KINDCASE (4, GFC_INTEGER_4
);
2544 #ifdef HAVE_GFC_INTEGER_8
2545 KINDCASE (8, GFC_INTEGER_8
);
2547 #ifdef HAVE_GFC_INTEGER_16
2548 KINDCASE (16, GFC_INTEGER_16
);
2551 caf_internal_error (vecrefunknownkind
, stat
, NULL
, 0);
2556 case CAF_ARR_REF_FULL
:
2558 COMPUTE_NUM_ITEMS (delta
,
2559 riter
->u
.a
.dim
[i
].s
.stride
,
2560 GFC_DIMENSION_LBOUND (dst
->dim
[i
]),
2561 GFC_DIMENSION_UBOUND (dst
->dim
[i
]));
2563 COMPUTE_NUM_ITEMS (delta
,
2564 riter
->u
.a
.dim
[i
].s
.stride
,
2565 GFC_DIMENSION_LBOUND (src
->dim
[src_cur_dim
]),
2566 GFC_DIMENSION_UBOUND (src
->dim
[src_cur_dim
]));
2568 case CAF_ARR_REF_RANGE
:
2569 COMPUTE_NUM_ITEMS (delta
,
2570 riter
->u
.a
.dim
[i
].s
.stride
,
2571 riter
->u
.a
.dim
[i
].s
.start
,
2572 riter
->u
.a
.dim
[i
].s
.end
);
2573 memptr
+= (riter
->u
.a
.dim
[i
].s
.start
2574 - dst
->dim
[i
].lower_bound
)
2575 * GFC_DIMENSION_STRIDE (dst
->dim
[i
])
2578 case CAF_ARR_REF_SINGLE
:
2580 memptr
+= (riter
->u
.a
.dim
[i
].s
.start
2581 - dst
->dim
[i
].lower_bound
)
2582 * GFC_DIMENSION_STRIDE (dst
->dim
[i
])
2585 case CAF_ARR_REF_OPEN_END
:
2587 COMPUTE_NUM_ITEMS (delta
,
2588 riter
->u
.a
.dim
[i
].s
.stride
,
2589 riter
->u
.a
.dim
[i
].s
.start
,
2590 GFC_DIMENSION_UBOUND (dst
->dim
[i
]));
2592 COMPUTE_NUM_ITEMS (delta
,
2593 riter
->u
.a
.dim
[i
].s
.stride
,
2594 riter
->u
.a
.dim
[i
].s
.start
,
2595 GFC_DIMENSION_UBOUND (src
->dim
[src_cur_dim
]));
2596 memptr
+= (riter
->u
.a
.dim
[i
].s
.start
2597 - dst
->dim
[i
].lower_bound
)
2598 * GFC_DIMENSION_STRIDE (dst
->dim
[i
])
2601 case CAF_ARR_REF_OPEN_START
:
2603 COMPUTE_NUM_ITEMS (delta
,
2604 riter
->u
.a
.dim
[i
].s
.stride
,
2605 GFC_DIMENSION_LBOUND (dst
->dim
[i
]),
2606 riter
->u
.a
.dim
[i
].s
.end
);
2608 COMPUTE_NUM_ITEMS (delta
,
2609 riter
->u
.a
.dim
[i
].s
.stride
,
2610 GFC_DIMENSION_LBOUND (src
->dim
[src_cur_dim
]),
2611 riter
->u
.a
.dim
[i
].s
.end
);
2612 /* The memptr stays unchanged when ref'ing the first element
2616 caf_internal_error (unknownarrreftype
, stat
, NULL
, 0);
2622 /* Check the various properties of the source array.
2623 When src is an array. */
2624 if (delta
> 1 && src_rank
> 0)
2626 /* Check that src_cur_dim is valid for src. Can be
2627 superceeded only by scalar data. */
2628 if (src_cur_dim
>= src_rank
)
2630 caf_internal_error (rankoutofrange
, stat
, NULL
, 0);
2633 /* Do further checks, when the source is not scalar. */
2636 /* When the realloc is required, then no extent may have
2638 extent_mismatch
= memptr
== NULL
2640 && GFC_DESCRIPTOR_EXTENT (dst
, src_cur_dim
)
2642 /* When it already known, that a realloc is needed or
2643 the extent does not match the needed one. */
2644 if (extent_mismatch
)
2646 /* Check whether dst is reallocatable. */
2647 if (unlikely (!dst_reallocatable
))
2649 caf_internal_error (nonallocextentmismatch
, stat
,
2651 GFC_DESCRIPTOR_EXTENT (dst
,
2655 /* Report error on allocatable but missing inner
2657 else if (riter
->next
!= NULL
)
2659 caf_internal_error (realloconinnerref
, stat
, NULL
,
2664 /* Only change the extent when it does not match. This is
2665 to prevent resetting given array bounds. */
2666 if (extent_mismatch
)
2667 GFC_DIMENSION_SET (dst
->dim
[src_cur_dim
], 1, delta
,
2670 /* Increase the dim-counter of the src only when the extent
2672 if (src_cur_dim
< src_rank
2673 && GFC_DESCRIPTOR_EXTENT (src
, src_cur_dim
) == delta
)
2676 size
*= (index_type
)delta
;
2679 case CAF_REF_STATIC_ARRAY
:
2680 for (i
= 0; riter
->u
.a
.mode
[i
] != CAF_ARR_REF_NONE
; ++i
)
2682 switch (riter
->u
.a
.mode
[i
])
2684 case CAF_ARR_REF_VECTOR
:
2685 delta
= riter
->u
.a
.dim
[i
].v
.nvec
;
2686 #define KINDCASE(kind, type) case kind: \
2687 memptr += ((type *)riter->u.a.dim[i].v.vector)[0] \
2688 * riter->item_size; \
2691 switch (riter
->u
.a
.dim
[i
].v
.kind
)
2693 KINDCASE (1, GFC_INTEGER_1
);
2694 KINDCASE (2, GFC_INTEGER_2
);
2695 KINDCASE (4, GFC_INTEGER_4
);
2696 #ifdef HAVE_GFC_INTEGER_8
2697 KINDCASE (8, GFC_INTEGER_8
);
2699 #ifdef HAVE_GFC_INTEGER_16
2700 KINDCASE (16, GFC_INTEGER_16
);
2703 caf_internal_error (vecrefunknownkind
, stat
, NULL
, 0);
2708 case CAF_ARR_REF_FULL
:
2709 delta
= riter
->u
.a
.dim
[i
].s
.end
/ riter
->u
.a
.dim
[i
].s
.stride
2711 /* The memptr stays unchanged when ref'ing the first element
2714 case CAF_ARR_REF_RANGE
:
2715 COMPUTE_NUM_ITEMS (delta
,
2716 riter
->u
.a
.dim
[i
].s
.stride
,
2717 riter
->u
.a
.dim
[i
].s
.start
,
2718 riter
->u
.a
.dim
[i
].s
.end
);
2719 memptr
+= riter
->u
.a
.dim
[i
].s
.start
2720 * riter
->u
.a
.dim
[i
].s
.stride
2723 case CAF_ARR_REF_SINGLE
:
2725 memptr
+= riter
->u
.a
.dim
[i
].s
.start
2726 * riter
->u
.a
.dim
[i
].s
.stride
2729 case CAF_ARR_REF_OPEN_END
:
2730 /* This and OPEN_START are mapped to a RANGE and therefore
2731 cannot occur here. */
2732 case CAF_ARR_REF_OPEN_START
:
2734 caf_internal_error (unknownarrreftype
, stat
, NULL
, 0);
2739 /* Check the various properties of the source array.
2740 Only when the source array is not scalar examine its
2742 if (delta
> 1 && src_rank
> 0)
2744 /* Check that src_cur_dim is valid for src. Can be
2745 superceeded only by scalar data. */
2746 if (src_cur_dim
>= src_rank
)
2748 caf_internal_error (rankoutofrange
, stat
, NULL
, 0);
2753 /* We will not be able to realloc the dst, because that's
2754 a fixed size array. */
2755 extent_mismatch
= GFC_DESCRIPTOR_EXTENT (src
, src_cur_dim
)
2757 /* When the extent does not match the needed one we can
2759 if (extent_mismatch
)
2761 caf_internal_error (nonallocextentmismatch
, stat
,
2763 GFC_DESCRIPTOR_EXTENT (src
,
2770 size
*= (index_type
)delta
;
2774 caf_internal_error (unknownreftype
, stat
, NULL
, 0);
2777 src_size
= riter
->item_size
;
2778 riter
= riter
->next
;
2780 if (size
== 0 || src_size
== 0)
2783 - size contains the number of elements to store in the destination array,
2784 - src_size gives the size in bytes of each item in the destination array.
2787 /* Reset the token. */
2788 single_token
= TOKEN (token
);
2789 memptr
= single_token
->memptr
;
2790 dst
= single_token
->desc
;
2791 memset (dst_index
, 0, sizeof (dst_index
));
2793 send_by_ref (refs
, &i
, dst_index
, single_token
, dst
, src
,
2794 memptr
, GFC_DESCRIPTOR_DATA (src
), dst_kind
, src_kind
, 0, 0,
2795 1, size
, stat
, dst_type
);
2801 _gfortran_caf_sendget_by_ref (caf_token_t dst_token
, int dst_image_index
,
2802 caf_reference_t
*dst_refs
, caf_token_t src_token
,
2803 int src_image_index
,
2804 caf_reference_t
*src_refs
, int dst_kind
,
2805 int src_kind
, bool may_require_tmp
, int *dst_stat
,
2806 int *src_stat
, int dst_type
, int src_type
)
2808 GFC_FULL_ARRAY_DESCRIPTOR (GFC_MAX_DIMENSIONS
, void) temp
;
2809 GFC_DESCRIPTOR_DATA (&temp
) = NULL
;
2810 GFC_DESCRIPTOR_RANK (&temp
) = -1;
2811 GFC_DESCRIPTOR_TYPE (&temp
) = dst_type
;
2813 _gfortran_caf_get_by_ref (src_token
, src_image_index
,
2814 (gfc_descriptor_t
*) &temp
, src_refs
,
2815 dst_kind
, src_kind
, may_require_tmp
, true,
2816 src_stat
, src_type
);
2818 if (src_stat
&& *src_stat
!= 0)
2821 _gfortran_caf_send_by_ref (dst_token
, dst_image_index
,
2822 (gfc_descriptor_t
*) &temp
, dst_refs
,
2823 dst_kind
, dst_kind
, may_require_tmp
, true,
2824 dst_stat
, dst_type
);
2825 if (GFC_DESCRIPTOR_DATA (&temp
))
2826 free (GFC_DESCRIPTOR_DATA (&temp
));
2831 _gfortran_caf_atomic_define (caf_token_t token
, size_t offset
,
2832 int image_index
__attribute__ ((unused
)),
2833 void *value
, int *stat
,
2834 int type
__attribute__ ((unused
)), int kind
)
2838 uint32_t *atom
= (uint32_t *) ((char *) MEMTOK (token
) + offset
);
2840 __atomic_store (atom
, (uint32_t *) value
, __ATOMIC_RELAXED
);
2847 _gfortran_caf_atomic_ref (caf_token_t token
, size_t offset
,
2848 int image_index
__attribute__ ((unused
)),
2849 void *value
, int *stat
,
2850 int type
__attribute__ ((unused
)), int kind
)
2854 uint32_t *atom
= (uint32_t *) ((char *) MEMTOK (token
) + offset
);
2856 __atomic_load (atom
, (uint32_t *) value
, __ATOMIC_RELAXED
);
2864 _gfortran_caf_atomic_cas (caf_token_t token
, size_t offset
,
2865 int image_index
__attribute__ ((unused
)),
2866 void *old
, void *compare
, void *new_val
, int *stat
,
2867 int type
__attribute__ ((unused
)), int kind
)
2871 uint32_t *atom
= (uint32_t *) ((char *) MEMTOK (token
) + offset
);
2873 *(uint32_t *) old
= *(uint32_t *) compare
;
2874 (void) __atomic_compare_exchange_n (atom
, (uint32_t *) old
,
2875 *(uint32_t *) new_val
, false,
2876 __ATOMIC_RELAXED
, __ATOMIC_RELAXED
);
2883 _gfortran_caf_atomic_op (int op
, caf_token_t token
, size_t offset
,
2884 int image_index
__attribute__ ((unused
)),
2885 void *value
, void *old
, int *stat
,
2886 int type
__attribute__ ((unused
)), int kind
)
2891 uint32_t *atom
= (uint32_t *) ((char *) MEMTOK (token
) + offset
);
2895 case GFC_CAF_ATOMIC_ADD
:
2896 res
= __atomic_fetch_add (atom
, *(uint32_t *) value
, __ATOMIC_RELAXED
);
2898 case GFC_CAF_ATOMIC_AND
:
2899 res
= __atomic_fetch_and (atom
, *(uint32_t *) value
, __ATOMIC_RELAXED
);
2901 case GFC_CAF_ATOMIC_OR
:
2902 res
= __atomic_fetch_or (atom
, *(uint32_t *) value
, __ATOMIC_RELAXED
);
2904 case GFC_CAF_ATOMIC_XOR
:
2905 res
= __atomic_fetch_xor (atom
, *(uint32_t *) value
, __ATOMIC_RELAXED
);
2908 __builtin_unreachable();
2912 *(uint32_t *) old
= res
;
2919 _gfortran_caf_event_post (caf_token_t token
, size_t index
,
2920 int image_index
__attribute__ ((unused
)),
2921 int *stat
, char *errmsg
__attribute__ ((unused
)),
2922 size_t errmsg_len
__attribute__ ((unused
)))
2925 uint32_t *event
= (uint32_t *) ((char *) MEMTOK (token
) + index
2926 * sizeof (uint32_t));
2927 __atomic_fetch_add (event
, (uint32_t) value
, __ATOMIC_RELAXED
);
2934 _gfortran_caf_event_wait (caf_token_t token
, size_t index
,
2935 int until_count
, int *stat
,
2936 char *errmsg
__attribute__ ((unused
)),
2937 size_t errmsg_len
__attribute__ ((unused
)))
2939 uint32_t *event
= (uint32_t *) ((char *) MEMTOK (token
) + index
2940 * sizeof (uint32_t));
2941 uint32_t value
= (uint32_t)-until_count
;
2942 __atomic_fetch_add (event
, (uint32_t) value
, __ATOMIC_RELAXED
);
2949 _gfortran_caf_event_query (caf_token_t token
, size_t index
,
2950 int image_index
__attribute__ ((unused
)),
2951 int *count
, int *stat
)
2953 uint32_t *event
= (uint32_t *) ((char *) MEMTOK (token
) + index
2954 * sizeof (uint32_t));
2955 __atomic_load (event
, (uint32_t *) count
, __ATOMIC_RELAXED
);
2962 _gfortran_caf_lock (caf_token_t token
, size_t index
,
2963 int image_index
__attribute__ ((unused
)),
2964 int *acquired_lock
, int *stat
, char *errmsg
,
2967 const char *msg
= "Already locked";
2968 bool *lock
= &((bool *) MEMTOK (token
))[index
];
2974 *acquired_lock
= (int) true;
2982 *acquired_lock
= (int) false;
2994 size_t len
= (sizeof (msg
) > errmsg_len
) ? errmsg_len
2996 memcpy (errmsg
, msg
, len
);
2997 if (errmsg_len
> len
)
2998 memset (&errmsg
[len
], ' ', errmsg_len
-len
);
3002 _gfortran_caf_error_stop_str (msg
, strlen (msg
), false);
3007 _gfortran_caf_unlock (caf_token_t token
, size_t index
,
3008 int image_index
__attribute__ ((unused
)),
3009 int *stat
, char *errmsg
, size_t errmsg_len
)
3011 const char *msg
= "Variable is not locked";
3012 bool *lock
= &((bool *) MEMTOK (token
))[index
];
3027 size_t len
= (sizeof (msg
) > errmsg_len
) ? errmsg_len
3029 memcpy (errmsg
, msg
, len
);
3030 if (errmsg_len
> len
)
3031 memset (&errmsg
[len
], ' ', errmsg_len
-len
);
3035 _gfortran_caf_error_stop_str (msg
, strlen (msg
), false);
3039 _gfortran_caf_is_present (caf_token_t token
,
3040 int image_index
__attribute__ ((unused
)),
3041 caf_reference_t
*refs
)
3043 const char arraddressingnotallowed
[] = "libcaf_single::caf_is_present(): "
3044 "only scalar indexes allowed.\n";
3045 const char unknownreftype
[] = "libcaf_single::caf_get_by_ref(): "
3046 "unknown reference type.\n";
3047 const char unknownarrreftype
[] = "libcaf_single::caf_get_by_ref(): "
3048 "unknown array reference type.\n";
3050 caf_single_token_t single_token
= TOKEN (token
);
3051 void *memptr
= single_token
->memptr
;
3052 gfc_descriptor_t
*src
= single_token
->desc
;
3053 caf_reference_t
*riter
= refs
;
3057 switch (riter
->type
)
3059 case CAF_REF_COMPONENT
:
3060 if (riter
->u
.c
.caf_token_offset
)
3062 single_token
= *(caf_single_token_t
*)
3063 (memptr
+ riter
->u
.c
.caf_token_offset
);
3064 memptr
= single_token
->memptr
;
3065 src
= single_token
->desc
;
3069 memptr
+= riter
->u
.c
.offset
;
3070 src
= (gfc_descriptor_t
*)memptr
;
3074 for (i
= 0; riter
->u
.a
.mode
[i
] != CAF_ARR_REF_NONE
; ++i
)
3076 switch (riter
->u
.a
.mode
[i
])
3078 case CAF_ARR_REF_SINGLE
:
3079 memptr
+= (riter
->u
.a
.dim
[i
].s
.start
3080 - GFC_DIMENSION_LBOUND (src
->dim
[i
]))
3081 * GFC_DIMENSION_STRIDE (src
->dim
[i
])
3084 case CAF_ARR_REF_FULL
:
3085 /* A full array ref is allowed on the last reference only. */
3086 if (riter
->next
== NULL
)
3088 /* else fall through reporting an error. */
3090 case CAF_ARR_REF_VECTOR
:
3091 case CAF_ARR_REF_RANGE
:
3092 case CAF_ARR_REF_OPEN_END
:
3093 case CAF_ARR_REF_OPEN_START
:
3094 caf_internal_error (arraddressingnotallowed
, 0, NULL
, 0);
3097 caf_internal_error (unknownarrreftype
, 0, NULL
, 0);
3102 case CAF_REF_STATIC_ARRAY
:
3103 for (i
= 0; riter
->u
.a
.mode
[i
] != CAF_ARR_REF_NONE
; ++i
)
3105 switch (riter
->u
.a
.mode
[i
])
3107 case CAF_ARR_REF_SINGLE
:
3108 memptr
+= riter
->u
.a
.dim
[i
].s
.start
3109 * riter
->u
.a
.dim
[i
].s
.stride
3112 case CAF_ARR_REF_FULL
:
3113 /* A full array ref is allowed on the last reference only. */
3114 if (riter
->next
== NULL
)
3116 /* else fall through reporting an error. */
3118 case CAF_ARR_REF_VECTOR
:
3119 case CAF_ARR_REF_RANGE
:
3120 case CAF_ARR_REF_OPEN_END
:
3121 case CAF_ARR_REF_OPEN_START
:
3122 caf_internal_error (arraddressingnotallowed
, 0, NULL
, 0);
3125 caf_internal_error (unknownarrreftype
, 0, NULL
, 0);
3131 caf_internal_error (unknownreftype
, 0, NULL
, 0);
3134 riter
= riter
->next
;
3136 return memptr
!= NULL
;
3139 /* Reference the libraries implementation. */
3140 extern void _gfortran_random_init (int32_t, int32_t, int32_t);
3142 void _gfortran_caf_random_init (bool repeatable
, bool image_distinct
)
3144 /* In a single image implementation always forward to the gfortran
3146 _gfortran_random_init (repeatable
, image_distinct
, 1);