1 /* Single-image implementation of GNU Fortran Coarray Library
2 Copyright (C) 2011-2018 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
)
272 fprintf (stderr
, "STOP %d\n", stop_code
);
278 _gfortran_caf_stop_str(const char *string
, size_t len
)
280 fputs ("STOP ", stderr
);
282 fputc (*(string
++), stderr
);
283 fputs ("\n", stderr
);
290 _gfortran_caf_error_stop_str (const char *string
, size_t len
)
292 fputs ("ERROR STOP ", stderr
);
294 fputc (*(string
++), stderr
);
295 fputs ("\n", stderr
);
301 /* Reported that the program terminated because of a fail image issued.
302 Because this is a single image library, nothing else than aborting the whole
303 program can be done. */
305 void _gfortran_caf_fail_image (void)
307 fputs ("IMAGE FAILED!\n", stderr
);
312 /* Get the status of image IMAGE. Because being the single image library all
313 other images are reported to be stopped. */
315 int _gfortran_caf_image_status (int image
,
316 caf_team_t
* team
__attribute__ ((unused
)))
321 return CAF_STAT_STOPPED_IMAGE
;
325 /* Single image library. There can not be any failed images with only one
329 _gfortran_caf_failed_images (gfc_descriptor_t
*array
,
330 caf_team_t
* team
__attribute__ ((unused
)),
333 int local_kind
= kind
!= NULL
? *kind
: 4;
335 array
->base_addr
= NULL
;
336 array
->dtype
.type
= BT_INTEGER
;
337 array
->dtype
.elem_len
= local_kind
;
338 /* Setting lower_bound higher then upper_bound is what the compiler does to
339 indicate an empty array. */
340 array
->dim
[0].lower_bound
= 0;
341 array
->dim
[0]._ubound
= -1;
342 array
->dim
[0]._stride
= 1;
347 /* With only one image available no other images can be stopped. Therefore
348 return an empty array. */
351 _gfortran_caf_stopped_images (gfc_descriptor_t
*array
,
352 caf_team_t
* team
__attribute__ ((unused
)),
355 int local_kind
= kind
!= NULL
? *kind
: 4;
357 array
->base_addr
= NULL
;
358 array
->dtype
.type
= BT_INTEGER
;
359 array
->dtype
.elem_len
= local_kind
;
360 /* Setting lower_bound higher then upper_bound is what the compiler does to
361 indicate an empty array. */
362 array
->dim
[0].lower_bound
= 0;
363 array
->dim
[0]._ubound
= -1;
364 array
->dim
[0]._stride
= 1;
370 _gfortran_caf_error_stop (int error
)
372 fprintf (stderr
, "ERROR STOP %d\n", error
);
378 _gfortran_caf_co_broadcast (gfc_descriptor_t
*a
__attribute__ ((unused
)),
379 int source_image
__attribute__ ((unused
)),
380 int *stat
, char *errmsg
__attribute__ ((unused
)),
381 size_t errmsg_len
__attribute__ ((unused
)))
388 _gfortran_caf_co_sum (gfc_descriptor_t
*a
__attribute__ ((unused
)),
389 int result_image
__attribute__ ((unused
)),
390 int *stat
, char *errmsg
__attribute__ ((unused
)),
391 size_t errmsg_len
__attribute__ ((unused
)))
398 _gfortran_caf_co_min (gfc_descriptor_t
*a
__attribute__ ((unused
)),
399 int result_image
__attribute__ ((unused
)),
400 int *stat
, char *errmsg
__attribute__ ((unused
)),
401 int a_len
__attribute__ ((unused
)),
402 size_t errmsg_len
__attribute__ ((unused
)))
409 _gfortran_caf_co_max (gfc_descriptor_t
*a
__attribute__ ((unused
)),
410 int result_image
__attribute__ ((unused
)),
411 int *stat
, char *errmsg
__attribute__ ((unused
)),
412 int a_len
__attribute__ ((unused
)),
413 size_t errmsg_len
__attribute__ ((unused
)))
421 _gfortran_caf_co_reduce (gfc_descriptor_t
*a
__attribute__ ((unused
)),
422 void * (*opr
) (void *, void *)
423 __attribute__ ((unused
)),
424 int opr_flags
__attribute__ ((unused
)),
425 int result_image
__attribute__ ((unused
)),
426 int *stat
, char *errmsg
__attribute__ ((unused
)),
427 int a_len
__attribute__ ((unused
)),
428 size_t errmsg_len
__attribute__ ((unused
)))
436 assign_char4_from_char1 (size_t dst_size
, size_t src_size
, uint32_t *dst
,
440 n
= dst_size
/4 > src_size
? src_size
: dst_size
/4;
441 for (i
= 0; i
< n
; ++i
)
442 dst
[i
] = (int32_t) src
[i
];
443 for (; i
< dst_size
/4; ++i
)
444 dst
[i
] = (int32_t) ' ';
449 assign_char1_from_char4 (size_t dst_size
, size_t src_size
, unsigned char *dst
,
453 n
= dst_size
> src_size
/4 ? src_size
/4 : dst_size
;
454 for (i
= 0; i
< n
; ++i
)
455 dst
[i
] = src
[i
] > UINT8_MAX
? (unsigned char) '?' : (unsigned char) src
[i
];
457 memset (&dst
[n
], ' ', dst_size
- n
);
462 convert_type (void *dst
, int dst_type
, int dst_kind
, void *src
, int src_type
,
463 int src_kind
, int *stat
)
465 #ifdef HAVE_GFC_INTEGER_16
466 typedef __int128 int128t
;
468 typedef int64_t int128t
;
471 #if defined(GFC_REAL_16_IS_LONG_DOUBLE)
472 typedef long double real128t
;
473 typedef _Complex
long double complex128t
;
474 #elif defined(HAVE_GFC_REAL_16)
475 typedef _Complex
float __attribute__((mode(TC
))) __complex128
;
476 typedef __float128 real128t
;
477 typedef __complex128 complex128t
;
478 #elif defined(HAVE_GFC_REAL_10)
479 typedef long double real128t
;
480 typedef long double complex128t
;
482 typedef double real128t
;
483 typedef _Complex
double complex128t
;
487 real128t real_val
= 0;
488 complex128t cmpx_val
= 0;
494 int_val
= *(int8_t*) src
;
495 else if (src_kind
== 2)
496 int_val
= *(int16_t*) src
;
497 else if (src_kind
== 4)
498 int_val
= *(int32_t*) src
;
499 else if (src_kind
== 8)
500 int_val
= *(int64_t*) src
;
501 #ifdef HAVE_GFC_INTEGER_16
502 else if (src_kind
== 16)
503 int_val
= *(int128t
*) src
;
510 real_val
= *(float*) src
;
511 else if (src_kind
== 8)
512 real_val
= *(double*) src
;
513 #ifdef HAVE_GFC_REAL_10
514 else if (src_kind
== 10)
515 real_val
= *(long double*) src
;
517 #ifdef HAVE_GFC_REAL_16
518 else if (src_kind
== 16)
519 real_val
= *(real128t
*) src
;
526 cmpx_val
= *(_Complex
float*) src
;
527 else if (src_kind
== 8)
528 cmpx_val
= *(_Complex
double*) src
;
529 #ifdef HAVE_GFC_REAL_10
530 else if (src_kind
== 10)
531 cmpx_val
= *(_Complex
long double*) src
;
533 #ifdef HAVE_GFC_REAL_16
534 else if (src_kind
== 16)
535 cmpx_val
= *(complex128t
*) src
;
547 if (src_type
== BT_INTEGER
)
550 *(int8_t*) dst
= (int8_t) int_val
;
551 else if (dst_kind
== 2)
552 *(int16_t*) dst
= (int16_t) int_val
;
553 else if (dst_kind
== 4)
554 *(int32_t*) dst
= (int32_t) int_val
;
555 else if (dst_kind
== 8)
556 *(int64_t*) dst
= (int64_t) int_val
;
557 #ifdef HAVE_GFC_INTEGER_16
558 else if (dst_kind
== 16)
559 *(int128t
*) dst
= (int128t
) int_val
;
564 else if (src_type
== BT_REAL
)
567 *(int8_t*) dst
= (int8_t) real_val
;
568 else if (dst_kind
== 2)
569 *(int16_t*) dst
= (int16_t) real_val
;
570 else if (dst_kind
== 4)
571 *(int32_t*) dst
= (int32_t) real_val
;
572 else if (dst_kind
== 8)
573 *(int64_t*) dst
= (int64_t) real_val
;
574 #ifdef HAVE_GFC_INTEGER_16
575 else if (dst_kind
== 16)
576 *(int128t
*) dst
= (int128t
) real_val
;
581 else if (src_type
== BT_COMPLEX
)
584 *(int8_t*) dst
= (int8_t) cmpx_val
;
585 else if (dst_kind
== 2)
586 *(int16_t*) dst
= (int16_t) cmpx_val
;
587 else if (dst_kind
== 4)
588 *(int32_t*) dst
= (int32_t) cmpx_val
;
589 else if (dst_kind
== 8)
590 *(int64_t*) dst
= (int64_t) cmpx_val
;
591 #ifdef HAVE_GFC_INTEGER_16
592 else if (dst_kind
== 16)
593 *(int128t
*) dst
= (int128t
) cmpx_val
;
602 if (src_type
== BT_INTEGER
)
605 *(float*) dst
= (float) int_val
;
606 else if (dst_kind
== 8)
607 *(double*) dst
= (double) int_val
;
608 #ifdef HAVE_GFC_REAL_10
609 else if (dst_kind
== 10)
610 *(long double*) dst
= (long double) int_val
;
612 #ifdef HAVE_GFC_REAL_16
613 else if (dst_kind
== 16)
614 *(real128t
*) dst
= (real128t
) int_val
;
619 else if (src_type
== BT_REAL
)
622 *(float*) dst
= (float) real_val
;
623 else if (dst_kind
== 8)
624 *(double*) dst
= (double) real_val
;
625 #ifdef HAVE_GFC_REAL_10
626 else if (dst_kind
== 10)
627 *(long double*) dst
= (long double) real_val
;
629 #ifdef HAVE_GFC_REAL_16
630 else if (dst_kind
== 16)
631 *(real128t
*) dst
= (real128t
) real_val
;
636 else if (src_type
== BT_COMPLEX
)
639 *(float*) dst
= (float) cmpx_val
;
640 else if (dst_kind
== 8)
641 *(double*) dst
= (double) cmpx_val
;
642 #ifdef HAVE_GFC_REAL_10
643 else if (dst_kind
== 10)
644 *(long double*) dst
= (long double) cmpx_val
;
646 #ifdef HAVE_GFC_REAL_16
647 else if (dst_kind
== 16)
648 *(real128t
*) dst
= (real128t
) cmpx_val
;
655 if (src_type
== BT_INTEGER
)
658 *(_Complex
float*) dst
= (_Complex
float) int_val
;
659 else if (dst_kind
== 8)
660 *(_Complex
double*) dst
= (_Complex
double) int_val
;
661 #ifdef HAVE_GFC_REAL_10
662 else if (dst_kind
== 10)
663 *(_Complex
long double*) dst
= (_Complex
long double) int_val
;
665 #ifdef HAVE_GFC_REAL_16
666 else if (dst_kind
== 16)
667 *(complex128t
*) dst
= (complex128t
) int_val
;
672 else if (src_type
== BT_REAL
)
675 *(_Complex
float*) dst
= (_Complex
float) real_val
;
676 else if (dst_kind
== 8)
677 *(_Complex
double*) dst
= (_Complex
double) real_val
;
678 #ifdef HAVE_GFC_REAL_10
679 else if (dst_kind
== 10)
680 *(_Complex
long double*) dst
= (_Complex
long double) real_val
;
682 #ifdef HAVE_GFC_REAL_16
683 else if (dst_kind
== 16)
684 *(complex128t
*) dst
= (complex128t
) real_val
;
689 else if (src_type
== BT_COMPLEX
)
692 *(_Complex
float*) dst
= (_Complex
float) cmpx_val
;
693 else if (dst_kind
== 8)
694 *(_Complex
double*) dst
= (_Complex
double) cmpx_val
;
695 #ifdef HAVE_GFC_REAL_10
696 else if (dst_kind
== 10)
697 *(_Complex
long double*) dst
= (_Complex
long double) cmpx_val
;
699 #ifdef HAVE_GFC_REAL_16
700 else if (dst_kind
== 16)
701 *(complex128t
*) dst
= (complex128t
) cmpx_val
;
714 fprintf (stderr
, "libcaf_single RUNTIME ERROR: Cannot convert type %d kind "
715 "%d to type %d kind %d\n", src_type
, src_kind
, dst_type
, dst_kind
);
724 _gfortran_caf_get (caf_token_t token
, size_t offset
,
725 int image_index
__attribute__ ((unused
)),
726 gfc_descriptor_t
*src
,
727 caf_vector_t
*src_vector
__attribute__ ((unused
)),
728 gfc_descriptor_t
*dest
, int src_kind
, int dst_kind
,
729 bool may_require_tmp
, int *stat
)
731 /* FIXME: Handle vector subscripts. */
734 int rank
= GFC_DESCRIPTOR_RANK (dest
);
735 size_t src_size
= GFC_DESCRIPTOR_SIZE (src
);
736 size_t dst_size
= GFC_DESCRIPTOR_SIZE (dest
);
743 void *sr
= (void *) ((char *) MEMTOK (token
) + offset
);
744 if (GFC_DESCRIPTOR_TYPE (dest
) == GFC_DESCRIPTOR_TYPE (src
)
745 && dst_kind
== src_kind
)
747 memmove (GFC_DESCRIPTOR_DATA (dest
), sr
,
748 dst_size
> src_size
? src_size
: dst_size
);
749 if (GFC_DESCRIPTOR_TYPE (dest
) == BT_CHARACTER
&& dst_size
> src_size
)
752 memset ((void*)(char*) GFC_DESCRIPTOR_DATA (dest
) + src_size
,
753 ' ', dst_size
- src_size
);
754 else /* dst_kind == 4. */
755 for (i
= src_size
/4; i
< dst_size
/4; i
++)
756 ((int32_t*) GFC_DESCRIPTOR_DATA (dest
))[i
] = (int32_t) ' ';
759 else if (GFC_DESCRIPTOR_TYPE (dest
) == BT_CHARACTER
&& dst_kind
== 1)
760 assign_char1_from_char4 (dst_size
, src_size
, GFC_DESCRIPTOR_DATA (dest
),
762 else if (GFC_DESCRIPTOR_TYPE (dest
) == BT_CHARACTER
)
763 assign_char4_from_char1 (dst_size
, src_size
, GFC_DESCRIPTOR_DATA (dest
),
766 convert_type (GFC_DESCRIPTOR_DATA (dest
), GFC_DESCRIPTOR_TYPE (dest
),
767 dst_kind
, sr
, GFC_DESCRIPTOR_TYPE (src
), src_kind
, stat
);
772 for (j
= 0; j
< rank
; j
++)
774 ptrdiff_t dimextent
= dest
->dim
[j
]._ubound
- dest
->dim
[j
].lower_bound
+ 1;
785 ptrdiff_t array_offset_sr
, array_offset_dst
;
786 void *tmp
= malloc (size
*src_size
);
788 array_offset_dst
= 0;
789 for (i
= 0; i
< size
; i
++)
791 ptrdiff_t array_offset_sr
= 0;
792 ptrdiff_t stride
= 1;
793 ptrdiff_t extent
= 1;
794 for (j
= 0; j
< GFC_DESCRIPTOR_RANK (src
)-1; j
++)
796 array_offset_sr
+= ((i
/ (extent
*stride
))
797 % (src
->dim
[j
]._ubound
798 - src
->dim
[j
].lower_bound
+ 1))
799 * src
->dim
[j
]._stride
;
800 extent
= (src
->dim
[j
]._ubound
- src
->dim
[j
].lower_bound
+ 1);
801 stride
= src
->dim
[j
]._stride
;
803 array_offset_sr
+= (i
/ extent
) * src
->dim
[rank
-1]._stride
;
804 void *sr
= (void *)((char *) MEMTOK (token
) + offset
805 + array_offset_sr
*GFC_DESCRIPTOR_SIZE (src
));
806 memcpy ((void *) ((char *) tmp
+ array_offset_dst
), sr
, src_size
);
807 array_offset_dst
+= src_size
;
811 for (i
= 0; i
< size
; i
++)
813 ptrdiff_t array_offset_dst
= 0;
814 ptrdiff_t stride
= 1;
815 ptrdiff_t extent
= 1;
816 for (j
= 0; j
< rank
-1; j
++)
818 array_offset_dst
+= ((i
/ (extent
*stride
))
819 % (dest
->dim
[j
]._ubound
820 - dest
->dim
[j
].lower_bound
+ 1))
821 * dest
->dim
[j
]._stride
;
822 extent
= (dest
->dim
[j
]._ubound
- dest
->dim
[j
].lower_bound
+ 1);
823 stride
= dest
->dim
[j
]._stride
;
825 array_offset_dst
+= (i
/ extent
) * dest
->dim
[rank
-1]._stride
;
826 void *dst
= dest
->base_addr
827 + array_offset_dst
*GFC_DESCRIPTOR_SIZE (dest
);
828 void *sr
= tmp
+ array_offset_sr
;
830 if (GFC_DESCRIPTOR_TYPE (dest
) == GFC_DESCRIPTOR_TYPE (src
)
831 && dst_kind
== src_kind
)
833 memmove (dst
, sr
, dst_size
> src_size
? src_size
: dst_size
);
834 if (GFC_DESCRIPTOR_TYPE (dest
) == BT_CHARACTER
835 && dst_size
> src_size
)
838 memset ((void*)(char*) dst
+ src_size
, ' ',
840 else /* dst_kind == 4. */
841 for (k
= src_size
/4; k
< dst_size
/4; k
++)
842 ((int32_t*) dst
)[k
] = (int32_t) ' ';
845 else if (GFC_DESCRIPTOR_TYPE (dest
) == BT_CHARACTER
&& dst_kind
== 1)
846 assign_char1_from_char4 (dst_size
, src_size
, dst
, sr
);
847 else if (GFC_DESCRIPTOR_TYPE (dest
) == BT_CHARACTER
)
848 assign_char4_from_char1 (dst_size
, src_size
, dst
, sr
);
850 convert_type (dst
, GFC_DESCRIPTOR_TYPE (dest
), dst_kind
,
851 sr
, GFC_DESCRIPTOR_TYPE (src
), src_kind
, stat
);
852 array_offset_sr
+= src_size
;
859 for (i
= 0; i
< size
; i
++)
861 ptrdiff_t array_offset_dst
= 0;
862 ptrdiff_t stride
= 1;
863 ptrdiff_t extent
= 1;
864 for (j
= 0; j
< rank
-1; j
++)
866 array_offset_dst
+= ((i
/ (extent
*stride
))
867 % (dest
->dim
[j
]._ubound
868 - dest
->dim
[j
].lower_bound
+ 1))
869 * dest
->dim
[j
]._stride
;
870 extent
= (dest
->dim
[j
]._ubound
- dest
->dim
[j
].lower_bound
+ 1);
871 stride
= dest
->dim
[j
]._stride
;
873 array_offset_dst
+= (i
/ extent
) * dest
->dim
[rank
-1]._stride
;
874 void *dst
= dest
->base_addr
+ array_offset_dst
*GFC_DESCRIPTOR_SIZE (dest
);
876 ptrdiff_t array_offset_sr
= 0;
879 for (j
= 0; j
< GFC_DESCRIPTOR_RANK (src
)-1; j
++)
881 array_offset_sr
+= ((i
/ (extent
*stride
))
882 % (src
->dim
[j
]._ubound
883 - src
->dim
[j
].lower_bound
+ 1))
884 * src
->dim
[j
]._stride
;
885 extent
= (src
->dim
[j
]._ubound
- src
->dim
[j
].lower_bound
+ 1);
886 stride
= src
->dim
[j
]._stride
;
888 array_offset_sr
+= (i
/ extent
) * src
->dim
[rank
-1]._stride
;
889 void *sr
= (void *)((char *) MEMTOK (token
) + offset
890 + array_offset_sr
*GFC_DESCRIPTOR_SIZE (src
));
892 if (GFC_DESCRIPTOR_TYPE (dest
) == GFC_DESCRIPTOR_TYPE (src
)
893 && dst_kind
== src_kind
)
895 memmove (dst
, sr
, dst_size
> src_size
? src_size
: dst_size
);
896 if (GFC_DESCRIPTOR_TYPE (dest
) == BT_CHARACTER
&& dst_size
> src_size
)
899 memset ((void*)(char*) dst
+ src_size
, ' ', dst_size
-src_size
);
900 else /* dst_kind == 4. */
901 for (k
= src_size
/4; k
< dst_size
/4; k
++)
902 ((int32_t*) dst
)[k
] = (int32_t) ' ';
905 else if (GFC_DESCRIPTOR_TYPE (dest
) == BT_CHARACTER
&& dst_kind
== 1)
906 assign_char1_from_char4 (dst_size
, src_size
, dst
, sr
);
907 else if (GFC_DESCRIPTOR_TYPE (dest
) == BT_CHARACTER
)
908 assign_char4_from_char1 (dst_size
, src_size
, dst
, sr
);
910 convert_type (dst
, GFC_DESCRIPTOR_TYPE (dest
), dst_kind
,
911 sr
, GFC_DESCRIPTOR_TYPE (src
), src_kind
, stat
);
917 _gfortran_caf_send (caf_token_t token
, size_t offset
,
918 int image_index
__attribute__ ((unused
)),
919 gfc_descriptor_t
*dest
,
920 caf_vector_t
*dst_vector
__attribute__ ((unused
)),
921 gfc_descriptor_t
*src
, int dst_kind
, int src_kind
,
922 bool may_require_tmp
, int *stat
)
924 /* FIXME: Handle vector subscripts. */
927 int rank
= GFC_DESCRIPTOR_RANK (dest
);
928 size_t src_size
= GFC_DESCRIPTOR_SIZE (src
);
929 size_t dst_size
= GFC_DESCRIPTOR_SIZE (dest
);
936 void *dst
= (void *) ((char *) MEMTOK (token
) + offset
);
937 if (GFC_DESCRIPTOR_TYPE (dest
) == GFC_DESCRIPTOR_TYPE (src
)
938 && dst_kind
== src_kind
)
940 memmove (dst
, GFC_DESCRIPTOR_DATA (src
),
941 dst_size
> src_size
? src_size
: dst_size
);
942 if (GFC_DESCRIPTOR_TYPE (dest
) == BT_CHARACTER
&& dst_size
> src_size
)
945 memset ((void*)(char*) dst
+ src_size
, ' ', dst_size
-src_size
);
946 else /* dst_kind == 4. */
947 for (i
= src_size
/4; i
< dst_size
/4; i
++)
948 ((int32_t*) dst
)[i
] = (int32_t) ' ';
951 else if (GFC_DESCRIPTOR_TYPE (dest
) == BT_CHARACTER
&& dst_kind
== 1)
952 assign_char1_from_char4 (dst_size
, src_size
, dst
,
953 GFC_DESCRIPTOR_DATA (src
));
954 else if (GFC_DESCRIPTOR_TYPE (dest
) == BT_CHARACTER
)
955 assign_char4_from_char1 (dst_size
, src_size
, dst
,
956 GFC_DESCRIPTOR_DATA (src
));
958 convert_type (dst
, GFC_DESCRIPTOR_TYPE (dest
), dst_kind
,
959 GFC_DESCRIPTOR_DATA (src
), GFC_DESCRIPTOR_TYPE (src
),
965 for (j
= 0; j
< rank
; j
++)
967 ptrdiff_t dimextent
= dest
->dim
[j
]._ubound
- dest
->dim
[j
].lower_bound
+ 1;
978 ptrdiff_t array_offset_sr
, array_offset_dst
;
981 if (GFC_DESCRIPTOR_RANK (src
) == 0)
983 tmp
= malloc (src_size
);
984 memcpy (tmp
, GFC_DESCRIPTOR_DATA (src
), src_size
);
988 tmp
= malloc (size
*src_size
);
989 array_offset_dst
= 0;
990 for (i
= 0; i
< size
; i
++)
992 ptrdiff_t array_offset_sr
= 0;
993 ptrdiff_t stride
= 1;
994 ptrdiff_t extent
= 1;
995 for (j
= 0; j
< GFC_DESCRIPTOR_RANK (src
)-1; j
++)
997 array_offset_sr
+= ((i
/ (extent
*stride
))
998 % (src
->dim
[j
]._ubound
999 - src
->dim
[j
].lower_bound
+ 1))
1000 * src
->dim
[j
]._stride
;
1001 extent
= (src
->dim
[j
]._ubound
- src
->dim
[j
].lower_bound
+ 1);
1002 stride
= src
->dim
[j
]._stride
;
1004 array_offset_sr
+= (i
/ extent
) * src
->dim
[rank
-1]._stride
;
1005 void *sr
= (void *) ((char *) src
->base_addr
1006 + array_offset_sr
*GFC_DESCRIPTOR_SIZE (src
));
1007 memcpy ((void *) ((char *) tmp
+ array_offset_dst
), sr
, src_size
);
1008 array_offset_dst
+= src_size
;
1012 array_offset_sr
= 0;
1013 for (i
= 0; i
< size
; i
++)
1015 ptrdiff_t array_offset_dst
= 0;
1016 ptrdiff_t stride
= 1;
1017 ptrdiff_t extent
= 1;
1018 for (j
= 0; j
< rank
-1; j
++)
1020 array_offset_dst
+= ((i
/ (extent
*stride
))
1021 % (dest
->dim
[j
]._ubound
1022 - dest
->dim
[j
].lower_bound
+ 1))
1023 * dest
->dim
[j
]._stride
;
1024 extent
= (dest
->dim
[j
]._ubound
- dest
->dim
[j
].lower_bound
+ 1);
1025 stride
= dest
->dim
[j
]._stride
;
1027 array_offset_dst
+= (i
/ extent
) * dest
->dim
[rank
-1]._stride
;
1028 void *dst
= (void *)((char *) MEMTOK (token
) + offset
1029 + array_offset_dst
*GFC_DESCRIPTOR_SIZE (dest
));
1030 void *sr
= tmp
+ array_offset_sr
;
1031 if (GFC_DESCRIPTOR_TYPE (dest
) == GFC_DESCRIPTOR_TYPE (src
)
1032 && dst_kind
== src_kind
)
1035 dst_size
> src_size
? src_size
: dst_size
);
1036 if (GFC_DESCRIPTOR_TYPE (dest
) == BT_CHARACTER
1037 && dst_size
> src_size
)
1040 memset ((void*)(char*) dst
+ src_size
, ' ',
1042 else /* dst_kind == 4. */
1043 for (k
= src_size
/4; k
< dst_size
/4; k
++)
1044 ((int32_t*) dst
)[k
] = (int32_t) ' ';
1047 else if (GFC_DESCRIPTOR_TYPE (dest
) == BT_CHARACTER
&& dst_kind
== 1)
1048 assign_char1_from_char4 (dst_size
, src_size
, dst
, sr
);
1049 else if (GFC_DESCRIPTOR_TYPE (dest
) == BT_CHARACTER
)
1050 assign_char4_from_char1 (dst_size
, src_size
, dst
, sr
);
1052 convert_type (dst
, GFC_DESCRIPTOR_TYPE (dest
), dst_kind
,
1053 sr
, GFC_DESCRIPTOR_TYPE (src
), src_kind
, stat
);
1054 if (GFC_DESCRIPTOR_RANK (src
))
1055 array_offset_sr
+= src_size
;
1061 for (i
= 0; i
< size
; i
++)
1063 ptrdiff_t array_offset_dst
= 0;
1064 ptrdiff_t stride
= 1;
1065 ptrdiff_t extent
= 1;
1066 for (j
= 0; j
< rank
-1; j
++)
1068 array_offset_dst
+= ((i
/ (extent
*stride
))
1069 % (dest
->dim
[j
]._ubound
1070 - dest
->dim
[j
].lower_bound
+ 1))
1071 * dest
->dim
[j
]._stride
;
1072 extent
= (dest
->dim
[j
]._ubound
- dest
->dim
[j
].lower_bound
+ 1);
1073 stride
= dest
->dim
[j
]._stride
;
1075 array_offset_dst
+= (i
/ extent
) * dest
->dim
[rank
-1]._stride
;
1076 void *dst
= (void *)((char *) MEMTOK (token
) + offset
1077 + array_offset_dst
*GFC_DESCRIPTOR_SIZE (dest
));
1079 if (GFC_DESCRIPTOR_RANK (src
) != 0)
1081 ptrdiff_t array_offset_sr
= 0;
1084 for (j
= 0; j
< GFC_DESCRIPTOR_RANK (src
)-1; j
++)
1086 array_offset_sr
+= ((i
/ (extent
*stride
))
1087 % (src
->dim
[j
]._ubound
1088 - src
->dim
[j
].lower_bound
+ 1))
1089 * src
->dim
[j
]._stride
;
1090 extent
= (src
->dim
[j
]._ubound
- src
->dim
[j
].lower_bound
+ 1);
1091 stride
= src
->dim
[j
]._stride
;
1093 array_offset_sr
+= (i
/ extent
) * src
->dim
[rank
-1]._stride
;
1094 sr
= (void *)((char *) src
->base_addr
1095 + array_offset_sr
*GFC_DESCRIPTOR_SIZE (src
));
1098 sr
= src
->base_addr
;
1100 if (GFC_DESCRIPTOR_TYPE (dest
) == GFC_DESCRIPTOR_TYPE (src
)
1101 && dst_kind
== src_kind
)
1104 dst_size
> src_size
? src_size
: dst_size
);
1105 if (GFC_DESCRIPTOR_TYPE (dest
) == BT_CHARACTER
&& dst_size
> src_size
)
1108 memset ((void*)(char*) dst
+ src_size
, ' ', dst_size
-src_size
);
1109 else /* dst_kind == 4. */
1110 for (k
= src_size
/4; k
< dst_size
/4; k
++)
1111 ((int32_t*) dst
)[k
] = (int32_t) ' ';
1114 else if (GFC_DESCRIPTOR_TYPE (dest
) == BT_CHARACTER
&& dst_kind
== 1)
1115 assign_char1_from_char4 (dst_size
, src_size
, dst
, sr
);
1116 else if (GFC_DESCRIPTOR_TYPE (dest
) == BT_CHARACTER
)
1117 assign_char4_from_char1 (dst_size
, src_size
, dst
, sr
);
1119 convert_type (dst
, GFC_DESCRIPTOR_TYPE (dest
), dst_kind
,
1120 sr
, GFC_DESCRIPTOR_TYPE (src
), src_kind
, stat
);
1126 _gfortran_caf_sendget (caf_token_t dst_token
, size_t dst_offset
,
1127 int dst_image_index
, gfc_descriptor_t
*dest
,
1128 caf_vector_t
*dst_vector
, caf_token_t src_token
,
1130 int src_image_index
__attribute__ ((unused
)),
1131 gfc_descriptor_t
*src
,
1132 caf_vector_t
*src_vector
__attribute__ ((unused
)),
1133 int dst_kind
, int src_kind
, bool may_require_tmp
)
1135 /* FIXME: Handle vector subscript of 'src_vector'. */
1136 /* For a single image, src->base_addr should be the same as src_token + offset
1137 but to play save, we do it properly. */
1138 void *src_base
= GFC_DESCRIPTOR_DATA (src
);
1139 GFC_DESCRIPTOR_DATA (src
) = (void *) ((char *) MEMTOK (src_token
)
1141 _gfortran_caf_send (dst_token
, dst_offset
, dst_image_index
, dest
, dst_vector
,
1142 src
, dst_kind
, src_kind
, may_require_tmp
, NULL
);
1143 GFC_DESCRIPTOR_DATA (src
) = src_base
;
1147 /* Emitted when a theorectically unreachable part is reached. */
1148 const char unreachable
[] = "Fatal error: unreachable alternative found.\n";
1152 copy_data (void *ds
, void *sr
, int dst_type
, int src_type
,
1153 int dst_kind
, int src_kind
, size_t dst_size
, size_t src_size
,
1154 size_t num
, int *stat
)
1157 if (dst_type
== src_type
&& dst_kind
== src_kind
)
1159 memmove (ds
, sr
, (dst_size
> src_size
? src_size
: dst_size
) * num
);
1160 if ((dst_type
== BT_CHARACTER
|| src_type
== BT_CHARACTER
)
1161 && dst_size
> src_size
)
1164 memset ((void*)(char*) ds
+ src_size
, ' ', dst_size
-src_size
);
1165 else /* dst_kind == 4. */
1166 for (k
= src_size
/4; k
< dst_size
/4; k
++)
1167 ((int32_t*) ds
)[k
] = (int32_t) ' ';
1170 else if (dst_type
== BT_CHARACTER
&& dst_kind
== 1)
1171 assign_char1_from_char4 (dst_size
, src_size
, ds
, sr
);
1172 else if (dst_type
== BT_CHARACTER
)
1173 assign_char4_from_char1 (dst_size
, src_size
, ds
, sr
);
1175 for (k
= 0; k
< num
; ++k
)
1177 convert_type (ds
, dst_type
, dst_kind
, sr
, src_type
, src_kind
, stat
);
1184 #define COMPUTE_NUM_ITEMS(num, stride, lb, ub) \
1186 index_type abs_stride = (stride) > 0 ? (stride) : -(stride); \
1187 num = (stride) > 0 ? (ub) + 1 - (lb) : (lb) + 1 - (ub); \
1188 if (num <= 0 || abs_stride < 1) return; \
1189 num = (abs_stride > 1) ? (1 + (num - 1) / abs_stride) : num; \
1194 get_for_ref (caf_reference_t
*ref
, size_t *i
, size_t *dst_index
,
1195 caf_single_token_t single_token
, gfc_descriptor_t
*dst
,
1196 gfc_descriptor_t
*src
, void *ds
, void *sr
,
1197 int dst_kind
, int src_kind
, size_t dst_dim
, size_t src_dim
,
1198 size_t num
, int *stat
, int src_type
)
1200 ptrdiff_t extent_src
= 1, array_offset_src
= 0, stride_src
;
1201 size_t next_dst_dim
;
1203 if (unlikely (ref
== NULL
))
1204 /* May be we should issue an error here, because this case should not
1208 if (ref
->next
== NULL
)
1210 size_t dst_size
= GFC_DESCRIPTOR_SIZE (dst
);
1211 ptrdiff_t array_offset_dst
= 0;;
1212 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 zero. */
1219 if (ref
->u
.c
.caf_token_offset
> 0)
1220 /* Note, that sr is dereffed here. */
1221 copy_data (ds
, *(void **)(sr
+ ref
->u
.c
.offset
),
1222 GFC_DESCRIPTOR_TYPE (dst
), src_type
,
1223 dst_kind
, src_kind
, dst_size
, ref
->item_size
, 1, stat
);
1225 copy_data (ds
, sr
+ ref
->u
.c
.offset
,
1226 GFC_DESCRIPTOR_TYPE (dst
), src_type
,
1227 dst_kind
, src_kind
, dst_size
, ref
->item_size
, 1, stat
);
1230 case CAF_REF_STATIC_ARRAY
:
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
), src_type
,
1239 dst_kind
, src_kind
, dst_size
, ref
->item_size
, num
,
1246 caf_runtime_error (unreachable
);
1252 case CAF_REF_COMPONENT
:
1253 if (ref
->u
.c
.caf_token_offset
> 0)
1255 single_token
= *(caf_single_token_t
*)(sr
+ ref
->u
.c
.caf_token_offset
);
1257 if (ref
->next
&& ref
->next
->type
== CAF_REF_ARRAY
)
1258 src
= single_token
->desc
;
1262 if (ref
->next
&& ref
->next
->type
== CAF_REF_COMPONENT
)
1263 /* The currently ref'ed component was allocatabe (caf_token_offset
1264 > 0) and the next ref is a component, too, then the new sr has to
1265 be dereffed. (static arrays can not be allocatable or they
1266 become an array with descriptor. */
1267 sr
= *(void **)(sr
+ ref
->u
.c
.offset
);
1269 sr
+= ref
->u
.c
.offset
;
1271 get_for_ref (ref
->next
, i
, dst_index
, single_token
, dst
, src
,
1272 ds
, sr
, dst_kind
, src_kind
, dst_dim
, 0,
1276 get_for_ref (ref
->next
, i
, dst_index
, single_token
, dst
,
1277 (gfc_descriptor_t
*)(sr
+ ref
->u
.c
.offset
), ds
,
1278 sr
+ ref
->u
.c
.offset
, dst_kind
, src_kind
, dst_dim
, 0, 1,
1282 if (ref
->u
.a
.mode
[src_dim
] == CAF_ARR_REF_NONE
)
1284 get_for_ref (ref
->next
, i
, dst_index
, single_token
, dst
,
1285 src
, ds
, sr
, dst_kind
, src_kind
,
1286 dst_dim
, 0, 1, stat
, src_type
);
1289 /* Only when on the left most index switch the data pointer to
1290 the array's data pointer. */
1292 sr
= GFC_DESCRIPTOR_DATA (src
);
1293 switch (ref
->u
.a
.mode
[src_dim
])
1295 case CAF_ARR_REF_VECTOR
:
1296 extent_src
= GFC_DIMENSION_EXTENT (src
->dim
[src_dim
]);
1297 array_offset_src
= 0;
1298 dst_index
[dst_dim
] = 0;
1299 for (size_t idx
= 0; idx
< ref
->u
.a
.dim
[src_dim
].v
.nvec
;
1302 #define KINDCASE(kind, type) case kind: \
1303 array_offset_src = (((index_type) \
1304 ((type *)ref->u.a.dim[src_dim].v.vector)[idx]) \
1305 - GFC_DIMENSION_LBOUND (src->dim[src_dim])) \
1306 * GFC_DIMENSION_STRIDE (src->dim[src_dim]); \
1309 switch (ref
->u
.a
.dim
[src_dim
].v
.kind
)
1311 KINDCASE (1, GFC_INTEGER_1
);
1312 KINDCASE (2, GFC_INTEGER_2
);
1313 KINDCASE (4, GFC_INTEGER_4
);
1314 #ifdef HAVE_GFC_INTEGER_8
1315 KINDCASE (8, GFC_INTEGER_8
);
1317 #ifdef HAVE_GFC_INTEGER_16
1318 KINDCASE (16, GFC_INTEGER_16
);
1321 caf_runtime_error (unreachable
);
1326 get_for_ref (ref
, i
, dst_index
, single_token
, dst
, src
,
1327 ds
, sr
+ array_offset_src
* ref
->item_size
,
1328 dst_kind
, src_kind
, dst_dim
+ 1, src_dim
+ 1,
1331 += GFC_DIMENSION_STRIDE (dst
->dim
[dst_dim
]);
1334 case CAF_ARR_REF_FULL
:
1335 COMPUTE_NUM_ITEMS (extent_src
,
1336 ref
->u
.a
.dim
[src_dim
].s
.stride
,
1337 GFC_DIMENSION_LBOUND (src
->dim
[src_dim
]),
1338 GFC_DIMENSION_UBOUND (src
->dim
[src_dim
]));
1339 stride_src
= src
->dim
[src_dim
]._stride
1340 * ref
->u
.a
.dim
[src_dim
].s
.stride
;
1341 array_offset_src
= 0;
1342 dst_index
[dst_dim
] = 0;
1343 for (index_type idx
= 0; idx
< extent_src
;
1344 ++idx
, array_offset_src
+= stride_src
)
1346 get_for_ref (ref
, i
, dst_index
, single_token
, dst
, src
,
1347 ds
, sr
+ array_offset_src
* ref
->item_size
,
1348 dst_kind
, src_kind
, dst_dim
+ 1, src_dim
+ 1,
1351 += GFC_DIMENSION_STRIDE (dst
->dim
[dst_dim
]);
1354 case CAF_ARR_REF_RANGE
:
1355 COMPUTE_NUM_ITEMS (extent_src
,
1356 ref
->u
.a
.dim
[src_dim
].s
.stride
,
1357 ref
->u
.a
.dim
[src_dim
].s
.start
,
1358 ref
->u
.a
.dim
[src_dim
].s
.end
);
1359 array_offset_src
= (ref
->u
.a
.dim
[src_dim
].s
.start
1360 - GFC_DIMENSION_LBOUND (src
->dim
[src_dim
]))
1361 * GFC_DIMENSION_STRIDE (src
->dim
[src_dim
]);
1362 stride_src
= GFC_DIMENSION_STRIDE (src
->dim
[src_dim
])
1363 * ref
->u
.a
.dim
[src_dim
].s
.stride
;
1364 dst_index
[dst_dim
] = 0;
1365 /* Increase the dst_dim only, when the src_extent is greater one
1366 or src and dst extent are both one. Don't increase when the scalar
1367 source is not present in the dst. */
1368 next_dst_dim
= extent_src
> 1
1369 || (GFC_DIMENSION_EXTENT (dst
->dim
[dst_dim
]) == 1
1370 && extent_src
== 1) ? (dst_dim
+ 1) : dst_dim
;
1371 for (index_type idx
= 0; idx
< extent_src
; ++idx
)
1373 get_for_ref (ref
, i
, dst_index
, single_token
, dst
, src
,
1374 ds
, sr
+ array_offset_src
* ref
->item_size
,
1375 dst_kind
, src_kind
, next_dst_dim
, src_dim
+ 1,
1378 += GFC_DIMENSION_STRIDE (dst
->dim
[dst_dim
]);
1379 array_offset_src
+= stride_src
;
1382 case CAF_ARR_REF_SINGLE
:
1383 array_offset_src
= (ref
->u
.a
.dim
[src_dim
].s
.start
1384 - src
->dim
[src_dim
].lower_bound
)
1385 * GFC_DIMENSION_STRIDE (src
->dim
[src_dim
]);
1386 dst_index
[dst_dim
] = 0;
1387 get_for_ref (ref
, i
, dst_index
, single_token
, dst
, src
, ds
,
1388 sr
+ array_offset_src
* ref
->item_size
,
1389 dst_kind
, src_kind
, dst_dim
, src_dim
+ 1, 1,
1392 case CAF_ARR_REF_OPEN_END
:
1393 COMPUTE_NUM_ITEMS (extent_src
,
1394 ref
->u
.a
.dim
[src_dim
].s
.stride
,
1395 ref
->u
.a
.dim
[src_dim
].s
.start
,
1396 GFC_DIMENSION_UBOUND (src
->dim
[src_dim
]));
1397 stride_src
= GFC_DIMENSION_STRIDE (src
->dim
[src_dim
])
1398 * ref
->u
.a
.dim
[src_dim
].s
.stride
;
1399 array_offset_src
= (ref
->u
.a
.dim
[src_dim
].s
.start
1400 - GFC_DIMENSION_LBOUND (src
->dim
[src_dim
]))
1401 * GFC_DIMENSION_STRIDE (src
->dim
[src_dim
]);
1402 dst_index
[dst_dim
] = 0;
1403 for (index_type idx
= 0; idx
< extent_src
; ++idx
)
1405 get_for_ref (ref
, i
, dst_index
, single_token
, dst
, src
,
1406 ds
, sr
+ array_offset_src
* ref
->item_size
,
1407 dst_kind
, src_kind
, dst_dim
+ 1, src_dim
+ 1,
1410 += GFC_DIMENSION_STRIDE (dst
->dim
[dst_dim
]);
1411 array_offset_src
+= stride_src
;
1414 case CAF_ARR_REF_OPEN_START
:
1415 COMPUTE_NUM_ITEMS (extent_src
,
1416 ref
->u
.a
.dim
[src_dim
].s
.stride
,
1417 GFC_DIMENSION_LBOUND (src
->dim
[src_dim
]),
1418 ref
->u
.a
.dim
[src_dim
].s
.end
);
1419 stride_src
= GFC_DIMENSION_STRIDE (src
->dim
[src_dim
])
1420 * ref
->u
.a
.dim
[src_dim
].s
.stride
;
1421 array_offset_src
= 0;
1422 dst_index
[dst_dim
] = 0;
1423 for (index_type idx
= 0; idx
< extent_src
; ++idx
)
1425 get_for_ref (ref
, i
, dst_index
, single_token
, dst
, src
,
1426 ds
, sr
+ array_offset_src
* ref
->item_size
,
1427 dst_kind
, src_kind
, dst_dim
+ 1, src_dim
+ 1,
1430 += GFC_DIMENSION_STRIDE (dst
->dim
[dst_dim
]);
1431 array_offset_src
+= stride_src
;
1435 caf_runtime_error (unreachable
);
1438 case CAF_REF_STATIC_ARRAY
:
1439 if (ref
->u
.a
.mode
[src_dim
] == CAF_ARR_REF_NONE
)
1441 get_for_ref (ref
->next
, i
, dst_index
, single_token
, dst
,
1442 NULL
, ds
, sr
, dst_kind
, src_kind
,
1443 dst_dim
, 0, 1, stat
, src_type
);
1446 switch (ref
->u
.a
.mode
[src_dim
])
1448 case CAF_ARR_REF_VECTOR
:
1449 array_offset_src
= 0;
1450 dst_index
[dst_dim
] = 0;
1451 for (size_t idx
= 0; idx
< ref
->u
.a
.dim
[src_dim
].v
.nvec
;
1454 #define KINDCASE(kind, type) case kind: \
1455 array_offset_src = ((type *)ref->u.a.dim[src_dim].v.vector)[idx]; \
1458 switch (ref
->u
.a
.dim
[src_dim
].v
.kind
)
1460 KINDCASE (1, GFC_INTEGER_1
);
1461 KINDCASE (2, GFC_INTEGER_2
);
1462 KINDCASE (4, GFC_INTEGER_4
);
1463 #ifdef HAVE_GFC_INTEGER_8
1464 KINDCASE (8, GFC_INTEGER_8
);
1466 #ifdef HAVE_GFC_INTEGER_16
1467 KINDCASE (16, GFC_INTEGER_16
);
1470 caf_runtime_error (unreachable
);
1475 get_for_ref (ref
, i
, dst_index
, single_token
, dst
, NULL
,
1476 ds
, sr
+ array_offset_src
* ref
->item_size
,
1477 dst_kind
, src_kind
, dst_dim
+ 1, src_dim
+ 1,
1480 += GFC_DIMENSION_STRIDE (dst
->dim
[dst_dim
]);
1483 case CAF_ARR_REF_FULL
:
1484 dst_index
[dst_dim
] = 0;
1485 for (array_offset_src
= 0 ;
1486 array_offset_src
<= ref
->u
.a
.dim
[src_dim
].s
.end
;
1487 array_offset_src
+= ref
->u
.a
.dim
[src_dim
].s
.stride
)
1489 get_for_ref (ref
, i
, dst_index
, single_token
, dst
, NULL
,
1490 ds
, sr
+ array_offset_src
* ref
->item_size
,
1491 dst_kind
, src_kind
, dst_dim
+ 1, src_dim
+ 1,
1494 += GFC_DIMENSION_STRIDE (dst
->dim
[dst_dim
]);
1497 case CAF_ARR_REF_RANGE
:
1498 COMPUTE_NUM_ITEMS (extent_src
,
1499 ref
->u
.a
.dim
[src_dim
].s
.stride
,
1500 ref
->u
.a
.dim
[src_dim
].s
.start
,
1501 ref
->u
.a
.dim
[src_dim
].s
.end
);
1502 array_offset_src
= ref
->u
.a
.dim
[src_dim
].s
.start
;
1503 dst_index
[dst_dim
] = 0;
1504 for (index_type idx
= 0; idx
< extent_src
; ++idx
)
1506 get_for_ref (ref
, i
, dst_index
, single_token
, dst
, NULL
,
1507 ds
, sr
+ array_offset_src
* ref
->item_size
,
1508 dst_kind
, src_kind
, dst_dim
+ 1, src_dim
+ 1,
1511 += GFC_DIMENSION_STRIDE (dst
->dim
[dst_dim
]);
1512 array_offset_src
+= ref
->u
.a
.dim
[src_dim
].s
.stride
;
1515 case CAF_ARR_REF_SINGLE
:
1516 array_offset_src
= ref
->u
.a
.dim
[src_dim
].s
.start
;
1517 get_for_ref (ref
, i
, dst_index
, single_token
, dst
, NULL
, ds
,
1518 sr
+ array_offset_src
* ref
->item_size
,
1519 dst_kind
, src_kind
, dst_dim
, src_dim
+ 1, 1,
1522 /* The OPEN_* are mapped to a RANGE and therefore can not occur. */
1523 case CAF_ARR_REF_OPEN_END
:
1524 case CAF_ARR_REF_OPEN_START
:
1526 caf_runtime_error (unreachable
);
1530 caf_runtime_error (unreachable
);
1536 _gfortran_caf_get_by_ref (caf_token_t token
,
1537 int image_index
__attribute__ ((unused
)),
1538 gfc_descriptor_t
*dst
, caf_reference_t
*refs
,
1539 int dst_kind
, int src_kind
,
1540 bool may_require_tmp
__attribute__ ((unused
)),
1541 bool dst_reallocatable
, int *stat
,
1544 const char vecrefunknownkind
[] = "libcaf_single::caf_get_by_ref(): "
1545 "unknown kind in vector-ref.\n";
1546 const char unknownreftype
[] = "libcaf_single::caf_get_by_ref(): "
1547 "unknown reference type.\n";
1548 const char unknownarrreftype
[] = "libcaf_single::caf_get_by_ref(): "
1549 "unknown array reference type.\n";
1550 const char rankoutofrange
[] = "libcaf_single::caf_get_by_ref(): "
1551 "rank out of range.\n";
1552 const char extentoutofrange
[] = "libcaf_single::caf_get_by_ref(): "
1553 "extent out of range.\n";
1554 const char cannotallocdst
[] = "libcaf_single::caf_get_by_ref(): "
1555 "can not allocate memory.\n";
1556 const char nonallocextentmismatch
[] = "libcaf_single::caf_get_by_ref(): "
1557 "extent of non-allocatable arrays mismatch (%lu != %lu).\n";
1558 const char doublearrayref
[] = "libcaf_single::caf_get_by_ref(): "
1559 "two or more array part references are not supported.\n";
1561 size_t dst_index
[GFC_MAX_DIMENSIONS
];
1562 int dst_rank
= GFC_DESCRIPTOR_RANK (dst
);
1563 int dst_cur_dim
= 0;
1564 size_t src_size
= 0;
1565 caf_single_token_t single_token
= TOKEN (token
);
1566 void *memptr
= single_token
->memptr
;
1567 gfc_descriptor_t
*src
= single_token
->desc
;
1568 caf_reference_t
*riter
= refs
;
1570 /* Reallocation of dst.data is needed (e.g., array to small). */
1571 bool realloc_needed
;
1572 /* Reallocation of dst.data is required, because data is not alloced at
1574 bool realloc_required
;
1575 bool extent_mismatch
= false;
1576 /* Set when the first non-scalar array reference is encountered. */
1577 bool in_array_ref
= false;
1578 bool array_extent_fixed
= false;
1579 realloc_needed
= realloc_required
= GFC_DESCRIPTOR_DATA (dst
) == NULL
;
1581 assert (!realloc_needed
|| dst_reallocatable
);
1586 /* Compute the size of the result. In the beginning size just counts the
1587 number of elements. */
1591 switch (riter
->type
)
1593 case CAF_REF_COMPONENT
:
1594 if (riter
->u
.c
.caf_token_offset
)
1596 single_token
= *(caf_single_token_t
*)
1597 (memptr
+ riter
->u
.c
.caf_token_offset
);
1598 memptr
= single_token
->memptr
;
1599 src
= single_token
->desc
;
1603 memptr
+= riter
->u
.c
.offset
;
1604 /* When the next ref is an array ref, assume there is an
1605 array descriptor at memptr. Note, static arrays do not have
1607 if (riter
->next
&& riter
->next
->type
== CAF_REF_ARRAY
)
1608 src
= (gfc_descriptor_t
*)memptr
;
1614 for (i
= 0; riter
->u
.a
.mode
[i
] != CAF_ARR_REF_NONE
; ++i
)
1616 switch (riter
->u
.a
.mode
[i
])
1618 case CAF_ARR_REF_VECTOR
:
1619 delta
= riter
->u
.a
.dim
[i
].v
.nvec
;
1620 #define KINDCASE(kind, type) case kind: \
1621 memptr += (((index_type) \
1622 ((type *)riter->u.a.dim[i].v.vector)[0]) \
1623 - GFC_DIMENSION_LBOUND (src->dim[i])) \
1624 * GFC_DIMENSION_STRIDE (src->dim[i]) \
1625 * riter->item_size; \
1628 switch (riter
->u
.a
.dim
[i
].v
.kind
)
1630 KINDCASE (1, GFC_INTEGER_1
);
1631 KINDCASE (2, GFC_INTEGER_2
);
1632 KINDCASE (4, GFC_INTEGER_4
);
1633 #ifdef HAVE_GFC_INTEGER_8
1634 KINDCASE (8, GFC_INTEGER_8
);
1636 #ifdef HAVE_GFC_INTEGER_16
1637 KINDCASE (16, GFC_INTEGER_16
);
1640 caf_internal_error (vecrefunknownkind
, stat
, NULL
, 0);
1645 case CAF_ARR_REF_FULL
:
1646 COMPUTE_NUM_ITEMS (delta
,
1647 riter
->u
.a
.dim
[i
].s
.stride
,
1648 GFC_DIMENSION_LBOUND (src
->dim
[i
]),
1649 GFC_DIMENSION_UBOUND (src
->dim
[i
]));
1650 /* The memptr stays unchanged when ref'ing the first element
1653 case CAF_ARR_REF_RANGE
:
1654 COMPUTE_NUM_ITEMS (delta
,
1655 riter
->u
.a
.dim
[i
].s
.stride
,
1656 riter
->u
.a
.dim
[i
].s
.start
,
1657 riter
->u
.a
.dim
[i
].s
.end
);
1658 memptr
+= (riter
->u
.a
.dim
[i
].s
.start
1659 - GFC_DIMENSION_LBOUND (src
->dim
[i
]))
1660 * GFC_DIMENSION_STRIDE (src
->dim
[i
])
1663 case CAF_ARR_REF_SINGLE
:
1665 memptr
+= (riter
->u
.a
.dim
[i
].s
.start
1666 - GFC_DIMENSION_LBOUND (src
->dim
[i
]))
1667 * GFC_DIMENSION_STRIDE (src
->dim
[i
])
1670 case CAF_ARR_REF_OPEN_END
:
1671 COMPUTE_NUM_ITEMS (delta
,
1672 riter
->u
.a
.dim
[i
].s
.stride
,
1673 riter
->u
.a
.dim
[i
].s
.start
,
1674 GFC_DIMENSION_UBOUND (src
->dim
[i
]));
1675 memptr
+= (riter
->u
.a
.dim
[i
].s
.start
1676 - GFC_DIMENSION_LBOUND (src
->dim
[i
]))
1677 * GFC_DIMENSION_STRIDE (src
->dim
[i
])
1680 case CAF_ARR_REF_OPEN_START
:
1681 COMPUTE_NUM_ITEMS (delta
,
1682 riter
->u
.a
.dim
[i
].s
.stride
,
1683 GFC_DIMENSION_LBOUND (src
->dim
[i
]),
1684 riter
->u
.a
.dim
[i
].s
.end
);
1685 /* The memptr stays unchanged when ref'ing the first element
1689 caf_internal_error (unknownarrreftype
, stat
, NULL
, 0);
1694 /* Check the various properties of the destination array.
1695 Is an array expected and present? */
1696 if (delta
> 1 && dst_rank
== 0)
1698 /* No, an array is required, but not provided. */
1699 caf_internal_error (extentoutofrange
, stat
, NULL
, 0);
1702 /* Special mode when called by __caf_sendget_by_ref (). */
1703 if (dst_rank
== -1 && GFC_DESCRIPTOR_DATA (dst
) == NULL
)
1705 dst_rank
= dst_cur_dim
+ 1;
1706 GFC_DESCRIPTOR_RANK (dst
) = dst_rank
;
1707 GFC_DESCRIPTOR_SIZE (dst
) = dst_kind
;
1709 /* When dst is an array. */
1712 /* Check that dst_cur_dim is valid for dst. Can be
1713 superceeded only by scalar data. */
1714 if (dst_cur_dim
>= dst_rank
&& delta
!= 1)
1716 caf_internal_error (rankoutofrange
, stat
, NULL
, 0);
1719 /* Do further checks, when the source is not scalar. */
1720 else if (delta
!= 1)
1722 /* Check that the extent is not scalar and we are not in
1723 an array ref for the dst side. */
1726 /* Check that this is the non-scalar extent. */
1727 if (!array_extent_fixed
)
1729 /* In an array extent now. */
1730 in_array_ref
= true;
1731 /* Check that we haven't skipped any scalar
1732 dimensions yet and that the dst is
1735 && dst_rank
== GFC_DESCRIPTOR_RANK (src
))
1737 if (dst_reallocatable
)
1739 /* Dst is reallocatable, which means that
1740 the bounds are not set. Set them. */
1741 for (dst_cur_dim
= 0; dst_cur_dim
< (int)i
;
1743 GFC_DIMENSION_SET (dst
->dim
[dst_cur_dim
],
1749 /* Else press thumbs, that there are enough
1750 dimensional refs to come. Checked below. */
1754 caf_internal_error (doublearrayref
, stat
, NULL
,
1759 /* When the realloc is required, then no extent may have
1761 extent_mismatch
= realloc_required
1762 || GFC_DESCRIPTOR_EXTENT (dst
, dst_cur_dim
) != delta
;
1763 /* When it already known, that a realloc is needed or
1764 the extent does not match the needed one. */
1765 if (realloc_required
|| realloc_needed
1768 /* Check whether dst is reallocatable. */
1769 if (unlikely (!dst_reallocatable
))
1771 caf_internal_error (nonallocextentmismatch
, stat
,
1773 GFC_DESCRIPTOR_EXTENT (dst
,
1777 /* Only report an error, when the extent needs to be
1778 modified, which is not allowed. */
1779 else if (!dst_reallocatable
&& extent_mismatch
)
1781 caf_internal_error (extentoutofrange
, stat
, NULL
,
1785 realloc_needed
= true;
1787 /* Only change the extent when it does not match. This is
1788 to prevent resetting given array bounds. */
1789 if (extent_mismatch
)
1790 GFC_DIMENSION_SET (dst
->dim
[dst_cur_dim
], 1, delta
,
1794 /* Only increase the dim counter, when in an array ref. */
1795 if (in_array_ref
&& dst_cur_dim
< dst_rank
)
1798 size
*= (index_type
)delta
;
1802 array_extent_fixed
= true;
1803 in_array_ref
= false;
1804 /* Check, if we got less dimensional refs than the rank of dst
1806 assert (dst_cur_dim
== GFC_DESCRIPTOR_RANK (dst
));
1809 case CAF_REF_STATIC_ARRAY
:
1810 for (i
= 0; riter
->u
.a
.mode
[i
] != CAF_ARR_REF_NONE
; ++i
)
1812 switch (riter
->u
.a
.mode
[i
])
1814 case CAF_ARR_REF_VECTOR
:
1815 delta
= riter
->u
.a
.dim
[i
].v
.nvec
;
1816 #define KINDCASE(kind, type) case kind: \
1817 memptr += ((type *)riter->u.a.dim[i].v.vector)[0] \
1818 * riter->item_size; \
1821 switch (riter
->u
.a
.dim
[i
].v
.kind
)
1823 KINDCASE (1, GFC_INTEGER_1
);
1824 KINDCASE (2, GFC_INTEGER_2
);
1825 KINDCASE (4, GFC_INTEGER_4
);
1826 #ifdef HAVE_GFC_INTEGER_8
1827 KINDCASE (8, GFC_INTEGER_8
);
1829 #ifdef HAVE_GFC_INTEGER_16
1830 KINDCASE (16, GFC_INTEGER_16
);
1833 caf_internal_error (vecrefunknownkind
, stat
, NULL
, 0);
1838 case CAF_ARR_REF_FULL
:
1839 delta
= riter
->u
.a
.dim
[i
].s
.end
/ riter
->u
.a
.dim
[i
].s
.stride
1841 /* The memptr stays unchanged when ref'ing the first element
1844 case CAF_ARR_REF_RANGE
:
1845 COMPUTE_NUM_ITEMS (delta
,
1846 riter
->u
.a
.dim
[i
].s
.stride
,
1847 riter
->u
.a
.dim
[i
].s
.start
,
1848 riter
->u
.a
.dim
[i
].s
.end
);
1849 memptr
+= riter
->u
.a
.dim
[i
].s
.start
1850 * riter
->u
.a
.dim
[i
].s
.stride
1853 case CAF_ARR_REF_SINGLE
:
1855 memptr
+= riter
->u
.a
.dim
[i
].s
.start
1856 * riter
->u
.a
.dim
[i
].s
.stride
1859 case CAF_ARR_REF_OPEN_END
:
1860 /* This and OPEN_START are mapped to a RANGE and therefore
1861 can not occur here. */
1862 case CAF_ARR_REF_OPEN_START
:
1864 caf_internal_error (unknownarrreftype
, stat
, NULL
, 0);
1869 /* Check the various properties of the destination array.
1870 Is an array expected and present? */
1871 if (delta
> 1 && dst_rank
== 0)
1873 /* No, an array is required, but not provided. */
1874 caf_internal_error (extentoutofrange
, stat
, NULL
, 0);
1877 /* Special mode when called by __caf_sendget_by_ref (). */
1878 if (dst_rank
== -1 && GFC_DESCRIPTOR_DATA (dst
) == NULL
)
1880 dst_rank
= dst_cur_dim
+ 1;
1881 GFC_DESCRIPTOR_RANK (dst
) = dst_rank
;
1882 GFC_DESCRIPTOR_SIZE (dst
) = dst_kind
;
1884 /* When dst is an array. */
1887 /* Check that dst_cur_dim is valid for dst. Can be
1888 superceeded only by scalar data. */
1889 if (dst_cur_dim
>= dst_rank
&& delta
!= 1)
1891 caf_internal_error (rankoutofrange
, stat
, NULL
, 0);
1894 /* Do further checks, when the source is not scalar. */
1895 else if (delta
!= 1)
1897 /* Check that the extent is not scalar and we are not in
1898 an array ref for the dst side. */
1901 /* Check that this is the non-scalar extent. */
1902 if (!array_extent_fixed
)
1904 /* In an array extent now. */
1905 in_array_ref
= true;
1906 /* The dst is not reallocatable, so nothing more
1907 to do, then correct the dim counter. */
1912 caf_internal_error (doublearrayref
, stat
, NULL
,
1917 /* When the realloc is required, then no extent may have
1919 extent_mismatch
= realloc_required
1920 || GFC_DESCRIPTOR_EXTENT (dst
, dst_cur_dim
) != delta
;
1921 /* When it is already known, that a realloc is needed or
1922 the extent does not match the needed one. */
1923 if (realloc_required
|| realloc_needed
1926 /* Check whether dst is reallocatable. */
1927 if (unlikely (!dst_reallocatable
))
1929 caf_internal_error (nonallocextentmismatch
, stat
,
1931 GFC_DESCRIPTOR_EXTENT (dst
,
1935 /* Only report an error, when the extent needs to be
1936 modified, which is not allowed. */
1937 else if (!dst_reallocatable
&& extent_mismatch
)
1939 caf_internal_error (extentoutofrange
, stat
, NULL
,
1943 realloc_needed
= true;
1945 /* Only change the extent when it does not match. This is
1946 to prevent resetting given array bounds. */
1947 if (extent_mismatch
)
1948 GFC_DIMENSION_SET (dst
->dim
[dst_cur_dim
], 1, delta
,
1951 /* Only increase the dim counter, when in an array ref. */
1952 if (in_array_ref
&& dst_cur_dim
< dst_rank
)
1955 size
*= (index_type
)delta
;
1959 array_extent_fixed
= true;
1960 in_array_ref
= false;
1961 /* Check, if we got less dimensional refs than the rank of dst
1963 assert (dst_cur_dim
== GFC_DESCRIPTOR_RANK (dst
));
1967 caf_internal_error (unknownreftype
, stat
, NULL
, 0);
1970 src_size
= riter
->item_size
;
1971 riter
= riter
->next
;
1973 if (size
== 0 || src_size
== 0)
1976 - size contains the number of elements to store in the destination array,
1977 - src_size gives the size in bytes of each item in the destination array.
1982 if (!array_extent_fixed
)
1985 /* Special mode when called by __caf_sendget_by_ref (). */
1986 if (dst_rank
== -1 && GFC_DESCRIPTOR_DATA (dst
) == NULL
)
1988 dst_rank
= dst_cur_dim
+ 1;
1989 GFC_DESCRIPTOR_RANK (dst
) = dst_rank
;
1990 GFC_DESCRIPTOR_SIZE (dst
) = dst_kind
;
1992 /* This can happen only, when the result is scalar. */
1993 for (dst_cur_dim
= 0; dst_cur_dim
< dst_rank
; ++dst_cur_dim
)
1994 GFC_DIMENSION_SET (dst
->dim
[dst_cur_dim
], 1, 1, 1);
1997 GFC_DESCRIPTOR_DATA (dst
) = malloc (size
* GFC_DESCRIPTOR_SIZE (dst
));
1998 if (unlikely (GFC_DESCRIPTOR_DATA (dst
) == NULL
))
2000 caf_internal_error (cannotallocdst
, stat
, NULL
, 0);
2005 /* Reset the token. */
2006 single_token
= TOKEN (token
);
2007 memptr
= single_token
->memptr
;
2008 src
= single_token
->desc
;
2009 memset(dst_index
, 0, sizeof (dst_index
));
2011 get_for_ref (refs
, &i
, dst_index
, single_token
, dst
, src
,
2012 GFC_DESCRIPTOR_DATA (dst
), memptr
, dst_kind
, src_kind
, 0, 0,
2018 send_by_ref (caf_reference_t
*ref
, size_t *i
, size_t *src_index
,
2019 caf_single_token_t single_token
, gfc_descriptor_t
*dst
,
2020 gfc_descriptor_t
*src
, void *ds
, void *sr
,
2021 int dst_kind
, int src_kind
, size_t dst_dim
, size_t src_dim
,
2022 size_t num
, size_t size
, int *stat
, int dst_type
)
2024 const char vecrefunknownkind
[] = "libcaf_single::caf_send_by_ref(): "
2025 "unknown kind in vector-ref.\n";
2026 ptrdiff_t extent_dst
= 1, array_offset_dst
= 0, stride_dst
;
2027 const size_t src_rank
= GFC_DESCRIPTOR_RANK (src
);
2029 if (unlikely (ref
== NULL
))
2030 /* May be we should issue an error here, because this case should not
2034 if (ref
->next
== NULL
)
2036 size_t src_size
= GFC_DESCRIPTOR_SIZE (src
);
2037 ptrdiff_t array_offset_src
= 0;;
2041 case CAF_REF_COMPONENT
:
2042 if (ref
->u
.c
.caf_token_offset
> 0)
2044 if (*(void**)(ds
+ ref
->u
.c
.offset
) == NULL
)
2046 /* Create a scalar temporary array descriptor. */
2047 gfc_descriptor_t static_dst
;
2048 GFC_DESCRIPTOR_DATA (&static_dst
) = NULL
;
2049 GFC_DESCRIPTOR_DTYPE (&static_dst
)
2050 = GFC_DESCRIPTOR_DTYPE (src
);
2051 /* The component can be allocated now, because it is a
2053 _gfortran_caf_register (ref
->item_size
,
2054 CAF_REGTYPE_COARRAY_ALLOC
,
2055 ds
+ ref
->u
.c
.caf_token_offset
,
2056 &static_dst
, stat
, NULL
, 0);
2057 single_token
= *(caf_single_token_t
*)
2058 (ds
+ ref
->u
.c
.caf_token_offset
);
2059 /* In case of an error in allocation return. When stat is
2060 NULL, then register_component() terminates on error. */
2061 if (stat
!= NULL
&& *stat
)
2063 /* Publish the allocated memory. */
2064 *((void **)(ds
+ ref
->u
.c
.offset
))
2065 = GFC_DESCRIPTOR_DATA (&static_dst
);
2066 ds
= GFC_DESCRIPTOR_DATA (&static_dst
);
2067 /* Set the type from the src. */
2068 dst_type
= GFC_DESCRIPTOR_TYPE (src
);
2072 single_token
= *(caf_single_token_t
*)
2073 (ds
+ ref
->u
.c
.caf_token_offset
);
2074 dst
= single_token
->desc
;
2077 ds
= GFC_DESCRIPTOR_DATA (dst
);
2078 dst_type
= GFC_DESCRIPTOR_TYPE (dst
);
2081 ds
= *(void **)(ds
+ ref
->u
.c
.offset
);
2083 copy_data (ds
, sr
, dst_type
, GFC_DESCRIPTOR_TYPE (src
),
2084 dst_kind
, src_kind
, ref
->item_size
, src_size
, 1, stat
);
2087 copy_data (ds
+ ref
->u
.c
.offset
, sr
, dst_type
,
2088 GFC_DESCRIPTOR_TYPE (src
),
2089 dst_kind
, src_kind
, ref
->item_size
, src_size
, 1, stat
);
2092 case CAF_REF_STATIC_ARRAY
:
2093 /* Intentionally fall through. */
2095 if (ref
->u
.a
.mode
[dst_dim
] == CAF_ARR_REF_NONE
)
2099 for (size_t d
= 0; d
< src_rank
; ++d
)
2100 array_offset_src
+= src_index
[d
];
2101 copy_data (ds
, sr
+ array_offset_src
* src_size
,
2102 dst_type
, GFC_DESCRIPTOR_TYPE (src
), dst_kind
,
2103 src_kind
, ref
->item_size
, src_size
, num
, stat
);
2106 copy_data (ds
, sr
, dst_type
, GFC_DESCRIPTOR_TYPE (src
),
2107 dst_kind
, src_kind
, ref
->item_size
, src_size
, num
,
2114 caf_runtime_error (unreachable
);
2120 case CAF_REF_COMPONENT
:
2121 if (ref
->u
.c
.caf_token_offset
> 0)
2123 if (*(void**)(ds
+ ref
->u
.c
.offset
) == NULL
)
2125 /* This component refs an unallocated array. Non-arrays are
2126 caught in the if (!ref->next) above. */
2127 dst
= (gfc_descriptor_t
*)(ds
+ ref
->u
.c
.offset
);
2128 /* Assume that the rank and the dimensions fit for copying src
2130 GFC_DESCRIPTOR_DTYPE (dst
) = GFC_DESCRIPTOR_DTYPE (src
);
2133 for (size_t d
= 0; d
< src_rank
; ++d
)
2135 extent_dst
= GFC_DIMENSION_EXTENT (src
->dim
[d
]);
2136 GFC_DIMENSION_LBOUND (dst
->dim
[d
]) = 0;
2137 GFC_DIMENSION_UBOUND (dst
->dim
[d
]) = extent_dst
- 1;
2138 GFC_DIMENSION_STRIDE (dst
->dim
[d
]) = stride_dst
;
2139 stride_dst
*= extent_dst
;
2141 /* Null the data-pointer to make register_component allocate
2143 GFC_DESCRIPTOR_DATA (dst
) = NULL
;
2145 /* The size of the array is given by size. */
2146 _gfortran_caf_register (size
* ref
->item_size
,
2147 CAF_REGTYPE_COARRAY_ALLOC
,
2148 ds
+ ref
->u
.c
.caf_token_offset
,
2149 dst
, stat
, NULL
, 0);
2150 /* In case of an error in allocation return. When stat is
2151 NULL, then register_component() terminates on error. */
2152 if (stat
!= NULL
&& *stat
)
2155 single_token
= *(caf_single_token_t
*)(ds
+ ref
->u
.c
.caf_token_offset
);
2156 /* When a component is allocatable (caf_token_offset != 0) and not an
2157 array (ref->next->type == CAF_REF_COMPONENT), then ds has to be
2159 if (ref
->next
&& ref
->next
->type
== CAF_REF_COMPONENT
)
2160 ds
= *(void **)(ds
+ ref
->u
.c
.offset
);
2162 ds
+= ref
->u
.c
.offset
;
2164 send_by_ref (ref
->next
, i
, src_index
, single_token
,
2165 single_token
->desc
, src
, ds
, sr
,
2166 dst_kind
, src_kind
, 0, src_dim
, 1, size
, stat
, dst_type
);
2169 send_by_ref (ref
->next
, i
, src_index
, single_token
,
2170 (gfc_descriptor_t
*)(ds
+ ref
->u
.c
.offset
), src
,
2171 ds
+ ref
->u
.c
.offset
, sr
, dst_kind
, src_kind
, 0, src_dim
,
2172 1, size
, stat
, dst_type
);
2175 if (ref
->u
.a
.mode
[dst_dim
] == CAF_ARR_REF_NONE
)
2177 send_by_ref (ref
->next
, i
, src_index
, single_token
,
2178 (gfc_descriptor_t
*)ds
, src
, ds
, sr
, dst_kind
, src_kind
,
2179 0, src_dim
, 1, size
, stat
, dst_type
);
2182 /* Only when on the left most index switch the data pointer to
2183 the array's data pointer. And only for non-static arrays. */
2184 if (dst_dim
== 0 && ref
->type
!= CAF_REF_STATIC_ARRAY
)
2185 ds
= GFC_DESCRIPTOR_DATA (dst
);
2186 switch (ref
->u
.a
.mode
[dst_dim
])
2188 case CAF_ARR_REF_VECTOR
:
2189 array_offset_dst
= 0;
2190 src_index
[src_dim
] = 0;
2191 for (size_t idx
= 0; idx
< ref
->u
.a
.dim
[dst_dim
].v
.nvec
;
2194 #define KINDCASE(kind, type) case kind: \
2195 array_offset_dst = (((index_type) \
2196 ((type *)ref->u.a.dim[dst_dim].v.vector)[idx]) \
2197 - GFC_DIMENSION_LBOUND (dst->dim[dst_dim])) \
2198 * GFC_DIMENSION_STRIDE (dst->dim[dst_dim]); \
2201 switch (ref
->u
.a
.dim
[dst_dim
].v
.kind
)
2203 KINDCASE (1, GFC_INTEGER_1
);
2204 KINDCASE (2, GFC_INTEGER_2
);
2205 KINDCASE (4, GFC_INTEGER_4
);
2206 #ifdef HAVE_GFC_INTEGER_8
2207 KINDCASE (8, GFC_INTEGER_8
);
2209 #ifdef HAVE_GFC_INTEGER_16
2210 KINDCASE (16, GFC_INTEGER_16
);
2213 caf_internal_error (vecrefunknownkind
, stat
, NULL
, 0);
2218 send_by_ref (ref
, i
, src_index
, single_token
, dst
, src
,
2219 ds
+ array_offset_dst
* ref
->item_size
, sr
,
2220 dst_kind
, src_kind
, dst_dim
+ 1, src_dim
+ 1,
2221 1, size
, stat
, dst_type
);
2224 += GFC_DIMENSION_STRIDE (src
->dim
[src_dim
]);
2227 case CAF_ARR_REF_FULL
:
2228 COMPUTE_NUM_ITEMS (extent_dst
,
2229 ref
->u
.a
.dim
[dst_dim
].s
.stride
,
2230 GFC_DIMENSION_LBOUND (dst
->dim
[dst_dim
]),
2231 GFC_DIMENSION_UBOUND (dst
->dim
[dst_dim
]));
2232 array_offset_dst
= 0;
2233 stride_dst
= GFC_DIMENSION_STRIDE (dst
->dim
[dst_dim
])
2234 * ref
->u
.a
.dim
[dst_dim
].s
.stride
;
2235 src_index
[src_dim
] = 0;
2236 for (index_type idx
= 0; idx
< extent_dst
;
2237 ++idx
, array_offset_dst
+= stride_dst
)
2239 send_by_ref (ref
, i
, src_index
, single_token
, dst
, src
,
2240 ds
+ array_offset_dst
* ref
->item_size
, sr
,
2241 dst_kind
, src_kind
, dst_dim
+ 1, src_dim
+ 1,
2242 1, size
, stat
, dst_type
);
2245 += GFC_DIMENSION_STRIDE (src
->dim
[src_dim
]);
2248 case CAF_ARR_REF_RANGE
:
2249 COMPUTE_NUM_ITEMS (extent_dst
,
2250 ref
->u
.a
.dim
[dst_dim
].s
.stride
,
2251 ref
->u
.a
.dim
[dst_dim
].s
.start
,
2252 ref
->u
.a
.dim
[dst_dim
].s
.end
);
2253 array_offset_dst
= ref
->u
.a
.dim
[dst_dim
].s
.start
2254 - GFC_DIMENSION_LBOUND (dst
->dim
[dst_dim
]);
2255 stride_dst
= GFC_DIMENSION_STRIDE (dst
->dim
[dst_dim
])
2256 * ref
->u
.a
.dim
[dst_dim
].s
.stride
;
2257 src_index
[src_dim
] = 0;
2258 for (index_type idx
= 0; idx
< extent_dst
; ++idx
)
2260 send_by_ref (ref
, i
, src_index
, single_token
, dst
, src
,
2261 ds
+ array_offset_dst
* ref
->item_size
, sr
,
2262 dst_kind
, src_kind
, dst_dim
+ 1, src_dim
+ 1,
2263 1, size
, stat
, dst_type
);
2266 += GFC_DIMENSION_STRIDE (src
->dim
[src_dim
]);
2267 array_offset_dst
+= stride_dst
;
2270 case CAF_ARR_REF_SINGLE
:
2271 array_offset_dst
= (ref
->u
.a
.dim
[dst_dim
].s
.start
2272 - GFC_DIMENSION_LBOUND (dst
->dim
[dst_dim
]))
2273 * GFC_DIMENSION_STRIDE (dst
->dim
[dst_dim
]);
2274 send_by_ref (ref
, i
, src_index
, single_token
, dst
, src
, ds
2275 + array_offset_dst
* ref
->item_size
, sr
,
2276 dst_kind
, src_kind
, dst_dim
+ 1, src_dim
, 1,
2277 size
, stat
, dst_type
);
2279 case CAF_ARR_REF_OPEN_END
:
2280 COMPUTE_NUM_ITEMS (extent_dst
,
2281 ref
->u
.a
.dim
[dst_dim
].s
.stride
,
2282 ref
->u
.a
.dim
[dst_dim
].s
.start
,
2283 GFC_DIMENSION_UBOUND (dst
->dim
[dst_dim
]));
2284 array_offset_dst
= ref
->u
.a
.dim
[dst_dim
].s
.start
2285 - GFC_DIMENSION_LBOUND (dst
->dim
[dst_dim
]);
2286 stride_dst
= GFC_DIMENSION_STRIDE (dst
->dim
[dst_dim
])
2287 * ref
->u
.a
.dim
[dst_dim
].s
.stride
;
2288 src_index
[src_dim
] = 0;
2289 for (index_type idx
= 0; idx
< extent_dst
; ++idx
)
2291 send_by_ref (ref
, i
, src_index
, single_token
, dst
, src
,
2292 ds
+ array_offset_dst
* ref
->item_size
, sr
,
2293 dst_kind
, src_kind
, dst_dim
+ 1, src_dim
+ 1,
2294 1, size
, stat
, dst_type
);
2297 += GFC_DIMENSION_STRIDE (src
->dim
[src_dim
]);
2298 array_offset_dst
+= stride_dst
;
2301 case CAF_ARR_REF_OPEN_START
:
2302 COMPUTE_NUM_ITEMS (extent_dst
,
2303 ref
->u
.a
.dim
[dst_dim
].s
.stride
,
2304 GFC_DIMENSION_LBOUND (dst
->dim
[dst_dim
]),
2305 ref
->u
.a
.dim
[dst_dim
].s
.end
);
2306 array_offset_dst
= 0;
2307 stride_dst
= GFC_DIMENSION_STRIDE (dst
->dim
[dst_dim
])
2308 * ref
->u
.a
.dim
[dst_dim
].s
.stride
;
2309 src_index
[src_dim
] = 0;
2310 for (index_type idx
= 0; idx
< extent_dst
; ++idx
)
2312 send_by_ref (ref
, i
, src_index
, single_token
, dst
, src
,
2313 ds
+ array_offset_dst
* ref
->item_size
, sr
,
2314 dst_kind
, src_kind
, dst_dim
+ 1, src_dim
+ 1,
2315 1, size
, stat
, dst_type
);
2318 += GFC_DIMENSION_STRIDE (src
->dim
[src_dim
]);
2319 array_offset_dst
+= stride_dst
;
2323 caf_runtime_error (unreachable
);
2326 case CAF_REF_STATIC_ARRAY
:
2327 if (ref
->u
.a
.mode
[dst_dim
] == CAF_ARR_REF_NONE
)
2329 send_by_ref (ref
->next
, i
, src_index
, single_token
, NULL
,
2330 src
, ds
, sr
, dst_kind
, src_kind
,
2331 0, src_dim
, 1, size
, stat
, dst_type
);
2334 switch (ref
->u
.a
.mode
[dst_dim
])
2336 case CAF_ARR_REF_VECTOR
:
2337 array_offset_dst
= 0;
2338 src_index
[src_dim
] = 0;
2339 for (size_t idx
= 0; idx
< ref
->u
.a
.dim
[dst_dim
].v
.nvec
;
2342 #define KINDCASE(kind, type) case kind: \
2343 array_offset_dst = ((type *)ref->u.a.dim[dst_dim].v.vector)[idx]; \
2346 switch (ref
->u
.a
.dim
[dst_dim
].v
.kind
)
2348 KINDCASE (1, GFC_INTEGER_1
);
2349 KINDCASE (2, GFC_INTEGER_2
);
2350 KINDCASE (4, GFC_INTEGER_4
);
2351 #ifdef HAVE_GFC_INTEGER_8
2352 KINDCASE (8, GFC_INTEGER_8
);
2354 #ifdef HAVE_GFC_INTEGER_16
2355 KINDCASE (16, GFC_INTEGER_16
);
2358 caf_runtime_error (unreachable
);
2363 send_by_ref (ref
, i
, src_index
, single_token
, NULL
, src
,
2364 ds
+ array_offset_dst
* ref
->item_size
, sr
,
2365 dst_kind
, src_kind
, dst_dim
+ 1, src_dim
+ 1,
2366 1, size
, stat
, dst_type
);
2368 += GFC_DIMENSION_STRIDE (src
->dim
[src_dim
]);
2371 case CAF_ARR_REF_FULL
:
2372 src_index
[src_dim
] = 0;
2373 for (array_offset_dst
= 0 ;
2374 array_offset_dst
<= ref
->u
.a
.dim
[dst_dim
].s
.end
;
2375 array_offset_dst
+= ref
->u
.a
.dim
[dst_dim
].s
.stride
)
2377 send_by_ref (ref
, i
, src_index
, single_token
, NULL
, src
,
2378 ds
+ array_offset_dst
* ref
->item_size
, sr
,
2379 dst_kind
, src_kind
, dst_dim
+ 1, src_dim
+ 1,
2380 1, size
, stat
, dst_type
);
2383 += GFC_DIMENSION_STRIDE (src
->dim
[src_dim
]);
2386 case CAF_ARR_REF_RANGE
:
2387 COMPUTE_NUM_ITEMS (extent_dst
,
2388 ref
->u
.a
.dim
[dst_dim
].s
.stride
,
2389 ref
->u
.a
.dim
[dst_dim
].s
.start
,
2390 ref
->u
.a
.dim
[dst_dim
].s
.end
);
2391 array_offset_dst
= ref
->u
.a
.dim
[dst_dim
].s
.start
;
2392 src_index
[src_dim
] = 0;
2393 for (index_type idx
= 0; idx
< extent_dst
; ++idx
)
2395 send_by_ref (ref
, i
, src_index
, single_token
, NULL
, src
,
2396 ds
+ array_offset_dst
* ref
->item_size
, sr
,
2397 dst_kind
, src_kind
, dst_dim
+ 1, src_dim
+ 1,
2398 1, size
, stat
, dst_type
);
2401 += GFC_DIMENSION_STRIDE (src
->dim
[src_dim
]);
2402 array_offset_dst
+= ref
->u
.a
.dim
[dst_dim
].s
.stride
;
2405 case CAF_ARR_REF_SINGLE
:
2406 array_offset_dst
= ref
->u
.a
.dim
[dst_dim
].s
.start
;
2407 send_by_ref (ref
, i
, src_index
, single_token
, NULL
, src
,
2408 ds
+ array_offset_dst
* ref
->item_size
, sr
,
2409 dst_kind
, src_kind
, dst_dim
+ 1, src_dim
, 1,
2410 size
, stat
, dst_type
);
2412 /* The OPEN_* are mapped to a RANGE and therefore can not occur. */
2413 case CAF_ARR_REF_OPEN_END
:
2414 case CAF_ARR_REF_OPEN_START
:
2416 caf_runtime_error (unreachable
);
2420 caf_runtime_error (unreachable
);
2426 _gfortran_caf_send_by_ref (caf_token_t token
,
2427 int image_index
__attribute__ ((unused
)),
2428 gfc_descriptor_t
*src
, caf_reference_t
*refs
,
2429 int dst_kind
, int src_kind
,
2430 bool may_require_tmp
__attribute__ ((unused
)),
2431 bool dst_reallocatable
, int *stat
, int dst_type
)
2433 const char vecrefunknownkind
[] = "libcaf_single::caf_get_by_ref(): "
2434 "unknown kind in vector-ref.\n";
2435 const char unknownreftype
[] = "libcaf_single::caf_send_by_ref(): "
2436 "unknown reference type.\n";
2437 const char unknownarrreftype
[] = "libcaf_single::caf_send_by_ref(): "
2438 "unknown array reference type.\n";
2439 const char rankoutofrange
[] = "libcaf_single::caf_send_by_ref(): "
2440 "rank out of range.\n";
2441 const char realloconinnerref
[] = "libcaf_single::caf_send_by_ref(): "
2442 "reallocation of array followed by component ref not allowed.\n";
2443 const char cannotallocdst
[] = "libcaf_single::caf_send_by_ref(): "
2444 "can not allocate memory.\n";
2445 const char nonallocextentmismatch
[] = "libcaf_single::caf_send_by_ref(): "
2446 "extent of non-allocatable array mismatch.\n";
2447 const char innercompref
[] = "libcaf_single::caf_send_by_ref(): "
2448 "inner unallocated component detected.\n";
2450 size_t dst_index
[GFC_MAX_DIMENSIONS
];
2451 int src_rank
= GFC_DESCRIPTOR_RANK (src
);
2452 int src_cur_dim
= 0;
2453 size_t src_size
= 0;
2454 caf_single_token_t single_token
= TOKEN (token
);
2455 void *memptr
= single_token
->memptr
;
2456 gfc_descriptor_t
*dst
= single_token
->desc
;
2457 caf_reference_t
*riter
= refs
;
2459 bool extent_mismatch
;
2460 /* Note that the component is not allocated yet. */
2461 index_type new_component_idx
= -1;
2466 /* Compute the size of the result. In the beginning size just counts the
2467 number of elements. */
2471 switch (riter
->type
)
2473 case CAF_REF_COMPONENT
:
2474 if (unlikely (new_component_idx
!= -1))
2476 /* Allocating a component in the middle of a component ref is not
2477 support. We don't know the type to allocate. */
2478 caf_internal_error (innercompref
, stat
, NULL
, 0);
2481 if (riter
->u
.c
.caf_token_offset
> 0)
2483 /* Check whether the allocatable component is zero, then no
2484 token is present, too. The token's pointer is not cleared
2485 when the structure is initialized. */
2486 if (*(void**)(memptr
+ riter
->u
.c
.offset
) == NULL
)
2488 /* This component is not yet allocated. Check that it is
2489 allocatable here. */
2490 if (!dst_reallocatable
)
2492 caf_internal_error (cannotallocdst
, stat
, NULL
, 0);
2495 single_token
= NULL
;
2500 single_token
= *(caf_single_token_t
*)
2501 (memptr
+ riter
->u
.c
.caf_token_offset
);
2502 memptr
+= riter
->u
.c
.offset
;
2503 dst
= single_token
->desc
;
2507 /* Regular component. */
2508 memptr
+= riter
->u
.c
.offset
;
2509 dst
= (gfc_descriptor_t
*)memptr
;
2514 memptr
= GFC_DESCRIPTOR_DATA (dst
);
2517 /* When the dst array needs to be allocated, then look at the
2518 extent of the source array in the dimension dst_cur_dim. */
2519 for (i
= 0; riter
->u
.a
.mode
[i
] != CAF_ARR_REF_NONE
; ++i
)
2521 switch (riter
->u
.a
.mode
[i
])
2523 case CAF_ARR_REF_VECTOR
:
2524 delta
= riter
->u
.a
.dim
[i
].v
.nvec
;
2525 #define KINDCASE(kind, type) case kind: \
2526 memptr += (((index_type) \
2527 ((type *)riter->u.a.dim[i].v.vector)[0]) \
2528 - GFC_DIMENSION_LBOUND (dst->dim[i])) \
2529 * GFC_DIMENSION_STRIDE (dst->dim[i]) \
2530 * riter->item_size; \
2533 switch (riter
->u
.a
.dim
[i
].v
.kind
)
2535 KINDCASE (1, GFC_INTEGER_1
);
2536 KINDCASE (2, GFC_INTEGER_2
);
2537 KINDCASE (4, GFC_INTEGER_4
);
2538 #ifdef HAVE_GFC_INTEGER_8
2539 KINDCASE (8, GFC_INTEGER_8
);
2541 #ifdef HAVE_GFC_INTEGER_16
2542 KINDCASE (16, GFC_INTEGER_16
);
2545 caf_internal_error (vecrefunknownkind
, stat
, NULL
, 0);
2550 case CAF_ARR_REF_FULL
:
2552 COMPUTE_NUM_ITEMS (delta
,
2553 riter
->u
.a
.dim
[i
].s
.stride
,
2554 GFC_DIMENSION_LBOUND (dst
->dim
[i
]),
2555 GFC_DIMENSION_UBOUND (dst
->dim
[i
]));
2557 COMPUTE_NUM_ITEMS (delta
,
2558 riter
->u
.a
.dim
[i
].s
.stride
,
2559 GFC_DIMENSION_LBOUND (src
->dim
[src_cur_dim
]),
2560 GFC_DIMENSION_UBOUND (src
->dim
[src_cur_dim
]));
2562 case CAF_ARR_REF_RANGE
:
2563 COMPUTE_NUM_ITEMS (delta
,
2564 riter
->u
.a
.dim
[i
].s
.stride
,
2565 riter
->u
.a
.dim
[i
].s
.start
,
2566 riter
->u
.a
.dim
[i
].s
.end
);
2567 memptr
+= (riter
->u
.a
.dim
[i
].s
.start
2568 - dst
->dim
[i
].lower_bound
)
2569 * GFC_DIMENSION_STRIDE (dst
->dim
[i
])
2572 case CAF_ARR_REF_SINGLE
:
2574 memptr
+= (riter
->u
.a
.dim
[i
].s
.start
2575 - dst
->dim
[i
].lower_bound
)
2576 * GFC_DIMENSION_STRIDE (dst
->dim
[i
])
2579 case CAF_ARR_REF_OPEN_END
:
2581 COMPUTE_NUM_ITEMS (delta
,
2582 riter
->u
.a
.dim
[i
].s
.stride
,
2583 riter
->u
.a
.dim
[i
].s
.start
,
2584 GFC_DIMENSION_UBOUND (dst
->dim
[i
]));
2586 COMPUTE_NUM_ITEMS (delta
,
2587 riter
->u
.a
.dim
[i
].s
.stride
,
2588 riter
->u
.a
.dim
[i
].s
.start
,
2589 GFC_DIMENSION_UBOUND (src
->dim
[src_cur_dim
]));
2590 memptr
+= (riter
->u
.a
.dim
[i
].s
.start
2591 - dst
->dim
[i
].lower_bound
)
2592 * GFC_DIMENSION_STRIDE (dst
->dim
[i
])
2595 case CAF_ARR_REF_OPEN_START
:
2597 COMPUTE_NUM_ITEMS (delta
,
2598 riter
->u
.a
.dim
[i
].s
.stride
,
2599 GFC_DIMENSION_LBOUND (dst
->dim
[i
]),
2600 riter
->u
.a
.dim
[i
].s
.end
);
2602 COMPUTE_NUM_ITEMS (delta
,
2603 riter
->u
.a
.dim
[i
].s
.stride
,
2604 GFC_DIMENSION_LBOUND (src
->dim
[src_cur_dim
]),
2605 riter
->u
.a
.dim
[i
].s
.end
);
2606 /* The memptr stays unchanged when ref'ing the first element
2610 caf_internal_error (unknownarrreftype
, stat
, NULL
, 0);
2616 /* Check the various properties of the source array.
2617 When src is an array. */
2618 if (delta
> 1 && src_rank
> 0)
2620 /* Check that src_cur_dim is valid for src. Can be
2621 superceeded only by scalar data. */
2622 if (src_cur_dim
>= src_rank
)
2624 caf_internal_error (rankoutofrange
, stat
, NULL
, 0);
2627 /* Do further checks, when the source is not scalar. */
2630 /* When the realloc is required, then no extent may have
2632 extent_mismatch
= memptr
== NULL
2634 && GFC_DESCRIPTOR_EXTENT (dst
, src_cur_dim
)
2636 /* When it already known, that a realloc is needed or
2637 the extent does not match the needed one. */
2638 if (extent_mismatch
)
2640 /* Check whether dst is reallocatable. */
2641 if (unlikely (!dst_reallocatable
))
2643 caf_internal_error (nonallocextentmismatch
, stat
,
2645 GFC_DESCRIPTOR_EXTENT (dst
,
2649 /* Report error on allocatable but missing inner
2651 else if (riter
->next
!= NULL
)
2653 caf_internal_error (realloconinnerref
, stat
, NULL
,
2658 /* Only change the extent when it does not match. This is
2659 to prevent resetting given array bounds. */
2660 if (extent_mismatch
)
2661 GFC_DIMENSION_SET (dst
->dim
[src_cur_dim
], 1, delta
,
2664 /* Increase the dim-counter of the src only when the extent
2666 if (src_cur_dim
< src_rank
2667 && GFC_DESCRIPTOR_EXTENT (src
, src_cur_dim
) == delta
)
2670 size
*= (index_type
)delta
;
2673 case CAF_REF_STATIC_ARRAY
:
2674 for (i
= 0; riter
->u
.a
.mode
[i
] != CAF_ARR_REF_NONE
; ++i
)
2676 switch (riter
->u
.a
.mode
[i
])
2678 case CAF_ARR_REF_VECTOR
:
2679 delta
= riter
->u
.a
.dim
[i
].v
.nvec
;
2680 #define KINDCASE(kind, type) case kind: \
2681 memptr += ((type *)riter->u.a.dim[i].v.vector)[0] \
2682 * riter->item_size; \
2685 switch (riter
->u
.a
.dim
[i
].v
.kind
)
2687 KINDCASE (1, GFC_INTEGER_1
);
2688 KINDCASE (2, GFC_INTEGER_2
);
2689 KINDCASE (4, GFC_INTEGER_4
);
2690 #ifdef HAVE_GFC_INTEGER_8
2691 KINDCASE (8, GFC_INTEGER_8
);
2693 #ifdef HAVE_GFC_INTEGER_16
2694 KINDCASE (16, GFC_INTEGER_16
);
2697 caf_internal_error (vecrefunknownkind
, stat
, NULL
, 0);
2702 case CAF_ARR_REF_FULL
:
2703 delta
= riter
->u
.a
.dim
[i
].s
.end
/ riter
->u
.a
.dim
[i
].s
.stride
2705 /* The memptr stays unchanged when ref'ing the first element
2708 case CAF_ARR_REF_RANGE
:
2709 COMPUTE_NUM_ITEMS (delta
,
2710 riter
->u
.a
.dim
[i
].s
.stride
,
2711 riter
->u
.a
.dim
[i
].s
.start
,
2712 riter
->u
.a
.dim
[i
].s
.end
);
2713 memptr
+= riter
->u
.a
.dim
[i
].s
.start
2714 * riter
->u
.a
.dim
[i
].s
.stride
2717 case CAF_ARR_REF_SINGLE
:
2719 memptr
+= riter
->u
.a
.dim
[i
].s
.start
2720 * riter
->u
.a
.dim
[i
].s
.stride
2723 case CAF_ARR_REF_OPEN_END
:
2724 /* This and OPEN_START are mapped to a RANGE and therefore
2725 can not occur here. */
2726 case CAF_ARR_REF_OPEN_START
:
2728 caf_internal_error (unknownarrreftype
, stat
, NULL
, 0);
2733 /* Check the various properties of the source array.
2734 Only when the source array is not scalar examine its
2736 if (delta
> 1 && src_rank
> 0)
2738 /* Check that src_cur_dim is valid for src. Can be
2739 superceeded only by scalar data. */
2740 if (src_cur_dim
>= src_rank
)
2742 caf_internal_error (rankoutofrange
, stat
, NULL
, 0);
2747 /* We will not be able to realloc the dst, because that's
2748 a fixed size array. */
2749 extent_mismatch
= GFC_DESCRIPTOR_EXTENT (src
, src_cur_dim
)
2751 /* When the extent does not match the needed one we can
2753 if (extent_mismatch
)
2755 caf_internal_error (nonallocextentmismatch
, stat
,
2757 GFC_DESCRIPTOR_EXTENT (src
,
2764 size
*= (index_type
)delta
;
2768 caf_internal_error (unknownreftype
, stat
, NULL
, 0);
2771 src_size
= riter
->item_size
;
2772 riter
= riter
->next
;
2774 if (size
== 0 || src_size
== 0)
2777 - size contains the number of elements to store in the destination array,
2778 - src_size gives the size in bytes of each item in the destination array.
2781 /* Reset the token. */
2782 single_token
= TOKEN (token
);
2783 memptr
= single_token
->memptr
;
2784 dst
= single_token
->desc
;
2785 memset (dst_index
, 0, sizeof (dst_index
));
2787 send_by_ref (refs
, &i
, dst_index
, single_token
, dst
, src
,
2788 memptr
, GFC_DESCRIPTOR_DATA (src
), dst_kind
, src_kind
, 0, 0,
2789 1, size
, stat
, dst_type
);
2795 _gfortran_caf_sendget_by_ref (caf_token_t dst_token
, int dst_image_index
,
2796 caf_reference_t
*dst_refs
, caf_token_t src_token
,
2797 int src_image_index
,
2798 caf_reference_t
*src_refs
, int dst_kind
,
2799 int src_kind
, bool may_require_tmp
, int *dst_stat
,
2800 int *src_stat
, int dst_type
, int src_type
)
2802 GFC_FULL_ARRAY_DESCRIPTOR (GFC_MAX_DIMENSIONS
, void) temp
;
2803 GFC_DESCRIPTOR_DATA (&temp
) = NULL
;
2804 GFC_DESCRIPTOR_RANK (&temp
) = -1;
2805 GFC_DESCRIPTOR_TYPE (&temp
) = dst_type
;
2807 _gfortran_caf_get_by_ref (src_token
, src_image_index
, &temp
, src_refs
,
2808 dst_kind
, src_kind
, may_require_tmp
, true,
2809 src_stat
, src_type
);
2811 if (src_stat
&& *src_stat
!= 0)
2814 _gfortran_caf_send_by_ref (dst_token
, dst_image_index
, &temp
, dst_refs
,
2815 dst_kind
, dst_kind
, may_require_tmp
, true,
2816 dst_stat
, dst_type
);
2817 if (GFC_DESCRIPTOR_DATA (&temp
))
2818 free (GFC_DESCRIPTOR_DATA (&temp
));
2823 _gfortran_caf_atomic_define (caf_token_t token
, size_t offset
,
2824 int image_index
__attribute__ ((unused
)),
2825 void *value
, int *stat
,
2826 int type
__attribute__ ((unused
)), int kind
)
2830 uint32_t *atom
= (uint32_t *) ((char *) MEMTOK (token
) + offset
);
2832 __atomic_store (atom
, (uint32_t *) value
, __ATOMIC_RELAXED
);
2839 _gfortran_caf_atomic_ref (caf_token_t token
, size_t offset
,
2840 int image_index
__attribute__ ((unused
)),
2841 void *value
, int *stat
,
2842 int type
__attribute__ ((unused
)), int kind
)
2846 uint32_t *atom
= (uint32_t *) ((char *) MEMTOK (token
) + offset
);
2848 __atomic_load (atom
, (uint32_t *) value
, __ATOMIC_RELAXED
);
2856 _gfortran_caf_atomic_cas (caf_token_t token
, size_t offset
,
2857 int image_index
__attribute__ ((unused
)),
2858 void *old
, void *compare
, void *new_val
, int *stat
,
2859 int type
__attribute__ ((unused
)), int kind
)
2863 uint32_t *atom
= (uint32_t *) ((char *) MEMTOK (token
) + offset
);
2865 *(uint32_t *) old
= *(uint32_t *) compare
;
2866 (void) __atomic_compare_exchange_n (atom
, (uint32_t *) old
,
2867 *(uint32_t *) new_val
, false,
2868 __ATOMIC_RELAXED
, __ATOMIC_RELAXED
);
2875 _gfortran_caf_atomic_op (int op
, caf_token_t token
, size_t offset
,
2876 int image_index
__attribute__ ((unused
)),
2877 void *value
, void *old
, int *stat
,
2878 int type
__attribute__ ((unused
)), int kind
)
2883 uint32_t *atom
= (uint32_t *) ((char *) MEMTOK (token
) + offset
);
2887 case GFC_CAF_ATOMIC_ADD
:
2888 res
= __atomic_fetch_add (atom
, *(uint32_t *) value
, __ATOMIC_RELAXED
);
2890 case GFC_CAF_ATOMIC_AND
:
2891 res
= __atomic_fetch_and (atom
, *(uint32_t *) value
, __ATOMIC_RELAXED
);
2893 case GFC_CAF_ATOMIC_OR
:
2894 res
= __atomic_fetch_or (atom
, *(uint32_t *) value
, __ATOMIC_RELAXED
);
2896 case GFC_CAF_ATOMIC_XOR
:
2897 res
= __atomic_fetch_xor (atom
, *(uint32_t *) value
, __ATOMIC_RELAXED
);
2900 __builtin_unreachable();
2904 *(uint32_t *) old
= res
;
2911 _gfortran_caf_event_post (caf_token_t token
, size_t index
,
2912 int image_index
__attribute__ ((unused
)),
2913 int *stat
, char *errmsg
__attribute__ ((unused
)),
2914 size_t errmsg_len
__attribute__ ((unused
)))
2917 uint32_t *event
= (uint32_t *) ((char *) MEMTOK (token
) + index
2918 * sizeof (uint32_t));
2919 __atomic_fetch_add (event
, (uint32_t) value
, __ATOMIC_RELAXED
);
2926 _gfortran_caf_event_wait (caf_token_t token
, size_t index
,
2927 int until_count
, int *stat
,
2928 char *errmsg
__attribute__ ((unused
)),
2929 size_t errmsg_len
__attribute__ ((unused
)))
2931 uint32_t *event
= (uint32_t *) ((char *) MEMTOK (token
) + index
2932 * sizeof (uint32_t));
2933 uint32_t value
= (uint32_t)-until_count
;
2934 __atomic_fetch_add (event
, (uint32_t) value
, __ATOMIC_RELAXED
);
2941 _gfortran_caf_event_query (caf_token_t token
, size_t index
,
2942 int image_index
__attribute__ ((unused
)),
2943 int *count
, int *stat
)
2945 uint32_t *event
= (uint32_t *) ((char *) MEMTOK (token
) + index
2946 * sizeof (uint32_t));
2947 __atomic_load (event
, (uint32_t *) count
, __ATOMIC_RELAXED
);
2954 _gfortran_caf_lock (caf_token_t token
, size_t index
,
2955 int image_index
__attribute__ ((unused
)),
2956 int *aquired_lock
, int *stat
, char *errmsg
, size_t errmsg_len
)
2958 const char *msg
= "Already locked";
2959 bool *lock
= &((bool *) MEMTOK (token
))[index
];
2965 *aquired_lock
= (int) true;
2973 *aquired_lock
= (int) false;
2985 size_t len
= (sizeof (msg
) > errmsg_len
) ? errmsg_len
2987 memcpy (errmsg
, msg
, len
);
2988 if (errmsg_len
> len
)
2989 memset (&errmsg
[len
], ' ', errmsg_len
-len
);
2993 _gfortran_caf_error_stop_str (msg
, strlen (msg
));
2998 _gfortran_caf_unlock (caf_token_t token
, size_t index
,
2999 int image_index
__attribute__ ((unused
)),
3000 int *stat
, char *errmsg
, size_t errmsg_len
)
3002 const char *msg
= "Variable is not locked";
3003 bool *lock
= &((bool *) MEMTOK (token
))[index
];
3018 size_t len
= (sizeof (msg
) > errmsg_len
) ? errmsg_len
3020 memcpy (errmsg
, msg
, len
);
3021 if (errmsg_len
> len
)
3022 memset (&errmsg
[len
], ' ', errmsg_len
-len
);
3026 _gfortran_caf_error_stop_str (msg
, strlen (msg
));
3030 _gfortran_caf_is_present (caf_token_t token
,
3031 int image_index
__attribute__ ((unused
)),
3032 caf_reference_t
*refs
)
3034 const char arraddressingnotallowed
[] = "libcaf_single::caf_is_present(): "
3035 "only scalar indexes allowed.\n";
3036 const char unknownreftype
[] = "libcaf_single::caf_get_by_ref(): "
3037 "unknown reference type.\n";
3038 const char unknownarrreftype
[] = "libcaf_single::caf_get_by_ref(): "
3039 "unknown array reference type.\n";
3041 caf_single_token_t single_token
= TOKEN (token
);
3042 void *memptr
= single_token
->memptr
;
3043 gfc_descriptor_t
*src
= single_token
->desc
;
3044 caf_reference_t
*riter
= refs
;
3048 switch (riter
->type
)
3050 case CAF_REF_COMPONENT
:
3051 if (riter
->u
.c
.caf_token_offset
)
3053 single_token
= *(caf_single_token_t
*)
3054 (memptr
+ riter
->u
.c
.caf_token_offset
);
3055 memptr
= single_token
->memptr
;
3056 src
= single_token
->desc
;
3060 memptr
+= riter
->u
.c
.offset
;
3061 src
= (gfc_descriptor_t
*)memptr
;
3065 for (i
= 0; riter
->u
.a
.mode
[i
] != CAF_ARR_REF_NONE
; ++i
)
3067 switch (riter
->u
.a
.mode
[i
])
3069 case CAF_ARR_REF_SINGLE
:
3070 memptr
+= (riter
->u
.a
.dim
[i
].s
.start
3071 - GFC_DIMENSION_LBOUND (src
->dim
[i
]))
3072 * GFC_DIMENSION_STRIDE (src
->dim
[i
])
3075 case CAF_ARR_REF_FULL
:
3076 /* A full array ref is allowed on the last reference only. */
3077 if (riter
->next
== NULL
)
3079 /* else fall through reporting an error. */
3081 case CAF_ARR_REF_VECTOR
:
3082 case CAF_ARR_REF_RANGE
:
3083 case CAF_ARR_REF_OPEN_END
:
3084 case CAF_ARR_REF_OPEN_START
:
3085 caf_internal_error (arraddressingnotallowed
, 0, NULL
, 0);
3088 caf_internal_error (unknownarrreftype
, 0, NULL
, 0);
3093 case CAF_REF_STATIC_ARRAY
:
3094 for (i
= 0; riter
->u
.a
.mode
[i
] != CAF_ARR_REF_NONE
; ++i
)
3096 switch (riter
->u
.a
.mode
[i
])
3098 case CAF_ARR_REF_SINGLE
:
3099 memptr
+= riter
->u
.a
.dim
[i
].s
.start
3100 * riter
->u
.a
.dim
[i
].s
.stride
3103 case CAF_ARR_REF_FULL
:
3104 /* A full array ref is allowed on the last reference only. */
3105 if (riter
->next
== NULL
)
3107 /* else fall through reporting an error. */
3109 case CAF_ARR_REF_VECTOR
:
3110 case CAF_ARR_REF_RANGE
:
3111 case CAF_ARR_REF_OPEN_END
:
3112 case CAF_ARR_REF_OPEN_START
:
3113 caf_internal_error (arraddressingnotallowed
, 0, NULL
, 0);
3116 caf_internal_error (unknownarrreftype
, 0, NULL
, 0);
3122 caf_internal_error (unknownreftype
, 0, NULL
, 0);
3125 riter
= riter
->next
;
3127 return memptr
!= NULL
;