Character length cleanup for Coarray Fortran library
[official-gcc.git] / libgfortran / caf / single.c
blob053ec87d562a6893dfaa439c023106a2f6ecfe39
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)
272 fprintf (stderr, "STOP %d\n", stop_code);
273 exit (0);
277 void
278 _gfortran_caf_stop_str(const char *string, size_t len)
280 fputs ("STOP ", stderr);
281 while (len--)
282 fputc (*(string++), stderr);
283 fputs ("\n", stderr);
285 exit (0);
289 void
290 _gfortran_caf_error_stop_str (const char *string, size_t len)
292 fputs ("ERROR STOP ", stderr);
293 while (len--)
294 fputc (*(string++), stderr);
295 fputs ("\n", stderr);
297 exit (1);
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);
308 exit (0);
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)))
318 if (image == 1)
319 return 0;
320 else
321 return CAF_STAT_STOPPED_IMAGE;
325 /* Single image library. There can not be any failed images with only one
326 image. */
328 void
329 _gfortran_caf_failed_images (gfc_descriptor_t *array,
330 caf_team_t * team __attribute__ ((unused)),
331 int * kind)
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;
343 array->offset = 0;
347 /* With only one image available no other images can be stopped. Therefore
348 return an empty array. */
350 void
351 _gfortran_caf_stopped_images (gfc_descriptor_t *array,
352 caf_team_t * team __attribute__ ((unused)),
353 int * kind)
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;
365 array->offset = 0;
369 void
370 _gfortran_caf_error_stop (int error)
372 fprintf (stderr, "ERROR STOP %d\n", error);
373 exit (error);
377 void
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)))
383 if (stat)
384 *stat = 0;
387 void
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)))
393 if (stat)
394 *stat = 0;
397 void
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)))
404 if (stat)
405 *stat = 0;
408 void
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)))
415 if (stat)
416 *stat = 0;
420 void
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)))
430 if (stat)
431 *stat = 0;
435 static void
436 assign_char4_from_char1 (size_t dst_size, size_t src_size, uint32_t *dst,
437 unsigned char *src)
439 size_t i, n;
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) ' ';
448 static void
449 assign_char1_from_char4 (size_t dst_size, size_t src_size, unsigned char *dst,
450 uint32_t *src)
452 size_t i, n;
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];
456 if (dst_size > n)
457 memset (&dst[n], ' ', dst_size - n);
461 static void
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;
467 #else
468 typedef int64_t int128t;
469 #endif
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;
481 #else
482 typedef double real128t;
483 typedef _Complex double complex128t;
484 #endif
486 int128t int_val = 0;
487 real128t real_val = 0;
488 complex128t cmpx_val = 0;
490 switch (src_type)
492 case BT_INTEGER:
493 if (src_kind == 1)
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;
504 #endif
505 else
506 goto error;
507 break;
508 case BT_REAL:
509 if (src_kind == 4)
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;
516 #endif
517 #ifdef HAVE_GFC_REAL_16
518 else if (src_kind == 16)
519 real_val = *(real128t*) src;
520 #endif
521 else
522 goto error;
523 break;
524 case BT_COMPLEX:
525 if (src_kind == 4)
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;
532 #endif
533 #ifdef HAVE_GFC_REAL_16
534 else if (src_kind == 16)
535 cmpx_val = *(complex128t*) src;
536 #endif
537 else
538 goto error;
539 break;
540 default:
541 goto error;
544 switch (dst_type)
546 case BT_INTEGER:
547 if (src_type == BT_INTEGER)
549 if (dst_kind == 1)
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;
560 #endif
561 else
562 goto error;
564 else if (src_type == BT_REAL)
566 if (dst_kind == 1)
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;
577 #endif
578 else
579 goto error;
581 else if (src_type == BT_COMPLEX)
583 if (dst_kind == 1)
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;
594 #endif
595 else
596 goto error;
598 else
599 goto error;
600 return;
601 case BT_REAL:
602 if (src_type == BT_INTEGER)
604 if (dst_kind == 4)
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;
611 #endif
612 #ifdef HAVE_GFC_REAL_16
613 else if (dst_kind == 16)
614 *(real128t*) dst = (real128t) int_val;
615 #endif
616 else
617 goto error;
619 else if (src_type == BT_REAL)
621 if (dst_kind == 4)
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;
628 #endif
629 #ifdef HAVE_GFC_REAL_16
630 else if (dst_kind == 16)
631 *(real128t*) dst = (real128t) real_val;
632 #endif
633 else
634 goto error;
636 else if (src_type == BT_COMPLEX)
638 if (dst_kind == 4)
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;
645 #endif
646 #ifdef HAVE_GFC_REAL_16
647 else if (dst_kind == 16)
648 *(real128t*) dst = (real128t) cmpx_val;
649 #endif
650 else
651 goto error;
653 return;
654 case BT_COMPLEX:
655 if (src_type == BT_INTEGER)
657 if (dst_kind == 4)
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;
664 #endif
665 #ifdef HAVE_GFC_REAL_16
666 else if (dst_kind == 16)
667 *(complex128t*) dst = (complex128t) int_val;
668 #endif
669 else
670 goto error;
672 else if (src_type == BT_REAL)
674 if (dst_kind == 4)
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;
681 #endif
682 #ifdef HAVE_GFC_REAL_16
683 else if (dst_kind == 16)
684 *(complex128t*) dst = (complex128t) real_val;
685 #endif
686 else
687 goto error;
689 else if (src_type == BT_COMPLEX)
691 if (dst_kind == 4)
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;
698 #endif
699 #ifdef HAVE_GFC_REAL_16
700 else if (dst_kind == 16)
701 *(complex128t*) dst = (complex128t) cmpx_val;
702 #endif
703 else
704 goto error;
706 else
707 goto error;
708 return;
709 default:
710 goto error;
713 error:
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);
716 if (stat)
717 *stat = 1;
718 else
719 abort ();
723 void
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. */
732 size_t i, k, size;
733 int j;
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);
738 if (stat)
739 *stat = 0;
741 if (rank == 0)
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)
751 if (dst_kind == 1)
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),
761 sr);
762 else if (GFC_DESCRIPTOR_TYPE (dest) == BT_CHARACTER)
763 assign_char4_from_char1 (dst_size, src_size, GFC_DESCRIPTOR_DATA (dest),
764 sr);
765 else
766 convert_type (GFC_DESCRIPTOR_DATA (dest), GFC_DESCRIPTOR_TYPE (dest),
767 dst_kind, sr, GFC_DESCRIPTOR_TYPE (src), src_kind, stat);
768 return;
771 size = 1;
772 for (j = 0; j < rank; j++)
774 ptrdiff_t dimextent = dest->dim[j]._ubound - dest->dim[j].lower_bound + 1;
775 if (dimextent < 0)
776 dimextent = 0;
777 size *= dimextent;
780 if (size == 0)
781 return;
783 if (may_require_tmp)
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;
810 array_offset_sr = 0;
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)
837 if (dst_kind == 1)
838 memset ((void*)(char*) dst + src_size, ' ',
839 dst_size-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);
849 else
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;
855 free (tmp);
856 return;
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;
877 stride = 1;
878 extent = 1;
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)
898 if (dst_kind == 1)
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);
909 else
910 convert_type (dst, GFC_DESCRIPTOR_TYPE (dest), dst_kind,
911 sr, GFC_DESCRIPTOR_TYPE (src), src_kind, stat);
916 void
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. */
925 size_t i, k, size;
926 int j;
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);
931 if (stat)
932 *stat = 0;
934 if (rank == 0)
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)
944 if (dst_kind == 1)
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));
957 else
958 convert_type (dst, GFC_DESCRIPTOR_TYPE (dest), dst_kind,
959 GFC_DESCRIPTOR_DATA (src), GFC_DESCRIPTOR_TYPE (src),
960 src_kind, stat);
961 return;
964 size = 1;
965 for (j = 0; j < rank; j++)
967 ptrdiff_t dimextent = dest->dim[j]._ubound - dest->dim[j].lower_bound + 1;
968 if (dimextent < 0)
969 dimextent = 0;
970 size *= dimextent;
973 if (size == 0)
974 return;
976 if (may_require_tmp)
978 ptrdiff_t array_offset_sr, array_offset_dst;
979 void *tmp;
981 if (GFC_DESCRIPTOR_RANK (src) == 0)
983 tmp = malloc (src_size);
984 memcpy (tmp, GFC_DESCRIPTOR_DATA (src), src_size);
986 else
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)
1034 memmove (dst, sr,
1035 dst_size > src_size ? src_size : dst_size);
1036 if (GFC_DESCRIPTOR_TYPE (dest) == BT_CHARACTER
1037 && dst_size > src_size)
1039 if (dst_kind == 1)
1040 memset ((void*)(char*) dst + src_size, ' ',
1041 dst_size-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);
1051 else
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;
1057 free (tmp);
1058 return;
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));
1078 void *sr;
1079 if (GFC_DESCRIPTOR_RANK (src) != 0)
1081 ptrdiff_t array_offset_sr = 0;
1082 stride = 1;
1083 extent = 1;
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));
1097 else
1098 sr = src->base_addr;
1100 if (GFC_DESCRIPTOR_TYPE (dest) == GFC_DESCRIPTOR_TYPE (src)
1101 && dst_kind == src_kind)
1103 memmove (dst, sr,
1104 dst_size > src_size ? src_size : dst_size);
1105 if (GFC_DESCRIPTOR_TYPE (dest) == BT_CHARACTER && dst_size > src_size)
1107 if (dst_kind == 1)
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);
1118 else
1119 convert_type (dst, GFC_DESCRIPTOR_TYPE (dest), dst_kind,
1120 sr, GFC_DESCRIPTOR_TYPE (src), src_kind, stat);
1125 void
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,
1129 size_t src_offset,
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)
1140 + src_offset);
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";
1151 static void
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)
1156 size_t k;
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)
1163 if (dst_kind == 1)
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);
1174 else
1175 for (k = 0; k < num; ++k)
1177 convert_type (ds, dst_type, dst_kind, sr, src_type, src_kind, stat);
1178 ds += dst_size;
1179 sr += src_size;
1184 #define COMPUTE_NUM_ITEMS(num, stride, lb, ub) \
1185 do { \
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; \
1190 } while (0)
1193 static void
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
1205 occur. */
1206 return;
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);
1214 switch (ref->type)
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);
1224 else
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);
1228 ++(*i);
1229 return;
1230 case CAF_REF_STATIC_ARRAY:
1231 /* Intentionally fall through. */
1232 case CAF_REF_ARRAY:
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,
1240 stat);
1241 *i += num;
1242 return;
1244 break;
1245 default:
1246 caf_runtime_error (unreachable);
1250 switch (ref->type)
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;
1259 else
1260 src = NULL;
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);
1268 else
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,
1273 1, stat, src_type);
1275 else
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,
1279 stat, src_type);
1280 return;
1281 case CAF_REF_ARRAY:
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);
1287 return;
1289 /* Only when on the left most index switch the data pointer to
1290 the array's data pointer. */
1291 if (src_dim == 0)
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;
1300 ++idx)
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]); \
1307 break
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);
1316 #endif
1317 #ifdef HAVE_GFC_INTEGER_16
1318 KINDCASE (16, GFC_INTEGER_16);
1319 #endif
1320 default:
1321 caf_runtime_error (unreachable);
1322 return;
1324 #undef KINDCASE
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,
1329 1, stat, src_type);
1330 dst_index[dst_dim]
1331 += GFC_DIMENSION_STRIDE (dst->dim[dst_dim]);
1333 return;
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,
1349 1, stat, src_type);
1350 dst_index[dst_dim]
1351 += GFC_DIMENSION_STRIDE (dst->dim[dst_dim]);
1353 return;
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,
1376 1, stat, src_type);
1377 dst_index[dst_dim]
1378 += GFC_DIMENSION_STRIDE (dst->dim[dst_dim]);
1379 array_offset_src += stride_src;
1381 return;
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,
1390 stat, src_type);
1391 return;
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,
1408 1, stat, src_type);
1409 dst_index[dst_dim]
1410 += GFC_DIMENSION_STRIDE (dst->dim[dst_dim]);
1411 array_offset_src += stride_src;
1413 return;
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,
1428 1, stat, src_type);
1429 dst_index[dst_dim]
1430 += GFC_DIMENSION_STRIDE (dst->dim[dst_dim]);
1431 array_offset_src += stride_src;
1433 return;
1434 default:
1435 caf_runtime_error (unreachable);
1437 return;
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);
1444 return;
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;
1452 ++idx)
1454 #define KINDCASE(kind, type) case kind: \
1455 array_offset_src = ((type *)ref->u.a.dim[src_dim].v.vector)[idx]; \
1456 break
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);
1465 #endif
1466 #ifdef HAVE_GFC_INTEGER_16
1467 KINDCASE (16, GFC_INTEGER_16);
1468 #endif
1469 default:
1470 caf_runtime_error (unreachable);
1471 return;
1473 #undef KINDCASE
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,
1478 1, stat, src_type);
1479 dst_index[dst_dim]
1480 += GFC_DIMENSION_STRIDE (dst->dim[dst_dim]);
1482 return;
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,
1492 1, stat, src_type);
1493 dst_index[dst_dim]
1494 += GFC_DIMENSION_STRIDE (dst->dim[dst_dim]);
1496 return;
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,
1509 1, stat, src_type);
1510 dst_index[dst_dim]
1511 += GFC_DIMENSION_STRIDE (dst->dim[dst_dim]);
1512 array_offset_src += ref->u.a.dim[src_dim].s.stride;
1514 return;
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,
1520 stat, src_type);
1521 return;
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:
1525 default:
1526 caf_runtime_error (unreachable);
1528 return;
1529 default:
1530 caf_runtime_error (unreachable);
1535 void
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,
1542 int src_type)
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";
1560 size_t size, i;
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;
1569 long delta;
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
1573 all. */
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);
1583 if (stat)
1584 *stat = 0;
1586 /* Compute the size of the result. In the beginning size just counts the
1587 number of elements. */
1588 size = 1;
1589 while (riter)
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;
1601 else
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
1606 a descriptor. */
1607 if (riter->next && riter->next->type == CAF_REF_ARRAY)
1608 src = (gfc_descriptor_t *)memptr;
1609 else
1610 src = NULL;
1612 break;
1613 case CAF_REF_ARRAY:
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; \
1626 break
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);
1635 #endif
1636 #ifdef HAVE_GFC_INTEGER_16
1637 KINDCASE (16, GFC_INTEGER_16);
1638 #endif
1639 default:
1640 caf_internal_error (vecrefunknownkind, stat, NULL, 0);
1641 return;
1643 #undef KINDCASE
1644 break;
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
1651 in a dimension. */
1652 break;
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])
1661 * riter->item_size;
1662 break;
1663 case CAF_ARR_REF_SINGLE:
1664 delta = 1;
1665 memptr += (riter->u.a.dim[i].s.start
1666 - GFC_DIMENSION_LBOUND (src->dim[i]))
1667 * GFC_DIMENSION_STRIDE (src->dim[i])
1668 * riter->item_size;
1669 break;
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])
1678 * riter->item_size;
1679 break;
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
1686 in a dimension. */
1687 break;
1688 default:
1689 caf_internal_error (unknownarrreftype, stat, NULL, 0);
1690 return;
1692 if (delta <= 0)
1693 return;
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);
1700 return;
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. */
1710 if (dst_rank > 0)
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);
1717 return;
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. */
1724 if (!in_array_ref)
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
1733 compatible. */
1734 if (i > 0
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;
1742 ++dst_cur_dim)
1743 GFC_DIMENSION_SET (dst->dim[dst_cur_dim],
1744 1, 1, 1);
1746 else
1747 dst_cur_dim = i;
1749 /* Else press thumbs, that there are enough
1750 dimensional refs to come. Checked below. */
1752 else
1754 caf_internal_error (doublearrayref, stat, NULL,
1756 return;
1759 /* When the realloc is required, then no extent may have
1760 been set. */
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
1766 || extent_mismatch)
1768 /* Check whether dst is reallocatable. */
1769 if (unlikely (!dst_reallocatable))
1771 caf_internal_error (nonallocextentmismatch, stat,
1772 NULL, 0, delta,
1773 GFC_DESCRIPTOR_EXTENT (dst,
1774 dst_cur_dim));
1775 return;
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,
1783 return;
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,
1791 size);
1794 /* Only increase the dim counter, when in an array ref. */
1795 if (in_array_ref && dst_cur_dim < dst_rank)
1796 ++dst_cur_dim;
1798 size *= (index_type)delta;
1800 if (in_array_ref)
1802 array_extent_fixed = true;
1803 in_array_ref = false;
1804 /* Check, if we got less dimensional refs than the rank of dst
1805 expects. */
1806 assert (dst_cur_dim == GFC_DESCRIPTOR_RANK (dst));
1808 break;
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; \
1819 break
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);
1828 #endif
1829 #ifdef HAVE_GFC_INTEGER_16
1830 KINDCASE (16, GFC_INTEGER_16);
1831 #endif
1832 default:
1833 caf_internal_error (vecrefunknownkind, stat, NULL, 0);
1834 return;
1836 #undef KINDCASE
1837 break;
1838 case CAF_ARR_REF_FULL:
1839 delta = riter->u.a.dim[i].s.end / riter->u.a.dim[i].s.stride
1840 + 1;
1841 /* The memptr stays unchanged when ref'ing the first element
1842 in a dimension. */
1843 break;
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
1851 * riter->item_size;
1852 break;
1853 case CAF_ARR_REF_SINGLE:
1854 delta = 1;
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_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:
1863 default:
1864 caf_internal_error (unknownarrreftype, stat, NULL, 0);
1865 return;
1867 if (delta <= 0)
1868 return;
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);
1875 return;
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. */
1885 if (dst_rank > 0)
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);
1892 return;
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. */
1899 if (!in_array_ref)
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. */
1908 dst_cur_dim = i;
1910 else
1912 caf_internal_error (doublearrayref, stat, NULL,
1914 return;
1917 /* When the realloc is required, then no extent may have
1918 been set. */
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
1924 || extent_mismatch)
1926 /* Check whether dst is reallocatable. */
1927 if (unlikely (!dst_reallocatable))
1929 caf_internal_error (nonallocextentmismatch, stat,
1930 NULL, 0, delta,
1931 GFC_DESCRIPTOR_EXTENT (dst,
1932 dst_cur_dim));
1933 return;
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,
1941 return;
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,
1949 size);
1951 /* Only increase the dim counter, when in an array ref. */
1952 if (in_array_ref && dst_cur_dim < dst_rank)
1953 ++dst_cur_dim;
1955 size *= (index_type)delta;
1957 if (in_array_ref)
1959 array_extent_fixed = true;
1960 in_array_ref = false;
1961 /* Check, if we got less dimensional refs than the rank of dst
1962 expects. */
1963 assert (dst_cur_dim == GFC_DESCRIPTOR_RANK (dst));
1965 break;
1966 default:
1967 caf_internal_error (unknownreftype, stat, NULL, 0);
1968 return;
1970 src_size = riter->item_size;
1971 riter = riter->next;
1973 if (size == 0 || src_size == 0)
1974 return;
1975 /* Postcondition:
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.
1980 if (realloc_needed)
1982 if (!array_extent_fixed)
1984 assert (size == 1);
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);
2001 return;
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));
2010 i = 0;
2011 get_for_ref (refs, &i, dst_index, single_token, dst, src,
2012 GFC_DESCRIPTOR_DATA (dst), memptr, dst_kind, src_kind, 0, 0,
2013 1, stat, src_type);
2017 static void
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
2031 occur. */
2032 return;
2034 if (ref->next == NULL)
2036 size_t src_size = GFC_DESCRIPTOR_SIZE (src);
2037 ptrdiff_t array_offset_src = 0;;
2039 switch (ref->type)
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
2052 scalar. */
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)
2062 return;
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);
2070 else
2072 single_token = *(caf_single_token_t *)
2073 (ds + ref->u.c.caf_token_offset);
2074 dst = single_token->desc;
2075 if (dst)
2077 ds = GFC_DESCRIPTOR_DATA (dst);
2078 dst_type = GFC_DESCRIPTOR_TYPE (dst);
2080 else
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);
2086 else
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);
2090 ++(*i);
2091 return;
2092 case CAF_REF_STATIC_ARRAY:
2093 /* Intentionally fall through. */
2094 case CAF_REF_ARRAY:
2095 if (ref->u.a.mode[dst_dim] == CAF_ARR_REF_NONE)
2097 if (src_rank > 0)
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);
2105 else
2106 copy_data (ds, sr, dst_type, GFC_DESCRIPTOR_TYPE (src),
2107 dst_kind, src_kind, ref->item_size, src_size, num,
2108 stat);
2109 *i += num;
2110 return;
2112 break;
2113 default:
2114 caf_runtime_error (unreachable);
2118 switch (ref->type)
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
2129 to dst. */
2130 GFC_DESCRIPTOR_DTYPE (dst) = GFC_DESCRIPTOR_DTYPE (src);
2131 dst->offset = 0;
2132 stride_dst = 1;
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
2142 its own memory. */
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)
2153 return;
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
2158 dereffed. */
2159 if (ref->next && ref->next->type == CAF_REF_COMPONENT)
2160 ds = *(void **)(ds + ref->u.c.offset);
2161 else
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);
2168 else
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);
2173 return;
2174 case CAF_REF_ARRAY:
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);
2180 return;
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;
2192 ++idx)
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]); \
2199 break
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);
2208 #endif
2209 #ifdef HAVE_GFC_INTEGER_16
2210 KINDCASE (16, GFC_INTEGER_16);
2211 #endif
2212 default:
2213 caf_internal_error (vecrefunknownkind, stat, NULL, 0);
2214 return;
2216 #undef KINDCASE
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);
2222 if (src_rank > 0)
2223 src_index[src_dim]
2224 += GFC_DIMENSION_STRIDE (src->dim[src_dim]);
2226 return;
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);
2243 if (src_rank > 0)
2244 src_index[src_dim]
2245 += GFC_DIMENSION_STRIDE (src->dim[src_dim]);
2247 return;
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);
2264 if (src_rank > 0)
2265 src_index[src_dim]
2266 += GFC_DIMENSION_STRIDE (src->dim[src_dim]);
2267 array_offset_dst += stride_dst;
2269 return;
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);
2278 return;
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);
2295 if (src_rank > 0)
2296 src_index[src_dim]
2297 += GFC_DIMENSION_STRIDE (src->dim[src_dim]);
2298 array_offset_dst += stride_dst;
2300 return;
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);
2316 if (src_rank > 0)
2317 src_index[src_dim]
2318 += GFC_DIMENSION_STRIDE (src->dim[src_dim]);
2319 array_offset_dst += stride_dst;
2321 return;
2322 default:
2323 caf_runtime_error (unreachable);
2325 return;
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);
2332 return;
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;
2340 ++idx)
2342 #define KINDCASE(kind, type) case kind: \
2343 array_offset_dst = ((type *)ref->u.a.dim[dst_dim].v.vector)[idx]; \
2344 break
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);
2353 #endif
2354 #ifdef HAVE_GFC_INTEGER_16
2355 KINDCASE (16, GFC_INTEGER_16);
2356 #endif
2357 default:
2358 caf_runtime_error (unreachable);
2359 return;
2361 #undef KINDCASE
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);
2367 src_index[src_dim]
2368 += GFC_DIMENSION_STRIDE (src->dim[src_dim]);
2370 return;
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);
2381 if (src_rank > 0)
2382 src_index[src_dim]
2383 += GFC_DIMENSION_STRIDE (src->dim[src_dim]);
2385 return;
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);
2399 if (src_rank > 0)
2400 src_index[src_dim]
2401 += GFC_DIMENSION_STRIDE (src->dim[src_dim]);
2402 array_offset_dst += ref->u.a.dim[dst_dim].s.stride;
2404 return;
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);
2411 return;
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:
2415 default:
2416 caf_runtime_error (unreachable);
2418 return;
2419 default:
2420 caf_runtime_error (unreachable);
2425 void
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";
2449 size_t size, i;
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;
2458 long delta;
2459 bool extent_mismatch;
2460 /* Note that the component is not allocated yet. */
2461 index_type new_component_idx = -1;
2463 if (stat)
2464 *stat = 0;
2466 /* Compute the size of the result. In the beginning size just counts the
2467 number of elements. */
2468 size = 1;
2469 while (riter)
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);
2479 return;
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);
2493 return;
2495 single_token = NULL;
2496 memptr = NULL;
2497 dst = NULL;
2498 break;
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;
2505 else
2507 /* Regular component. */
2508 memptr += riter->u.c.offset;
2509 dst = (gfc_descriptor_t *)memptr;
2511 break;
2512 case CAF_REF_ARRAY:
2513 if (dst != NULL)
2514 memptr = GFC_DESCRIPTOR_DATA (dst);
2515 else
2516 dst = src;
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; \
2531 break
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);
2540 #endif
2541 #ifdef HAVE_GFC_INTEGER_16
2542 KINDCASE (16, GFC_INTEGER_16);
2543 #endif
2544 default:
2545 caf_internal_error (vecrefunknownkind, stat, NULL, 0);
2546 return;
2548 #undef KINDCASE
2549 break;
2550 case CAF_ARR_REF_FULL:
2551 if (dst)
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]));
2556 else
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]));
2561 break;
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])
2570 * riter->item_size;
2571 break;
2572 case CAF_ARR_REF_SINGLE:
2573 delta = 1;
2574 memptr += (riter->u.a.dim[i].s.start
2575 - dst->dim[i].lower_bound)
2576 * GFC_DIMENSION_STRIDE (dst->dim[i])
2577 * riter->item_size;
2578 break;
2579 case CAF_ARR_REF_OPEN_END:
2580 if (dst)
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]));
2585 else
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])
2593 * riter->item_size;
2594 break;
2595 case CAF_ARR_REF_OPEN_START:
2596 if (dst)
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);
2601 else
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
2607 in a dimension. */
2608 break;
2609 default:
2610 caf_internal_error (unknownarrreftype, stat, NULL, 0);
2611 return;
2614 if (delta <= 0)
2615 return;
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);
2625 return;
2627 /* Do further checks, when the source is not scalar. */
2628 else
2630 /* When the realloc is required, then no extent may have
2631 been set. */
2632 extent_mismatch = memptr == NULL
2633 || (dst
2634 && GFC_DESCRIPTOR_EXTENT (dst, src_cur_dim)
2635 != delta);
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,
2644 NULL, 0, delta,
2645 GFC_DESCRIPTOR_EXTENT (dst,
2646 src_cur_dim));
2647 return;
2649 /* Report error on allocatable but missing inner
2650 ref. */
2651 else if (riter->next != NULL)
2653 caf_internal_error (realloconinnerref, stat, NULL,
2655 return;
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,
2662 size);
2664 /* Increase the dim-counter of the src only when the extent
2665 matches. */
2666 if (src_cur_dim < src_rank
2667 && GFC_DESCRIPTOR_EXTENT (src, src_cur_dim) == delta)
2668 ++src_cur_dim;
2670 size *= (index_type)delta;
2672 break;
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; \
2683 break
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);
2692 #endif
2693 #ifdef HAVE_GFC_INTEGER_16
2694 KINDCASE (16, GFC_INTEGER_16);
2695 #endif
2696 default:
2697 caf_internal_error (vecrefunknownkind, stat, NULL, 0);
2698 return;
2700 #undef KINDCASE
2701 break;
2702 case CAF_ARR_REF_FULL:
2703 delta = riter->u.a.dim[i].s.end / riter->u.a.dim[i].s.stride
2704 + 1;
2705 /* The memptr stays unchanged when ref'ing the first element
2706 in a dimension. */
2707 break;
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
2715 * riter->item_size;
2716 break;
2717 case CAF_ARR_REF_SINGLE:
2718 delta = 1;
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_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:
2727 default:
2728 caf_internal_error (unknownarrreftype, stat, NULL, 0);
2729 return;
2731 if (delta <= 0)
2732 return;
2733 /* Check the various properties of the source array.
2734 Only when the source array is not scalar examine its
2735 properties. */
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);
2743 return;
2745 else
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)
2750 != delta;
2751 /* When the extent does not match the needed one we can
2752 only stop here. */
2753 if (extent_mismatch)
2755 caf_internal_error (nonallocextentmismatch, stat,
2756 NULL, 0, delta,
2757 GFC_DESCRIPTOR_EXTENT (src,
2758 src_cur_dim));
2759 return;
2762 ++src_cur_dim;
2764 size *= (index_type)delta;
2766 break;
2767 default:
2768 caf_internal_error (unknownreftype, stat, NULL, 0);
2769 return;
2771 src_size = riter->item_size;
2772 riter = riter->next;
2774 if (size == 0 || src_size == 0)
2775 return;
2776 /* Postcondition:
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));
2786 i = 0;
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);
2790 assert (i == size);
2794 void
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)
2812 return;
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));
2822 void
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)
2828 assert(kind == 4);
2830 uint32_t *atom = (uint32_t *) ((char *) MEMTOK (token) + offset);
2832 __atomic_store (atom, (uint32_t *) value, __ATOMIC_RELAXED);
2834 if (stat)
2835 *stat = 0;
2838 void
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)
2844 assert(kind == 4);
2846 uint32_t *atom = (uint32_t *) ((char *) MEMTOK (token) + offset);
2848 __atomic_load (atom, (uint32_t *) value, __ATOMIC_RELAXED);
2850 if (stat)
2851 *stat = 0;
2855 void
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)
2861 assert(kind == 4);
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);
2869 if (stat)
2870 *stat = 0;
2874 void
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)
2880 assert(kind == 4);
2882 uint32_t res;
2883 uint32_t *atom = (uint32_t *) ((char *) MEMTOK (token) + offset);
2885 switch (op)
2887 case GFC_CAF_ATOMIC_ADD:
2888 res = __atomic_fetch_add (atom, *(uint32_t *) value, __ATOMIC_RELAXED);
2889 break;
2890 case GFC_CAF_ATOMIC_AND:
2891 res = __atomic_fetch_and (atom, *(uint32_t *) value, __ATOMIC_RELAXED);
2892 break;
2893 case GFC_CAF_ATOMIC_OR:
2894 res = __atomic_fetch_or (atom, *(uint32_t *) value, __ATOMIC_RELAXED);
2895 break;
2896 case GFC_CAF_ATOMIC_XOR:
2897 res = __atomic_fetch_xor (atom, *(uint32_t *) value, __ATOMIC_RELAXED);
2898 break;
2899 default:
2900 __builtin_unreachable();
2903 if (old)
2904 *(uint32_t *) old = res;
2906 if (stat)
2907 *stat = 0;
2910 void
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)))
2916 uint32_t value = 1;
2917 uint32_t *event = (uint32_t *) ((char *) MEMTOK (token) + index
2918 * sizeof (uint32_t));
2919 __atomic_fetch_add (event, (uint32_t) value, __ATOMIC_RELAXED);
2921 if(stat)
2922 *stat = 0;
2925 void
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);
2936 if(stat)
2937 *stat = 0;
2940 void
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);
2949 if(stat)
2950 *stat = 0;
2953 void
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];
2961 if (!*lock)
2963 *lock = true;
2964 if (aquired_lock)
2965 *aquired_lock = (int) true;
2966 if (stat)
2967 *stat = 0;
2968 return;
2971 if (aquired_lock)
2973 *aquired_lock = (int) false;
2974 if (stat)
2975 *stat = 0;
2976 return;
2980 if (stat)
2982 *stat = 1;
2983 if (errmsg_len > 0)
2985 size_t len = (sizeof (msg) > errmsg_len) ? errmsg_len
2986 : sizeof (msg);
2987 memcpy (errmsg, msg, len);
2988 if (errmsg_len > len)
2989 memset (&errmsg[len], ' ', errmsg_len-len);
2991 return;
2993 _gfortran_caf_error_stop_str (msg, strlen (msg));
2997 void
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];
3005 if (*lock)
3007 *lock = false;
3008 if (stat)
3009 *stat = 0;
3010 return;
3013 if (stat)
3015 *stat = 1;
3016 if (errmsg_len > 0)
3018 size_t len = (sizeof (msg) > errmsg_len) ? errmsg_len
3019 : sizeof (msg);
3020 memcpy (errmsg, msg, len);
3021 if (errmsg_len > len)
3022 memset (&errmsg[len], ' ', errmsg_len-len);
3024 return;
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";
3040 size_t i;
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;
3046 while (riter)
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;
3058 else
3060 memptr += riter->u.c.offset;
3061 src = (gfc_descriptor_t *)memptr;
3063 break;
3064 case CAF_REF_ARRAY:
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])
3073 * riter->item_size;
3074 break;
3075 case CAF_ARR_REF_FULL:
3076 /* A full array ref is allowed on the last reference only. */
3077 if (riter->next == NULL)
3078 break;
3079 /* else fall through reporting an error. */
3080 /* FALLTHROUGH */
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);
3086 return 0;
3087 default:
3088 caf_internal_error (unknownarrreftype, 0, NULL, 0);
3089 return 0;
3092 break;
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
3101 * riter->item_size;
3102 break;
3103 case CAF_ARR_REF_FULL:
3104 /* A full array ref is allowed on the last reference only. */
3105 if (riter->next == NULL)
3106 break;
3107 /* else fall through reporting an error. */
3108 /* FALLTHROUGH */
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);
3114 return 0;
3115 default:
3116 caf_internal_error (unknownarrreftype, 0, NULL, 0);
3117 return 0;
3120 break;
3121 default:
3122 caf_internal_error (unknownreftype, 0, NULL, 0);
3123 return 0;
3125 riter = riter->next;
3127 return memptr != NULL;