* es.po, sv.po: Update.
[official-gcc.git] / libgfortran / caf / single.c
blob1ad13bd5643843e4342a9ae3a0505dafce7a74fa
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)
10 any later version.
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/>. */
26 #include "libcaf.h"
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. */
31 #include <stdint.h>
32 #include <assert.h>
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. */
41 void *memptr;
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. */
46 bool owning_memory;
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. */
61 static void
62 caf_runtime_error (const char *message, ...)
64 va_list ap;
65 fprintf (stderr, "Fortran runtime error: ");
66 va_start (ap, message);
67 vfprintf (stderr, message, ap);
68 va_end (ap);
69 fprintf (stderr, "\n");
71 /* FIXME: Shutdown the Fortran RTL to flush the buffer. PR 43849. */
72 exit (EXIT_FAILURE);
75 /* Error handling is similar everytime. */
76 static void
77 caf_internal_error (const char *msg, int *stat, char *errmsg,
78 size_t errmsg_len, ...)
80 va_list args;
81 va_start (args, errmsg_len);
82 if (stat)
84 *stat = 1;
85 if (errmsg_len > 0)
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);
91 va_end (args);
92 return;
94 else
95 caf_runtime_error (msg, args);
96 va_end (args);
100 void
101 _gfortran_caf_init (int *argc __attribute__ ((unused)),
102 char ***argv __attribute__ ((unused)))
107 void
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)))
123 return 1;
128 _gfortran_caf_num_images (int distance __attribute__ ((unused)),
129 int failed __attribute__ ((unused)))
131 return 1;
135 void
136 _gfortran_caf_register (size_t size, caf_register_t type, caf_token_t *token,
137 gfc_descriptor_t *data, int *stat, char *errmsg,
138 size_t errmsg_len)
140 const char alloc_fail_msg[] = "Failed to allocate coarray";
141 void *local;
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)
152 local = NULL;
153 else
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
160 || (local == 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. */
166 if (local)
167 free (local);
168 if (*token)
169 free (*token);
170 caf_internal_error (alloc_fail_msg, stat, errmsg, errmsg_len);
171 return;
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;
180 if (stat)
181 *stat = 0;
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;
189 tmp->token = *token;
190 caf_static_list = tmp;
192 GFC_DESCRIPTOR_DATA (data) = local;
196 void
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));
209 *token = NULL;
211 else
213 single_token->memptr = NULL;
214 single_token->owning_memory = false;
217 if (stat)
218 *stat = 0;
222 void
223 _gfortran_caf_sync_all (int *stat,
224 char *errmsg __attribute__ ((unused)),
225 size_t errmsg_len __attribute__ ((unused)))
227 __asm__ __volatile__ ("":::"memory");
228 if (stat)
229 *stat = 0;
233 void
234 _gfortran_caf_sync_memory (int *stat,
235 char *errmsg __attribute__ ((unused)),
236 size_t errmsg_len __attribute__ ((unused)))
238 __asm__ __volatile__ ("":::"memory");
239 if (stat)
240 *stat = 0;
244 void
245 _gfortran_caf_sync_images (int count __attribute__ ((unused)),
246 int images[] __attribute__ ((unused)),
247 int *stat,
248 char *errmsg __attribute__ ((unused)),
249 size_t errmsg_len __attribute__ ((unused)))
251 #ifdef GFC_CAF_CHECK
252 int i;
254 for (i = 0; i < count; i++)
255 if (images[i] != 1)
257 fprintf (stderr, "COARRAY ERROR: Invalid image index %d to SYNC "
258 "IMAGES", images[i]);
259 exit (EXIT_FAILURE);
261 #endif
263 __asm__ __volatile__ ("":::"memory");
264 if (stat)
265 *stat = 0;
269 void
270 _gfortran_caf_stop_numeric(int stop_code, bool quiet)
272 if (!quiet)
273 fprintf (stderr, "STOP %d\n", stop_code);
274 exit (0);
278 void
279 _gfortran_caf_stop_str(const char *string, size_t len, bool quiet)
281 if (!quiet)
283 fputs ("STOP ", stderr);
284 while (len--)
285 fputc (*(string++), stderr);
286 fputs ("\n", stderr);
288 exit (0);
292 void
293 _gfortran_caf_error_stop_str (const char *string, size_t len, bool quiet)
295 if (!quiet)
297 fputs ("ERROR STOP ", stderr);
298 while (len--)
299 fputc (*(string++), stderr);
300 fputs ("\n", stderr);
302 exit (1);
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);
313 exit (0);
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)))
323 if (image == 1)
324 return 0;
325 else
326 return CAF_STAT_STOPPED_IMAGE;
330 /* Single image library. There can not be any failed images with only one
331 image. */
333 void
334 _gfortran_caf_failed_images (gfc_descriptor_t *array,
335 caf_team_t * team __attribute__ ((unused)),
336 int * kind)
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;
348 array->offset = 0;
352 /* With only one image available no other images can be stopped. Therefore
353 return an empty array. */
355 void
356 _gfortran_caf_stopped_images (gfc_descriptor_t *array,
357 caf_team_t * team __attribute__ ((unused)),
358 int * kind)
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;
370 array->offset = 0;
374 void
375 _gfortran_caf_error_stop (int error, bool quiet)
377 if (!quiet)
378 fprintf (stderr, "ERROR STOP %d\n", error);
379 exit (error);
383 void
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)))
389 if (stat)
390 *stat = 0;
393 void
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)))
399 if (stat)
400 *stat = 0;
403 void
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)))
410 if (stat)
411 *stat = 0;
414 void
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)))
421 if (stat)
422 *stat = 0;
426 void
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)))
436 if (stat)
437 *stat = 0;
441 static void
442 assign_char4_from_char1 (size_t dst_size, size_t src_size, uint32_t *dst,
443 unsigned char *src)
445 size_t i, n;
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) ' ';
454 static void
455 assign_char1_from_char4 (size_t dst_size, size_t src_size, unsigned char *dst,
456 uint32_t *src)
458 size_t i, n;
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];
462 if (dst_size > n)
463 memset (&dst[n], ' ', dst_size - n);
467 static void
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;
473 #else
474 typedef int64_t int128t;
475 #endif
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;
487 #else
488 typedef double real128t;
489 typedef _Complex double complex128t;
490 #endif
492 int128t int_val = 0;
493 real128t real_val = 0;
494 complex128t cmpx_val = 0;
496 switch (src_type)
498 case BT_INTEGER:
499 if (src_kind == 1)
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;
510 #endif
511 else
512 goto error;
513 break;
514 case BT_REAL:
515 if (src_kind == 4)
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;
522 #endif
523 #ifdef HAVE_GFC_REAL_16
524 else if (src_kind == 16)
525 real_val = *(real128t*) src;
526 #endif
527 else
528 goto error;
529 break;
530 case BT_COMPLEX:
531 if (src_kind == 4)
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;
538 #endif
539 #ifdef HAVE_GFC_REAL_16
540 else if (src_kind == 16)
541 cmpx_val = *(complex128t*) src;
542 #endif
543 else
544 goto error;
545 break;
546 default:
547 goto error;
550 switch (dst_type)
552 case BT_INTEGER:
553 if (src_type == BT_INTEGER)
555 if (dst_kind == 1)
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;
566 #endif
567 else
568 goto error;
570 else if (src_type == BT_REAL)
572 if (dst_kind == 1)
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;
583 #endif
584 else
585 goto error;
587 else if (src_type == BT_COMPLEX)
589 if (dst_kind == 1)
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;
600 #endif
601 else
602 goto error;
604 else
605 goto error;
606 return;
607 case BT_REAL:
608 if (src_type == BT_INTEGER)
610 if (dst_kind == 4)
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;
617 #endif
618 #ifdef HAVE_GFC_REAL_16
619 else if (dst_kind == 16)
620 *(real128t*) dst = (real128t) int_val;
621 #endif
622 else
623 goto error;
625 else if (src_type == BT_REAL)
627 if (dst_kind == 4)
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;
634 #endif
635 #ifdef HAVE_GFC_REAL_16
636 else if (dst_kind == 16)
637 *(real128t*) dst = (real128t) real_val;
638 #endif
639 else
640 goto error;
642 else if (src_type == BT_COMPLEX)
644 if (dst_kind == 4)
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;
651 #endif
652 #ifdef HAVE_GFC_REAL_16
653 else if (dst_kind == 16)
654 *(real128t*) dst = (real128t) cmpx_val;
655 #endif
656 else
657 goto error;
659 return;
660 case BT_COMPLEX:
661 if (src_type == BT_INTEGER)
663 if (dst_kind == 4)
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;
670 #endif
671 #ifdef HAVE_GFC_REAL_16
672 else if (dst_kind == 16)
673 *(complex128t*) dst = (complex128t) int_val;
674 #endif
675 else
676 goto error;
678 else if (src_type == BT_REAL)
680 if (dst_kind == 4)
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;
687 #endif
688 #ifdef HAVE_GFC_REAL_16
689 else if (dst_kind == 16)
690 *(complex128t*) dst = (complex128t) real_val;
691 #endif
692 else
693 goto error;
695 else if (src_type == BT_COMPLEX)
697 if (dst_kind == 4)
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;
704 #endif
705 #ifdef HAVE_GFC_REAL_16
706 else if (dst_kind == 16)
707 *(complex128t*) dst = (complex128t) cmpx_val;
708 #endif
709 else
710 goto error;
712 else
713 goto error;
714 return;
715 default:
716 goto error;
719 error:
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);
722 if (stat)
723 *stat = 1;
724 else
725 abort ();
729 void
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. */
738 size_t i, k, size;
739 int j;
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);
744 if (stat)
745 *stat = 0;
747 if (rank == 0)
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)
757 if (dst_kind == 1)
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),
767 sr);
768 else if (GFC_DESCRIPTOR_TYPE (dest) == BT_CHARACTER)
769 assign_char4_from_char1 (dst_size, src_size, GFC_DESCRIPTOR_DATA (dest),
770 sr);
771 else
772 convert_type (GFC_DESCRIPTOR_DATA (dest), GFC_DESCRIPTOR_TYPE (dest),
773 dst_kind, sr, GFC_DESCRIPTOR_TYPE (src), src_kind, stat);
774 return;
777 size = 1;
778 for (j = 0; j < rank; j++)
780 ptrdiff_t dimextent = dest->dim[j]._ubound - dest->dim[j].lower_bound + 1;
781 if (dimextent < 0)
782 dimextent = 0;
783 size *= dimextent;
786 if (size == 0)
787 return;
789 if (may_require_tmp)
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;
816 array_offset_sr = 0;
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)
843 if (dst_kind == 1)
844 memset ((void*)(char*) dst + src_size, ' ',
845 dst_size-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);
855 else
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;
861 free (tmp);
862 return;
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;
883 stride = 1;
884 extent = 1;
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)
904 if (dst_kind == 1)
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);
915 else
916 convert_type (dst, GFC_DESCRIPTOR_TYPE (dest), dst_kind,
917 sr, GFC_DESCRIPTOR_TYPE (src), src_kind, stat);
922 void
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. */
931 size_t i, k, size;
932 int j;
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);
937 if (stat)
938 *stat = 0;
940 if (rank == 0)
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)
950 if (dst_kind == 1)
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));
963 else
964 convert_type (dst, GFC_DESCRIPTOR_TYPE (dest), dst_kind,
965 GFC_DESCRIPTOR_DATA (src), GFC_DESCRIPTOR_TYPE (src),
966 src_kind, stat);
967 return;
970 size = 1;
971 for (j = 0; j < rank; j++)
973 ptrdiff_t dimextent = dest->dim[j]._ubound - dest->dim[j].lower_bound + 1;
974 if (dimextent < 0)
975 dimextent = 0;
976 size *= dimextent;
979 if (size == 0)
980 return;
982 if (may_require_tmp)
984 ptrdiff_t array_offset_sr, array_offset_dst;
985 void *tmp;
987 if (GFC_DESCRIPTOR_RANK (src) == 0)
989 tmp = malloc (src_size);
990 memcpy (tmp, GFC_DESCRIPTOR_DATA (src), src_size);
992 else
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)
1040 memmove (dst, sr,
1041 dst_size > src_size ? src_size : dst_size);
1042 if (GFC_DESCRIPTOR_TYPE (dest) == BT_CHARACTER
1043 && dst_size > src_size)
1045 if (dst_kind == 1)
1046 memset ((void*)(char*) dst + src_size, ' ',
1047 dst_size-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);
1057 else
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;
1063 free (tmp);
1064 return;
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));
1084 void *sr;
1085 if (GFC_DESCRIPTOR_RANK (src) != 0)
1087 ptrdiff_t array_offset_sr = 0;
1088 stride = 1;
1089 extent = 1;
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));
1103 else
1104 sr = src->base_addr;
1106 if (GFC_DESCRIPTOR_TYPE (dest) == GFC_DESCRIPTOR_TYPE (src)
1107 && dst_kind == src_kind)
1109 memmove (dst, sr,
1110 dst_size > src_size ? src_size : dst_size);
1111 if (GFC_DESCRIPTOR_TYPE (dest) == BT_CHARACTER && dst_size > src_size)
1113 if (dst_kind == 1)
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);
1124 else
1125 convert_type (dst, GFC_DESCRIPTOR_TYPE (dest), dst_kind,
1126 sr, GFC_DESCRIPTOR_TYPE (src), src_kind, stat);
1131 void
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,
1135 size_t src_offset,
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)
1146 + src_offset);
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";
1157 static void
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)
1162 size_t k;
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)
1169 if (dst_kind == 1)
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);
1180 else
1181 for (k = 0; k < num; ++k)
1183 convert_type (ds, dst_type, dst_kind, sr, src_type, src_kind, stat);
1184 ds += dst_size;
1185 sr += src_size;
1190 #define COMPUTE_NUM_ITEMS(num, stride, lb, ub) \
1191 do { \
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; \
1196 } while (0)
1199 static void
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
1211 occur. */
1212 return;
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);
1220 switch (ref->type)
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);
1230 else
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);
1234 ++(*i);
1235 return;
1236 case CAF_REF_STATIC_ARRAY:
1237 /* Intentionally fall through. */
1238 case CAF_REF_ARRAY:
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,
1246 stat);
1247 *i += num;
1248 return;
1250 break;
1251 default:
1252 caf_runtime_error (unreachable);
1256 switch (ref->type)
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;
1265 else
1266 src = NULL;
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 can not be allocatable or they
1272 become an array with descriptor. */
1273 sr = *(void **)(sr + ref->u.c.offset);
1274 else
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,
1279 1, stat, src_type);
1281 else
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,
1285 stat, src_type);
1286 return;
1287 case CAF_REF_ARRAY:
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);
1293 return;
1295 /* Only when on the left most index switch the data pointer to
1296 the array's data pointer. */
1297 if (src_dim == 0)
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;
1306 ++idx)
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]); \
1313 break
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);
1322 #endif
1323 #ifdef HAVE_GFC_INTEGER_16
1324 KINDCASE (16, GFC_INTEGER_16);
1325 #endif
1326 default:
1327 caf_runtime_error (unreachable);
1328 return;
1330 #undef KINDCASE
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,
1335 1, stat, src_type);
1336 dst_index[dst_dim]
1337 += GFC_DIMENSION_STRIDE (dst->dim[dst_dim]);
1339 return;
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,
1355 1, stat, src_type);
1356 dst_index[dst_dim]
1357 += GFC_DIMENSION_STRIDE (dst->dim[dst_dim]);
1359 return;
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,
1382 1, stat, src_type);
1383 dst_index[dst_dim]
1384 += GFC_DIMENSION_STRIDE (dst->dim[dst_dim]);
1385 array_offset_src += stride_src;
1387 return;
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,
1396 stat, src_type);
1397 return;
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,
1414 1, stat, src_type);
1415 dst_index[dst_dim]
1416 += GFC_DIMENSION_STRIDE (dst->dim[dst_dim]);
1417 array_offset_src += stride_src;
1419 return;
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,
1434 1, stat, src_type);
1435 dst_index[dst_dim]
1436 += GFC_DIMENSION_STRIDE (dst->dim[dst_dim]);
1437 array_offset_src += stride_src;
1439 return;
1440 default:
1441 caf_runtime_error (unreachable);
1443 return;
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);
1450 return;
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;
1458 ++idx)
1460 #define KINDCASE(kind, type) case kind: \
1461 array_offset_src = ((type *)ref->u.a.dim[src_dim].v.vector)[idx]; \
1462 break
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);
1471 #endif
1472 #ifdef HAVE_GFC_INTEGER_16
1473 KINDCASE (16, GFC_INTEGER_16);
1474 #endif
1475 default:
1476 caf_runtime_error (unreachable);
1477 return;
1479 #undef KINDCASE
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,
1484 1, stat, src_type);
1485 dst_index[dst_dim]
1486 += GFC_DIMENSION_STRIDE (dst->dim[dst_dim]);
1488 return;
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,
1498 1, stat, src_type);
1499 dst_index[dst_dim]
1500 += GFC_DIMENSION_STRIDE (dst->dim[dst_dim]);
1502 return;
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,
1515 1, stat, src_type);
1516 dst_index[dst_dim]
1517 += GFC_DIMENSION_STRIDE (dst->dim[dst_dim]);
1518 array_offset_src += ref->u.a.dim[src_dim].s.stride;
1520 return;
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,
1526 stat, src_type);
1527 return;
1528 /* The OPEN_* are mapped to a RANGE and therefore can not occur. */
1529 case CAF_ARR_REF_OPEN_END:
1530 case CAF_ARR_REF_OPEN_START:
1531 default:
1532 caf_runtime_error (unreachable);
1534 return;
1535 default:
1536 caf_runtime_error (unreachable);
1541 void
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,
1548 int src_type)
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 "can not 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";
1566 size_t size, i;
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;
1575 long delta;
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
1579 all. */
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);
1589 if (stat)
1590 *stat = 0;
1592 /* Compute the size of the result. In the beginning size just counts the
1593 number of elements. */
1594 size = 1;
1595 while (riter)
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;
1607 else
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
1612 a descriptor. */
1613 if (riter->next && riter->next->type == CAF_REF_ARRAY)
1614 src = (gfc_descriptor_t *)memptr;
1615 else
1616 src = NULL;
1618 break;
1619 case CAF_REF_ARRAY:
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; \
1632 break
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);
1641 #endif
1642 #ifdef HAVE_GFC_INTEGER_16
1643 KINDCASE (16, GFC_INTEGER_16);
1644 #endif
1645 default:
1646 caf_internal_error (vecrefunknownkind, stat, NULL, 0);
1647 return;
1649 #undef KINDCASE
1650 break;
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
1657 in a dimension. */
1658 break;
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])
1667 * riter->item_size;
1668 break;
1669 case CAF_ARR_REF_SINGLE:
1670 delta = 1;
1671 memptr += (riter->u.a.dim[i].s.start
1672 - GFC_DIMENSION_LBOUND (src->dim[i]))
1673 * GFC_DIMENSION_STRIDE (src->dim[i])
1674 * riter->item_size;
1675 break;
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])
1684 * riter->item_size;
1685 break;
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
1692 in a dimension. */
1693 break;
1694 default:
1695 caf_internal_error (unknownarrreftype, stat, NULL, 0);
1696 return;
1698 if (delta <= 0)
1699 return;
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);
1706 return;
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. */
1716 if (dst_rank > 0)
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);
1723 return;
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. */
1730 if (!in_array_ref)
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
1739 compatible. */
1740 if (i > 0
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;
1748 ++dst_cur_dim)
1749 GFC_DIMENSION_SET (dst->dim[dst_cur_dim],
1750 1, 1, 1);
1752 else
1753 dst_cur_dim = i;
1755 /* Else press thumbs, that there are enough
1756 dimensional refs to come. Checked below. */
1758 else
1760 caf_internal_error (doublearrayref, stat, NULL,
1762 return;
1765 /* When the realloc is required, then no extent may have
1766 been set. */
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
1772 || extent_mismatch)
1774 /* Check whether dst is reallocatable. */
1775 if (unlikely (!dst_reallocatable))
1777 caf_internal_error (nonallocextentmismatch, stat,
1778 NULL, 0, delta,
1779 GFC_DESCRIPTOR_EXTENT (dst,
1780 dst_cur_dim));
1781 return;
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,
1789 return;
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,
1797 size);
1800 /* Only increase the dim counter, when in an array ref. */
1801 if (in_array_ref && dst_cur_dim < dst_rank)
1802 ++dst_cur_dim;
1804 size *= (index_type)delta;
1806 if (in_array_ref)
1808 array_extent_fixed = true;
1809 in_array_ref = false;
1810 /* Check, if we got less dimensional refs than the rank of dst
1811 expects. */
1812 assert (dst_cur_dim == GFC_DESCRIPTOR_RANK (dst));
1814 break;
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; \
1825 break
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);
1834 #endif
1835 #ifdef HAVE_GFC_INTEGER_16
1836 KINDCASE (16, GFC_INTEGER_16);
1837 #endif
1838 default:
1839 caf_internal_error (vecrefunknownkind, stat, NULL, 0);
1840 return;
1842 #undef KINDCASE
1843 break;
1844 case CAF_ARR_REF_FULL:
1845 delta = riter->u.a.dim[i].s.end / riter->u.a.dim[i].s.stride
1846 + 1;
1847 /* The memptr stays unchanged when ref'ing the first element
1848 in a dimension. */
1849 break;
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
1857 * riter->item_size;
1858 break;
1859 case CAF_ARR_REF_SINGLE:
1860 delta = 1;
1861 memptr += riter->u.a.dim[i].s.start
1862 * riter->u.a.dim[i].s.stride
1863 * riter->item_size;
1864 break;
1865 case CAF_ARR_REF_OPEN_END:
1866 /* This and OPEN_START are mapped to a RANGE and therefore
1867 can not occur here. */
1868 case CAF_ARR_REF_OPEN_START:
1869 default:
1870 caf_internal_error (unknownarrreftype, stat, NULL, 0);
1871 return;
1873 if (delta <= 0)
1874 return;
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);
1881 return;
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. */
1891 if (dst_rank > 0)
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);
1898 return;
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. */
1905 if (!in_array_ref)
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. */
1914 dst_cur_dim = i;
1916 else
1918 caf_internal_error (doublearrayref, stat, NULL,
1920 return;
1923 /* When the realloc is required, then no extent may have
1924 been set. */
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
1930 || extent_mismatch)
1932 /* Check whether dst is reallocatable. */
1933 if (unlikely (!dst_reallocatable))
1935 caf_internal_error (nonallocextentmismatch, stat,
1936 NULL, 0, delta,
1937 GFC_DESCRIPTOR_EXTENT (dst,
1938 dst_cur_dim));
1939 return;
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,
1947 return;
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,
1955 size);
1957 /* Only increase the dim counter, when in an array ref. */
1958 if (in_array_ref && dst_cur_dim < dst_rank)
1959 ++dst_cur_dim;
1961 size *= (index_type)delta;
1963 if (in_array_ref)
1965 array_extent_fixed = true;
1966 in_array_ref = false;
1967 /* Check, if we got less dimensional refs than the rank of dst
1968 expects. */
1969 assert (dst_cur_dim == GFC_DESCRIPTOR_RANK (dst));
1971 break;
1972 default:
1973 caf_internal_error (unknownreftype, stat, NULL, 0);
1974 return;
1976 src_size = riter->item_size;
1977 riter = riter->next;
1979 if (size == 0 || src_size == 0)
1980 return;
1981 /* Postcondition:
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.
1986 if (realloc_needed)
1988 if (!array_extent_fixed)
1990 assert (size == 1);
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);
2007 return;
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));
2016 i = 0;
2017 get_for_ref (refs, &i, dst_index, single_token, dst, src,
2018 GFC_DESCRIPTOR_DATA (dst), memptr, dst_kind, src_kind, 0, 0,
2019 1, stat, src_type);
2023 static void
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
2037 occur. */
2038 return;
2040 if (ref->next == NULL)
2042 size_t src_size = GFC_DESCRIPTOR_SIZE (src);
2043 ptrdiff_t array_offset_src = 0;;
2045 switch (ref->type)
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
2058 scalar. */
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)
2068 return;
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);
2076 else
2078 single_token = *(caf_single_token_t *)
2079 (ds + ref->u.c.caf_token_offset);
2080 dst = single_token->desc;
2081 if (dst)
2083 ds = GFC_DESCRIPTOR_DATA (dst);
2084 dst_type = GFC_DESCRIPTOR_TYPE (dst);
2086 else
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);
2092 else
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);
2096 ++(*i);
2097 return;
2098 case CAF_REF_STATIC_ARRAY:
2099 /* Intentionally fall through. */
2100 case CAF_REF_ARRAY:
2101 if (ref->u.a.mode[dst_dim] == CAF_ARR_REF_NONE)
2103 if (src_rank > 0)
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);
2111 else
2112 copy_data (ds, sr, dst_type, GFC_DESCRIPTOR_TYPE (src),
2113 dst_kind, src_kind, ref->item_size, src_size, num,
2114 stat);
2115 *i += num;
2116 return;
2118 break;
2119 default:
2120 caf_runtime_error (unreachable);
2124 switch (ref->type)
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
2135 to dst. */
2136 GFC_DESCRIPTOR_DTYPE (dst) = GFC_DESCRIPTOR_DTYPE (src);
2137 dst->offset = 0;
2138 stride_dst = 1;
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
2148 its own memory. */
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)
2159 return;
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
2164 dereffed. */
2165 if (ref->next && ref->next->type == CAF_REF_COMPONENT)
2166 ds = *(void **)(ds + ref->u.c.offset);
2167 else
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);
2174 else
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);
2179 return;
2180 case CAF_REF_ARRAY:
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);
2186 return;
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;
2198 ++idx)
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]); \
2205 break
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);
2214 #endif
2215 #ifdef HAVE_GFC_INTEGER_16
2216 KINDCASE (16, GFC_INTEGER_16);
2217 #endif
2218 default:
2219 caf_internal_error (vecrefunknownkind, stat, NULL, 0);
2220 return;
2222 #undef KINDCASE
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);
2228 if (src_rank > 0)
2229 src_index[src_dim]
2230 += GFC_DIMENSION_STRIDE (src->dim[src_dim]);
2232 return;
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);
2249 if (src_rank > 0)
2250 src_index[src_dim]
2251 += GFC_DIMENSION_STRIDE (src->dim[src_dim]);
2253 return;
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);
2270 if (src_rank > 0)
2271 src_index[src_dim]
2272 += GFC_DIMENSION_STRIDE (src->dim[src_dim]);
2273 array_offset_dst += stride_dst;
2275 return;
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);
2284 return;
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);
2301 if (src_rank > 0)
2302 src_index[src_dim]
2303 += GFC_DIMENSION_STRIDE (src->dim[src_dim]);
2304 array_offset_dst += stride_dst;
2306 return;
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);
2322 if (src_rank > 0)
2323 src_index[src_dim]
2324 += GFC_DIMENSION_STRIDE (src->dim[src_dim]);
2325 array_offset_dst += stride_dst;
2327 return;
2328 default:
2329 caf_runtime_error (unreachable);
2331 return;
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);
2338 return;
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;
2346 ++idx)
2348 #define KINDCASE(kind, type) case kind: \
2349 array_offset_dst = ((type *)ref->u.a.dim[dst_dim].v.vector)[idx]; \
2350 break
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);
2359 #endif
2360 #ifdef HAVE_GFC_INTEGER_16
2361 KINDCASE (16, GFC_INTEGER_16);
2362 #endif
2363 default:
2364 caf_runtime_error (unreachable);
2365 return;
2367 #undef KINDCASE
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);
2373 src_index[src_dim]
2374 += GFC_DIMENSION_STRIDE (src->dim[src_dim]);
2376 return;
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);
2387 if (src_rank > 0)
2388 src_index[src_dim]
2389 += GFC_DIMENSION_STRIDE (src->dim[src_dim]);
2391 return;
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);
2405 if (src_rank > 0)
2406 src_index[src_dim]
2407 += GFC_DIMENSION_STRIDE (src->dim[src_dim]);
2408 array_offset_dst += ref->u.a.dim[dst_dim].s.stride;
2410 return;
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);
2417 return;
2418 /* The OPEN_* are mapped to a RANGE and therefore can not occur. */
2419 case CAF_ARR_REF_OPEN_END:
2420 case CAF_ARR_REF_OPEN_START:
2421 default:
2422 caf_runtime_error (unreachable);
2424 return;
2425 default:
2426 caf_runtime_error (unreachable);
2431 void
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 "can not 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";
2455 size_t size, i;
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;
2464 long delta;
2465 bool extent_mismatch;
2466 /* Note that the component is not allocated yet. */
2467 index_type new_component_idx = -1;
2469 if (stat)
2470 *stat = 0;
2472 /* Compute the size of the result. In the beginning size just counts the
2473 number of elements. */
2474 size = 1;
2475 while (riter)
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);
2485 return;
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);
2499 return;
2501 single_token = NULL;
2502 memptr = NULL;
2503 dst = NULL;
2504 break;
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;
2511 else
2513 /* Regular component. */
2514 memptr += riter->u.c.offset;
2515 dst = (gfc_descriptor_t *)memptr;
2517 break;
2518 case CAF_REF_ARRAY:
2519 if (dst != NULL)
2520 memptr = GFC_DESCRIPTOR_DATA (dst);
2521 else
2522 dst = src;
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; \
2537 break
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);
2546 #endif
2547 #ifdef HAVE_GFC_INTEGER_16
2548 KINDCASE (16, GFC_INTEGER_16);
2549 #endif
2550 default:
2551 caf_internal_error (vecrefunknownkind, stat, NULL, 0);
2552 return;
2554 #undef KINDCASE
2555 break;
2556 case CAF_ARR_REF_FULL:
2557 if (dst)
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]));
2562 else
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]));
2567 break;
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])
2576 * riter->item_size;
2577 break;
2578 case CAF_ARR_REF_SINGLE:
2579 delta = 1;
2580 memptr += (riter->u.a.dim[i].s.start
2581 - dst->dim[i].lower_bound)
2582 * GFC_DIMENSION_STRIDE (dst->dim[i])
2583 * riter->item_size;
2584 break;
2585 case CAF_ARR_REF_OPEN_END:
2586 if (dst)
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]));
2591 else
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])
2599 * riter->item_size;
2600 break;
2601 case CAF_ARR_REF_OPEN_START:
2602 if (dst)
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);
2607 else
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
2613 in a dimension. */
2614 break;
2615 default:
2616 caf_internal_error (unknownarrreftype, stat, NULL, 0);
2617 return;
2620 if (delta <= 0)
2621 return;
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);
2631 return;
2633 /* Do further checks, when the source is not scalar. */
2634 else
2636 /* When the realloc is required, then no extent may have
2637 been set. */
2638 extent_mismatch = memptr == NULL
2639 || (dst
2640 && GFC_DESCRIPTOR_EXTENT (dst, src_cur_dim)
2641 != delta);
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,
2650 NULL, 0, delta,
2651 GFC_DESCRIPTOR_EXTENT (dst,
2652 src_cur_dim));
2653 return;
2655 /* Report error on allocatable but missing inner
2656 ref. */
2657 else if (riter->next != NULL)
2659 caf_internal_error (realloconinnerref, stat, NULL,
2661 return;
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,
2668 size);
2670 /* Increase the dim-counter of the src only when the extent
2671 matches. */
2672 if (src_cur_dim < src_rank
2673 && GFC_DESCRIPTOR_EXTENT (src, src_cur_dim) == delta)
2674 ++src_cur_dim;
2676 size *= (index_type)delta;
2678 break;
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; \
2689 break
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);
2698 #endif
2699 #ifdef HAVE_GFC_INTEGER_16
2700 KINDCASE (16, GFC_INTEGER_16);
2701 #endif
2702 default:
2703 caf_internal_error (vecrefunknownkind, stat, NULL, 0);
2704 return;
2706 #undef KINDCASE
2707 break;
2708 case CAF_ARR_REF_FULL:
2709 delta = riter->u.a.dim[i].s.end / riter->u.a.dim[i].s.stride
2710 + 1;
2711 /* The memptr stays unchanged when ref'ing the first element
2712 in a dimension. */
2713 break;
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
2721 * riter->item_size;
2722 break;
2723 case CAF_ARR_REF_SINGLE:
2724 delta = 1;
2725 memptr += riter->u.a.dim[i].s.start
2726 * riter->u.a.dim[i].s.stride
2727 * riter->item_size;
2728 break;
2729 case CAF_ARR_REF_OPEN_END:
2730 /* This and OPEN_START are mapped to a RANGE and therefore
2731 can not occur here. */
2732 case CAF_ARR_REF_OPEN_START:
2733 default:
2734 caf_internal_error (unknownarrreftype, stat, NULL, 0);
2735 return;
2737 if (delta <= 0)
2738 return;
2739 /* Check the various properties of the source array.
2740 Only when the source array is not scalar examine its
2741 properties. */
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);
2749 return;
2751 else
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)
2756 != delta;
2757 /* When the extent does not match the needed one we can
2758 only stop here. */
2759 if (extent_mismatch)
2761 caf_internal_error (nonallocextentmismatch, stat,
2762 NULL, 0, delta,
2763 GFC_DESCRIPTOR_EXTENT (src,
2764 src_cur_dim));
2765 return;
2768 ++src_cur_dim;
2770 size *= (index_type)delta;
2772 break;
2773 default:
2774 caf_internal_error (unknownreftype, stat, NULL, 0);
2775 return;
2777 src_size = riter->item_size;
2778 riter = riter->next;
2780 if (size == 0 || src_size == 0)
2781 return;
2782 /* Postcondition:
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));
2792 i = 0;
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);
2796 assert (i == size);
2800 void
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, &temp, src_refs,
2814 dst_kind, src_kind, may_require_tmp, true,
2815 src_stat, src_type);
2817 if (src_stat && *src_stat != 0)
2818 return;
2820 _gfortran_caf_send_by_ref (dst_token, dst_image_index, &temp, dst_refs,
2821 dst_kind, dst_kind, may_require_tmp, true,
2822 dst_stat, dst_type);
2823 if (GFC_DESCRIPTOR_DATA (&temp))
2824 free (GFC_DESCRIPTOR_DATA (&temp));
2828 void
2829 _gfortran_caf_atomic_define (caf_token_t token, size_t offset,
2830 int image_index __attribute__ ((unused)),
2831 void *value, int *stat,
2832 int type __attribute__ ((unused)), int kind)
2834 assert(kind == 4);
2836 uint32_t *atom = (uint32_t *) ((char *) MEMTOK (token) + offset);
2838 __atomic_store (atom, (uint32_t *) value, __ATOMIC_RELAXED);
2840 if (stat)
2841 *stat = 0;
2844 void
2845 _gfortran_caf_atomic_ref (caf_token_t token, size_t offset,
2846 int image_index __attribute__ ((unused)),
2847 void *value, int *stat,
2848 int type __attribute__ ((unused)), int kind)
2850 assert(kind == 4);
2852 uint32_t *atom = (uint32_t *) ((char *) MEMTOK (token) + offset);
2854 __atomic_load (atom, (uint32_t *) value, __ATOMIC_RELAXED);
2856 if (stat)
2857 *stat = 0;
2861 void
2862 _gfortran_caf_atomic_cas (caf_token_t token, size_t offset,
2863 int image_index __attribute__ ((unused)),
2864 void *old, void *compare, void *new_val, int *stat,
2865 int type __attribute__ ((unused)), int kind)
2867 assert(kind == 4);
2869 uint32_t *atom = (uint32_t *) ((char *) MEMTOK (token) + offset);
2871 *(uint32_t *) old = *(uint32_t *) compare;
2872 (void) __atomic_compare_exchange_n (atom, (uint32_t *) old,
2873 *(uint32_t *) new_val, false,
2874 __ATOMIC_RELAXED, __ATOMIC_RELAXED);
2875 if (stat)
2876 *stat = 0;
2880 void
2881 _gfortran_caf_atomic_op (int op, caf_token_t token, size_t offset,
2882 int image_index __attribute__ ((unused)),
2883 void *value, void *old, int *stat,
2884 int type __attribute__ ((unused)), int kind)
2886 assert(kind == 4);
2888 uint32_t res;
2889 uint32_t *atom = (uint32_t *) ((char *) MEMTOK (token) + offset);
2891 switch (op)
2893 case GFC_CAF_ATOMIC_ADD:
2894 res = __atomic_fetch_add (atom, *(uint32_t *) value, __ATOMIC_RELAXED);
2895 break;
2896 case GFC_CAF_ATOMIC_AND:
2897 res = __atomic_fetch_and (atom, *(uint32_t *) value, __ATOMIC_RELAXED);
2898 break;
2899 case GFC_CAF_ATOMIC_OR:
2900 res = __atomic_fetch_or (atom, *(uint32_t *) value, __ATOMIC_RELAXED);
2901 break;
2902 case GFC_CAF_ATOMIC_XOR:
2903 res = __atomic_fetch_xor (atom, *(uint32_t *) value, __ATOMIC_RELAXED);
2904 break;
2905 default:
2906 __builtin_unreachable();
2909 if (old)
2910 *(uint32_t *) old = res;
2912 if (stat)
2913 *stat = 0;
2916 void
2917 _gfortran_caf_event_post (caf_token_t token, size_t index,
2918 int image_index __attribute__ ((unused)),
2919 int *stat, char *errmsg __attribute__ ((unused)),
2920 size_t errmsg_len __attribute__ ((unused)))
2922 uint32_t value = 1;
2923 uint32_t *event = (uint32_t *) ((char *) MEMTOK (token) + index
2924 * sizeof (uint32_t));
2925 __atomic_fetch_add (event, (uint32_t) value, __ATOMIC_RELAXED);
2927 if(stat)
2928 *stat = 0;
2931 void
2932 _gfortran_caf_event_wait (caf_token_t token, size_t index,
2933 int until_count, int *stat,
2934 char *errmsg __attribute__ ((unused)),
2935 size_t errmsg_len __attribute__ ((unused)))
2937 uint32_t *event = (uint32_t *) ((char *) MEMTOK (token) + index
2938 * sizeof (uint32_t));
2939 uint32_t value = (uint32_t)-until_count;
2940 __atomic_fetch_add (event, (uint32_t) value, __ATOMIC_RELAXED);
2942 if(stat)
2943 *stat = 0;
2946 void
2947 _gfortran_caf_event_query (caf_token_t token, size_t index,
2948 int image_index __attribute__ ((unused)),
2949 int *count, int *stat)
2951 uint32_t *event = (uint32_t *) ((char *) MEMTOK (token) + index
2952 * sizeof (uint32_t));
2953 __atomic_load (event, (uint32_t *) count, __ATOMIC_RELAXED);
2955 if(stat)
2956 *stat = 0;
2959 void
2960 _gfortran_caf_lock (caf_token_t token, size_t index,
2961 int image_index __attribute__ ((unused)),
2962 int *aquired_lock, int *stat, char *errmsg, size_t errmsg_len)
2964 const char *msg = "Already locked";
2965 bool *lock = &((bool *) MEMTOK (token))[index];
2967 if (!*lock)
2969 *lock = true;
2970 if (aquired_lock)
2971 *aquired_lock = (int) true;
2972 if (stat)
2973 *stat = 0;
2974 return;
2977 if (aquired_lock)
2979 *aquired_lock = (int) false;
2980 if (stat)
2981 *stat = 0;
2982 return;
2986 if (stat)
2988 *stat = 1;
2989 if (errmsg_len > 0)
2991 size_t len = (sizeof (msg) > errmsg_len) ? errmsg_len
2992 : sizeof (msg);
2993 memcpy (errmsg, msg, len);
2994 if (errmsg_len > len)
2995 memset (&errmsg[len], ' ', errmsg_len-len);
2997 return;
2999 _gfortran_caf_error_stop_str (msg, strlen (msg), false);
3003 void
3004 _gfortran_caf_unlock (caf_token_t token, size_t index,
3005 int image_index __attribute__ ((unused)),
3006 int *stat, char *errmsg, size_t errmsg_len)
3008 const char *msg = "Variable is not locked";
3009 bool *lock = &((bool *) MEMTOK (token))[index];
3011 if (*lock)
3013 *lock = false;
3014 if (stat)
3015 *stat = 0;
3016 return;
3019 if (stat)
3021 *stat = 1;
3022 if (errmsg_len > 0)
3024 size_t len = (sizeof (msg) > errmsg_len) ? errmsg_len
3025 : sizeof (msg);
3026 memcpy (errmsg, msg, len);
3027 if (errmsg_len > len)
3028 memset (&errmsg[len], ' ', errmsg_len-len);
3030 return;
3032 _gfortran_caf_error_stop_str (msg, strlen (msg), false);
3036 _gfortran_caf_is_present (caf_token_t token,
3037 int image_index __attribute__ ((unused)),
3038 caf_reference_t *refs)
3040 const char arraddressingnotallowed[] = "libcaf_single::caf_is_present(): "
3041 "only scalar indexes allowed.\n";
3042 const char unknownreftype[] = "libcaf_single::caf_get_by_ref(): "
3043 "unknown reference type.\n";
3044 const char unknownarrreftype[] = "libcaf_single::caf_get_by_ref(): "
3045 "unknown array reference type.\n";
3046 size_t i;
3047 caf_single_token_t single_token = TOKEN (token);
3048 void *memptr = single_token->memptr;
3049 gfc_descriptor_t *src = single_token->desc;
3050 caf_reference_t *riter = refs;
3052 while (riter)
3054 switch (riter->type)
3056 case CAF_REF_COMPONENT:
3057 if (riter->u.c.caf_token_offset)
3059 single_token = *(caf_single_token_t*)
3060 (memptr + riter->u.c.caf_token_offset);
3061 memptr = single_token->memptr;
3062 src = single_token->desc;
3064 else
3066 memptr += riter->u.c.offset;
3067 src = (gfc_descriptor_t *)memptr;
3069 break;
3070 case CAF_REF_ARRAY:
3071 for (i = 0; riter->u.a.mode[i] != CAF_ARR_REF_NONE; ++i)
3073 switch (riter->u.a.mode[i])
3075 case CAF_ARR_REF_SINGLE:
3076 memptr += (riter->u.a.dim[i].s.start
3077 - GFC_DIMENSION_LBOUND (src->dim[i]))
3078 * GFC_DIMENSION_STRIDE (src->dim[i])
3079 * riter->item_size;
3080 break;
3081 case CAF_ARR_REF_FULL:
3082 /* A full array ref is allowed on the last reference only. */
3083 if (riter->next == NULL)
3084 break;
3085 /* else fall through reporting an error. */
3086 /* FALLTHROUGH */
3087 case CAF_ARR_REF_VECTOR:
3088 case CAF_ARR_REF_RANGE:
3089 case CAF_ARR_REF_OPEN_END:
3090 case CAF_ARR_REF_OPEN_START:
3091 caf_internal_error (arraddressingnotallowed, 0, NULL, 0);
3092 return 0;
3093 default:
3094 caf_internal_error (unknownarrreftype, 0, NULL, 0);
3095 return 0;
3098 break;
3099 case CAF_REF_STATIC_ARRAY:
3100 for (i = 0; riter->u.a.mode[i] != CAF_ARR_REF_NONE; ++i)
3102 switch (riter->u.a.mode[i])
3104 case CAF_ARR_REF_SINGLE:
3105 memptr += riter->u.a.dim[i].s.start
3106 * riter->u.a.dim[i].s.stride
3107 * riter->item_size;
3108 break;
3109 case CAF_ARR_REF_FULL:
3110 /* A full array ref is allowed on the last reference only. */
3111 if (riter->next == NULL)
3112 break;
3113 /* else fall through reporting an error. */
3114 /* FALLTHROUGH */
3115 case CAF_ARR_REF_VECTOR:
3116 case CAF_ARR_REF_RANGE:
3117 case CAF_ARR_REF_OPEN_END:
3118 case CAF_ARR_REF_OPEN_START:
3119 caf_internal_error (arraddressingnotallowed, 0, NULL, 0);
3120 return 0;
3121 default:
3122 caf_internal_error (unknownarrreftype, 0, NULL, 0);
3123 return 0;
3126 break;
3127 default:
3128 caf_internal_error (unknownreftype, 0, NULL, 0);
3129 return 0;
3131 riter = riter->next;
3133 return memptr != NULL;