Home | History | Annotate | Line # | Download | only in caf
      1      1.1  mrg /* Single-image implementation of GNU Fortran Coarray Library
      2  1.1.1.4  mrg    Copyright (C) 2011-2024 Free Software Foundation, Inc.
      3      1.1  mrg    Contributed by Tobias Burnus <burnus (at) net-b.de>
      4      1.1  mrg 
      5      1.1  mrg This file is part of the GNU Fortran Coarray Runtime Library (libcaf).
      6      1.1  mrg 
      7      1.1  mrg Libcaf is free software; you can redistribute it and/or modify
      8      1.1  mrg it under the terms of the GNU General Public License as published by
      9      1.1  mrg the Free Software Foundation; either version 3, or (at your option)
     10      1.1  mrg any later version.
     11      1.1  mrg 
     12      1.1  mrg Libcaf is distributed in the hope that it will be useful,
     13      1.1  mrg but WITHOUT ANY WARRANTY; without even the implied warranty of
     14      1.1  mrg MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     15      1.1  mrg GNU General Public License for more details.
     16      1.1  mrg 
     17      1.1  mrg Under Section 7 of GPL version 3, you are granted additional
     18      1.1  mrg permissions described in the GCC Runtime Library Exception, version
     19      1.1  mrg 3.1, as published by the Free Software Foundation.
     20      1.1  mrg 
     21      1.1  mrg You should have received a copy of the GNU General Public License and
     22      1.1  mrg a copy of the GCC Runtime Library Exception along with this program;
     23      1.1  mrg see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
     24      1.1  mrg <http://www.gnu.org/licenses/>.  */
     25      1.1  mrg 
     26      1.1  mrg #include "libcaf.h"
     27      1.1  mrg #include <stdio.h>  /* For fputs and fprintf.  */
     28      1.1  mrg #include <stdlib.h> /* For exit and malloc.  */
     29      1.1  mrg #include <string.h> /* For memcpy and memset.  */
     30      1.1  mrg #include <stdarg.h> /* For variadic arguments.  */
     31      1.1  mrg #include <stdint.h>
     32      1.1  mrg #include <assert.h>
     33      1.1  mrg 
     34      1.1  mrg /* Define GFC_CAF_CHECK to enable run-time checking.  */
     35      1.1  mrg /* #define GFC_CAF_CHECK  1  */
     36      1.1  mrg 
     37      1.1  mrg struct caf_single_token
     38      1.1  mrg {
     39      1.1  mrg   /* The pointer to the memory registered.  For arrays this is the data member
     40      1.1  mrg      in the descriptor.  For components it's the pure data pointer.  */
     41      1.1  mrg   void *memptr;
     42      1.1  mrg   /* The descriptor when this token is associated to an allocatable array.  */
     43      1.1  mrg   gfc_descriptor_t *desc;
     44      1.1  mrg   /* Set when the caf lib has allocated the memory in memptr and is responsible
     45      1.1  mrg      for freeing it on deregister.  */
     46      1.1  mrg   bool owning_memory;
     47      1.1  mrg };
     48      1.1  mrg typedef struct caf_single_token *caf_single_token_t;
     49      1.1  mrg 
     50      1.1  mrg #define TOKEN(X) ((caf_single_token_t) (X))
     51      1.1  mrg #define MEMTOK(X) ((caf_single_token_t) (X))->memptr
     52      1.1  mrg 
     53      1.1  mrg /* Single-image implementation of the CAF library.
     54      1.1  mrg    Note: For performance reasons -fcoarry=single should be used
     55      1.1  mrg    rather than this library.  */
     56      1.1  mrg 
     57      1.1  mrg /* Global variables.  */
     58      1.1  mrg caf_static_t *caf_static_list = NULL;
     59      1.1  mrg 
     60      1.1  mrg /* Keep in sync with mpi.c.  */
     61      1.1  mrg static void
     62      1.1  mrg caf_runtime_error (const char *message, ...)
     63      1.1  mrg {
     64      1.1  mrg   va_list ap;
     65      1.1  mrg   fprintf (stderr, "Fortran runtime error: ");
     66      1.1  mrg   va_start (ap, message);
     67      1.1  mrg   vfprintf (stderr, message, ap);
     68      1.1  mrg   va_end (ap);
     69      1.1  mrg   fprintf (stderr, "\n");
     70      1.1  mrg 
     71      1.1  mrg   /* FIXME: Shutdown the Fortran RTL to flush the buffer.  PR 43849.  */
     72      1.1  mrg   exit (EXIT_FAILURE);
     73      1.1  mrg }
     74      1.1  mrg 
     75      1.1  mrg /* Error handling is similar everytime.  */
     76      1.1  mrg static void
     77      1.1  mrg caf_internal_error (const char *msg, int *stat, char *errmsg,
     78      1.1  mrg 		    size_t errmsg_len, ...)
     79      1.1  mrg {
     80      1.1  mrg   va_list args;
     81      1.1  mrg   va_start (args, errmsg_len);
     82      1.1  mrg   if (stat)
     83      1.1  mrg     {
     84      1.1  mrg       *stat = 1;
     85      1.1  mrg       if (errmsg_len > 0)
     86      1.1  mrg 	{
     87      1.1  mrg 	  int len = snprintf (errmsg, errmsg_len, msg, args);
     88      1.1  mrg 	  if (len >= 0 && errmsg_len > (size_t) len)
     89      1.1  mrg 	    memset (&errmsg[len], ' ', errmsg_len - len);
     90      1.1  mrg 	}
     91      1.1  mrg       va_end (args);
     92      1.1  mrg       return;
     93      1.1  mrg     }
     94      1.1  mrg   else
     95      1.1  mrg     caf_runtime_error (msg, args);
     96      1.1  mrg   va_end (args);
     97      1.1  mrg }
     98      1.1  mrg 
     99      1.1  mrg 
    100      1.1  mrg void
    101      1.1  mrg _gfortran_caf_init (int *argc __attribute__ ((unused)),
    102      1.1  mrg 		    char ***argv __attribute__ ((unused)))
    103      1.1  mrg {
    104      1.1  mrg }
    105      1.1  mrg 
    106      1.1  mrg 
    107      1.1  mrg void
    108      1.1  mrg _gfortran_caf_finalize (void)
    109      1.1  mrg {
    110      1.1  mrg   while (caf_static_list != NULL)
    111      1.1  mrg     {
    112      1.1  mrg       caf_static_t *tmp = caf_static_list->prev;
    113      1.1  mrg       free (caf_static_list->token);
    114      1.1  mrg       free (caf_static_list);
    115      1.1  mrg       caf_static_list = tmp;
    116      1.1  mrg     }
    117      1.1  mrg }
    118      1.1  mrg 
    119      1.1  mrg 
    120      1.1  mrg int
    121      1.1  mrg _gfortran_caf_this_image (int distance __attribute__ ((unused)))
    122      1.1  mrg {
    123      1.1  mrg   return 1;
    124      1.1  mrg }
    125      1.1  mrg 
    126      1.1  mrg 
    127      1.1  mrg int
    128      1.1  mrg _gfortran_caf_num_images (int distance __attribute__ ((unused)),
    129      1.1  mrg 			  int failed __attribute__ ((unused)))
    130      1.1  mrg {
    131      1.1  mrg   return 1;
    132      1.1  mrg }
    133      1.1  mrg 
    134      1.1  mrg 
    135      1.1  mrg void
    136      1.1  mrg _gfortran_caf_register (size_t size, caf_register_t type, caf_token_t *token,
    137      1.1  mrg 			gfc_descriptor_t *data, int *stat, char *errmsg,
    138      1.1  mrg 			size_t errmsg_len)
    139      1.1  mrg {
    140      1.1  mrg   const char alloc_fail_msg[] = "Failed to allocate coarray";
    141      1.1  mrg   void *local;
    142      1.1  mrg   caf_single_token_t single_token;
    143      1.1  mrg 
    144      1.1  mrg   if (type == CAF_REGTYPE_LOCK_STATIC || type == CAF_REGTYPE_LOCK_ALLOC
    145      1.1  mrg       || type == CAF_REGTYPE_CRITICAL)
    146      1.1  mrg     local = calloc (size, sizeof (bool));
    147      1.1  mrg   else if (type == CAF_REGTYPE_EVENT_STATIC || type == CAF_REGTYPE_EVENT_ALLOC)
    148      1.1  mrg     /* In the event_(wait|post) function the counter for events is a uint32,
    149      1.1  mrg        so better allocate enough memory here.  */
    150      1.1  mrg     local = calloc (size, sizeof (uint32_t));
    151      1.1  mrg   else if (type == CAF_REGTYPE_COARRAY_ALLOC_REGISTER_ONLY)
    152      1.1  mrg     local = NULL;
    153      1.1  mrg   else
    154      1.1  mrg     local = malloc (size);
    155      1.1  mrg 
    156      1.1  mrg   if (type != CAF_REGTYPE_COARRAY_ALLOC_ALLOCATE_ONLY)
    157      1.1  mrg     *token = malloc (sizeof (struct caf_single_token));
    158      1.1  mrg 
    159      1.1  mrg   if (unlikely (*token == NULL
    160      1.1  mrg 		|| (local == NULL
    161      1.1  mrg 		    && type != CAF_REGTYPE_COARRAY_ALLOC_REGISTER_ONLY)))
    162      1.1  mrg     {
    163      1.1  mrg       /* Freeing the memory conditionally seems pointless, but
    164      1.1  mrg 	 caf_internal_error () may return, when a stat is given and then the
    165      1.1  mrg 	 memory may be lost.  */
    166  1.1.1.4  mrg       free (local);
    167  1.1.1.4  mrg       free (*token);
    168      1.1  mrg       caf_internal_error (alloc_fail_msg, stat, errmsg, errmsg_len);
    169      1.1  mrg       return;
    170      1.1  mrg     }
    171      1.1  mrg 
    172      1.1  mrg   single_token = TOKEN (*token);
    173      1.1  mrg   single_token->memptr = local;
    174      1.1  mrg   single_token->owning_memory = type != CAF_REGTYPE_COARRAY_ALLOC_REGISTER_ONLY;
    175      1.1  mrg   single_token->desc = GFC_DESCRIPTOR_RANK (data) > 0 ? data : NULL;
    176      1.1  mrg 
    177      1.1  mrg 
    178      1.1  mrg   if (stat)
    179      1.1  mrg     *stat = 0;
    180      1.1  mrg 
    181      1.1  mrg   if (type == CAF_REGTYPE_COARRAY_STATIC || type == CAF_REGTYPE_LOCK_STATIC
    182      1.1  mrg       || type == CAF_REGTYPE_CRITICAL || type == CAF_REGTYPE_EVENT_STATIC
    183      1.1  mrg       || type == CAF_REGTYPE_EVENT_ALLOC)
    184      1.1  mrg     {
    185      1.1  mrg       caf_static_t *tmp = malloc (sizeof (caf_static_t));
    186      1.1  mrg       tmp->prev  = caf_static_list;
    187      1.1  mrg       tmp->token = *token;
    188      1.1  mrg       caf_static_list = tmp;
    189      1.1  mrg     }
    190      1.1  mrg   GFC_DESCRIPTOR_DATA (data) = local;
    191      1.1  mrg }
    192      1.1  mrg 
    193      1.1  mrg 
    194      1.1  mrg void
    195      1.1  mrg _gfortran_caf_deregister (caf_token_t *token, caf_deregister_t type, int *stat,
    196      1.1  mrg 			  char *errmsg __attribute__ ((unused)),
    197      1.1  mrg 			  size_t errmsg_len __attribute__ ((unused)))
    198      1.1  mrg {
    199      1.1  mrg   caf_single_token_t single_token = TOKEN (*token);
    200      1.1  mrg 
    201      1.1  mrg   if (single_token->owning_memory && single_token->memptr)
    202      1.1  mrg     free (single_token->memptr);
    203      1.1  mrg 
    204      1.1  mrg   if (type != CAF_DEREGTYPE_COARRAY_DEALLOCATE_ONLY)
    205      1.1  mrg     {
    206      1.1  mrg       free (TOKEN (*token));
    207      1.1  mrg       *token = NULL;
    208      1.1  mrg     }
    209      1.1  mrg   else
    210      1.1  mrg     {
    211      1.1  mrg       single_token->memptr = NULL;
    212      1.1  mrg       single_token->owning_memory = false;
    213      1.1  mrg     }
    214      1.1  mrg 
    215      1.1  mrg   if (stat)
    216      1.1  mrg     *stat = 0;
    217      1.1  mrg }
    218      1.1  mrg 
    219      1.1  mrg 
    220      1.1  mrg void
    221      1.1  mrg _gfortran_caf_sync_all (int *stat,
    222      1.1  mrg 			char *errmsg __attribute__ ((unused)),
    223      1.1  mrg 			size_t errmsg_len __attribute__ ((unused)))
    224      1.1  mrg {
    225      1.1  mrg   __asm__ __volatile__ ("":::"memory");
    226      1.1  mrg   if (stat)
    227      1.1  mrg     *stat = 0;
    228      1.1  mrg }
    229      1.1  mrg 
    230      1.1  mrg 
    231      1.1  mrg void
    232      1.1  mrg _gfortran_caf_sync_memory (int *stat,
    233      1.1  mrg 			   char *errmsg __attribute__ ((unused)),
    234      1.1  mrg 			   size_t errmsg_len __attribute__ ((unused)))
    235      1.1  mrg {
    236      1.1  mrg   __asm__ __volatile__ ("":::"memory");
    237      1.1  mrg   if (stat)
    238      1.1  mrg     *stat = 0;
    239      1.1  mrg }
    240      1.1  mrg 
    241      1.1  mrg 
    242      1.1  mrg void
    243      1.1  mrg _gfortran_caf_sync_images (int count __attribute__ ((unused)),
    244      1.1  mrg 			   int images[] __attribute__ ((unused)),
    245      1.1  mrg 			   int *stat,
    246      1.1  mrg 			   char *errmsg __attribute__ ((unused)),
    247      1.1  mrg 			   size_t errmsg_len __attribute__ ((unused)))
    248      1.1  mrg {
    249      1.1  mrg #ifdef GFC_CAF_CHECK
    250      1.1  mrg   int i;
    251      1.1  mrg 
    252      1.1  mrg   for (i = 0; i < count; i++)
    253      1.1  mrg     if (images[i] != 1)
    254      1.1  mrg       {
    255      1.1  mrg 	fprintf (stderr, "COARRAY ERROR: Invalid image index %d to SYNC "
    256      1.1  mrg 		 "IMAGES", images[i]);
    257      1.1  mrg 	exit (EXIT_FAILURE);
    258      1.1  mrg       }
    259      1.1  mrg #endif
    260      1.1  mrg 
    261      1.1  mrg   __asm__ __volatile__ ("":::"memory");
    262      1.1  mrg   if (stat)
    263      1.1  mrg     *stat = 0;
    264      1.1  mrg }
    265      1.1  mrg 
    266      1.1  mrg 
    267      1.1  mrg void
    268      1.1  mrg _gfortran_caf_stop_numeric(int stop_code, bool quiet)
    269      1.1  mrg {
    270      1.1  mrg   if (!quiet)
    271      1.1  mrg     fprintf (stderr, "STOP %d\n", stop_code);
    272      1.1  mrg   exit (0);
    273      1.1  mrg }
    274      1.1  mrg 
    275      1.1  mrg 
    276      1.1  mrg void
    277      1.1  mrg _gfortran_caf_stop_str(const char *string, size_t len, bool quiet)
    278      1.1  mrg {
    279      1.1  mrg   if (!quiet)
    280      1.1  mrg     {
    281      1.1  mrg       fputs ("STOP ", stderr);
    282      1.1  mrg       while (len--)
    283      1.1  mrg 	fputc (*(string++), stderr);
    284      1.1  mrg       fputs ("\n", stderr);
    285      1.1  mrg     }
    286      1.1  mrg   exit (0);
    287      1.1  mrg }
    288      1.1  mrg 
    289      1.1  mrg 
    290      1.1  mrg void
    291      1.1  mrg _gfortran_caf_error_stop_str (const char *string, size_t len, bool quiet)
    292      1.1  mrg {
    293      1.1  mrg   if (!quiet)
    294      1.1  mrg     {
    295      1.1  mrg       fputs ("ERROR STOP ", stderr);
    296      1.1  mrg       while (len--)
    297      1.1  mrg 	fputc (*(string++), stderr);
    298      1.1  mrg       fputs ("\n", stderr);
    299      1.1  mrg     }
    300      1.1  mrg   exit (1);
    301      1.1  mrg }
    302      1.1  mrg 
    303      1.1  mrg 
    304      1.1  mrg /* Reported that the program terminated because of a fail image issued.
    305      1.1  mrg    Because this is a single image library, nothing else than aborting the whole
    306      1.1  mrg    program can be done.  */
    307      1.1  mrg 
    308      1.1  mrg void _gfortran_caf_fail_image (void)
    309      1.1  mrg {
    310      1.1  mrg   fputs ("IMAGE FAILED!\n", stderr);
    311      1.1  mrg   exit (0);
    312      1.1  mrg }
    313      1.1  mrg 
    314      1.1  mrg 
    315      1.1  mrg /* Get the status of image IMAGE.  Because being the single image library all
    316      1.1  mrg    other images are reported to be stopped.  */
    317      1.1  mrg 
    318      1.1  mrg int _gfortran_caf_image_status (int image,
    319      1.1  mrg 				caf_team_t * team __attribute__ ((unused)))
    320      1.1  mrg {
    321      1.1  mrg   if (image == 1)
    322      1.1  mrg     return 0;
    323      1.1  mrg   else
    324      1.1  mrg     return CAF_STAT_STOPPED_IMAGE;
    325      1.1  mrg }
    326      1.1  mrg 
    327      1.1  mrg 
    328      1.1  mrg /* Single image library.  There cannot be any failed images with only one
    329      1.1  mrg    image.  */
    330      1.1  mrg 
    331      1.1  mrg void
    332      1.1  mrg _gfortran_caf_failed_images (gfc_descriptor_t *array,
    333      1.1  mrg 			     caf_team_t * team __attribute__ ((unused)),
    334      1.1  mrg 			     int * kind)
    335      1.1  mrg {
    336      1.1  mrg   int local_kind = kind != NULL ? *kind : 4;
    337      1.1  mrg 
    338      1.1  mrg   array->base_addr = NULL;
    339      1.1  mrg   array->dtype.type = BT_INTEGER;
    340      1.1  mrg   array->dtype.elem_len = local_kind;
    341      1.1  mrg    /* Setting lower_bound higher then upper_bound is what the compiler does to
    342      1.1  mrg       indicate an empty array.  */
    343      1.1  mrg   array->dim[0].lower_bound = 0;
    344      1.1  mrg   array->dim[0]._ubound = -1;
    345      1.1  mrg   array->dim[0]._stride = 1;
    346      1.1  mrg   array->offset = 0;
    347      1.1  mrg }
    348      1.1  mrg 
    349      1.1  mrg 
    350      1.1  mrg /* With only one image available no other images can be stopped.  Therefore
    351      1.1  mrg    return an empty array.  */
    352      1.1  mrg 
    353      1.1  mrg void
    354      1.1  mrg _gfortran_caf_stopped_images (gfc_descriptor_t *array,
    355      1.1  mrg 			      caf_team_t * team __attribute__ ((unused)),
    356      1.1  mrg 			      int * kind)
    357      1.1  mrg {
    358      1.1  mrg   int local_kind = kind != NULL ? *kind : 4;
    359      1.1  mrg 
    360      1.1  mrg   array->base_addr = NULL;
    361      1.1  mrg   array->dtype.type =  BT_INTEGER;
    362      1.1  mrg   array->dtype.elem_len =  local_kind;
    363      1.1  mrg   /* Setting lower_bound higher then upper_bound is what the compiler does to
    364      1.1  mrg      indicate an empty array.  */
    365      1.1  mrg   array->dim[0].lower_bound = 0;
    366      1.1  mrg   array->dim[0]._ubound = -1;
    367      1.1  mrg   array->dim[0]._stride = 1;
    368      1.1  mrg   array->offset = 0;
    369      1.1  mrg }
    370      1.1  mrg 
    371      1.1  mrg 
    372      1.1  mrg void
    373      1.1  mrg _gfortran_caf_error_stop (int error, bool quiet)
    374      1.1  mrg {
    375      1.1  mrg   if (!quiet)
    376      1.1  mrg     fprintf (stderr, "ERROR STOP %d\n", error);
    377      1.1  mrg   exit (error);
    378      1.1  mrg }
    379      1.1  mrg 
    380      1.1  mrg 
    381      1.1  mrg void
    382      1.1  mrg _gfortran_caf_co_broadcast (gfc_descriptor_t *a __attribute__ ((unused)),
    383      1.1  mrg 			    int source_image __attribute__ ((unused)),
    384      1.1  mrg 			    int *stat, char *errmsg __attribute__ ((unused)),
    385      1.1  mrg 			    size_t errmsg_len __attribute__ ((unused)))
    386      1.1  mrg {
    387      1.1  mrg   if (stat)
    388      1.1  mrg     *stat = 0;
    389      1.1  mrg }
    390      1.1  mrg 
    391      1.1  mrg void
    392      1.1  mrg _gfortran_caf_co_sum (gfc_descriptor_t *a __attribute__ ((unused)),
    393      1.1  mrg 		      int result_image __attribute__ ((unused)),
    394      1.1  mrg 		      int *stat, char *errmsg __attribute__ ((unused)),
    395      1.1  mrg 		      size_t errmsg_len __attribute__ ((unused)))
    396      1.1  mrg {
    397      1.1  mrg   if (stat)
    398      1.1  mrg     *stat = 0;
    399      1.1  mrg }
    400      1.1  mrg 
    401      1.1  mrg void
    402      1.1  mrg _gfortran_caf_co_min (gfc_descriptor_t *a __attribute__ ((unused)),
    403      1.1  mrg 		      int result_image __attribute__ ((unused)),
    404      1.1  mrg 		      int *stat, char *errmsg __attribute__ ((unused)),
    405      1.1  mrg 		      int a_len __attribute__ ((unused)),
    406      1.1  mrg 		      size_t errmsg_len __attribute__ ((unused)))
    407      1.1  mrg {
    408      1.1  mrg   if (stat)
    409      1.1  mrg     *stat = 0;
    410      1.1  mrg }
    411      1.1  mrg 
    412      1.1  mrg void
    413      1.1  mrg _gfortran_caf_co_max (gfc_descriptor_t *a __attribute__ ((unused)),
    414      1.1  mrg 		      int result_image __attribute__ ((unused)),
    415      1.1  mrg 		      int *stat, char *errmsg __attribute__ ((unused)),
    416      1.1  mrg 		      int a_len __attribute__ ((unused)),
    417      1.1  mrg 		      size_t errmsg_len __attribute__ ((unused)))
    418      1.1  mrg {
    419      1.1  mrg   if (stat)
    420      1.1  mrg     *stat = 0;
    421      1.1  mrg }
    422      1.1  mrg 
    423      1.1  mrg 
    424      1.1  mrg void
    425      1.1  mrg _gfortran_caf_co_reduce (gfc_descriptor_t *a __attribute__ ((unused)),
    426      1.1  mrg                         void * (*opr) (void *, void *)
    427      1.1  mrg                                __attribute__ ((unused)),
    428      1.1  mrg                         int opr_flags __attribute__ ((unused)),
    429      1.1  mrg                         int result_image __attribute__ ((unused)),
    430      1.1  mrg                         int *stat, char *errmsg __attribute__ ((unused)),
    431      1.1  mrg                         int a_len __attribute__ ((unused)),
    432      1.1  mrg                         size_t errmsg_len __attribute__ ((unused)))
    433      1.1  mrg  {
    434      1.1  mrg    if (stat)
    435      1.1  mrg      *stat = 0;
    436      1.1  mrg  }
    437      1.1  mrg 
    438      1.1  mrg 
    439      1.1  mrg static void
    440      1.1  mrg assign_char4_from_char1 (size_t dst_size, size_t src_size, uint32_t *dst,
    441      1.1  mrg 			 unsigned char *src)
    442      1.1  mrg {
    443      1.1  mrg   size_t i, n;
    444      1.1  mrg   n = dst_size/4 > src_size ? src_size : dst_size/4;
    445      1.1  mrg   for (i = 0; i < n; ++i)
    446      1.1  mrg     dst[i] = (int32_t) src[i];
    447      1.1  mrg   for (; i < dst_size/4; ++i)
    448      1.1  mrg     dst[i] = (int32_t) ' ';
    449      1.1  mrg }
    450      1.1  mrg 
    451      1.1  mrg 
    452      1.1  mrg static void
    453      1.1  mrg assign_char1_from_char4 (size_t dst_size, size_t src_size, unsigned char *dst,
    454      1.1  mrg 			 uint32_t *src)
    455      1.1  mrg {
    456      1.1  mrg   size_t i, n;
    457      1.1  mrg   n = dst_size > src_size/4 ? src_size/4 : dst_size;
    458      1.1  mrg   for (i = 0; i < n; ++i)
    459      1.1  mrg     dst[i] = src[i] > UINT8_MAX ? (unsigned char) '?' : (unsigned char) src[i];
    460      1.1  mrg   if (dst_size > n)
    461      1.1  mrg     memset (&dst[n], ' ', dst_size - n);
    462      1.1  mrg }
    463      1.1  mrg 
    464      1.1  mrg 
    465      1.1  mrg static void
    466      1.1  mrg convert_type (void *dst, int dst_type, int dst_kind, void *src, int src_type,
    467      1.1  mrg 	      int src_kind, int *stat)
    468      1.1  mrg {
    469      1.1  mrg #ifdef HAVE_GFC_INTEGER_16
    470      1.1  mrg   typedef __int128 int128t;
    471      1.1  mrg #else
    472      1.1  mrg   typedef int64_t int128t;
    473      1.1  mrg #endif
    474      1.1  mrg 
    475      1.1  mrg #if defined(GFC_REAL_16_IS_LONG_DOUBLE)
    476      1.1  mrg   typedef long double real128t;
    477      1.1  mrg   typedef _Complex long double complex128t;
    478      1.1  mrg #elif defined(HAVE_GFC_REAL_16)
    479  1.1.1.4  mrg   typedef _Float128 real128t;
    480  1.1.1.4  mrg   typedef _Complex _Float128 complex128t;
    481      1.1  mrg #elif defined(HAVE_GFC_REAL_10)
    482      1.1  mrg   typedef long double real128t;
    483  1.1.1.4  mrg   typedef _Complex long double complex128t;
    484      1.1  mrg #else
    485      1.1  mrg   typedef double real128t;
    486      1.1  mrg   typedef _Complex double complex128t;
    487      1.1  mrg #endif
    488      1.1  mrg 
    489      1.1  mrg   int128t int_val = 0;
    490      1.1  mrg   real128t real_val = 0;
    491      1.1  mrg   complex128t cmpx_val = 0;
    492      1.1  mrg 
    493      1.1  mrg   switch (src_type)
    494      1.1  mrg     {
    495      1.1  mrg     case BT_INTEGER:
    496      1.1  mrg       if (src_kind == 1)
    497      1.1  mrg 	int_val = *(int8_t*) src;
    498      1.1  mrg       else if (src_kind == 2)
    499      1.1  mrg 	int_val = *(int16_t*) src;
    500      1.1  mrg       else if (src_kind == 4)
    501      1.1  mrg 	int_val = *(int32_t*) src;
    502      1.1  mrg       else if (src_kind == 8)
    503      1.1  mrg 	int_val = *(int64_t*) src;
    504      1.1  mrg #ifdef HAVE_GFC_INTEGER_16
    505      1.1  mrg       else if (src_kind == 16)
    506      1.1  mrg 	int_val = *(int128t*) src;
    507      1.1  mrg #endif
    508      1.1  mrg       else
    509      1.1  mrg 	goto error;
    510      1.1  mrg       break;
    511      1.1  mrg     case BT_REAL:
    512      1.1  mrg       if (src_kind == 4)
    513      1.1  mrg 	real_val = *(float*) src;
    514      1.1  mrg       else if (src_kind == 8)
    515      1.1  mrg 	real_val = *(double*) src;
    516      1.1  mrg #ifdef HAVE_GFC_REAL_10
    517      1.1  mrg       else if (src_kind == 10)
    518      1.1  mrg 	real_val = *(long double*) src;
    519      1.1  mrg #endif
    520      1.1  mrg #ifdef HAVE_GFC_REAL_16
    521      1.1  mrg       else if (src_kind == 16)
    522      1.1  mrg 	real_val = *(real128t*) src;
    523      1.1  mrg #endif
    524      1.1  mrg       else
    525      1.1  mrg 	goto error;
    526      1.1  mrg       break;
    527      1.1  mrg     case BT_COMPLEX:
    528      1.1  mrg       if (src_kind == 4)
    529      1.1  mrg 	cmpx_val = *(_Complex float*) src;
    530      1.1  mrg       else if (src_kind == 8)
    531      1.1  mrg 	cmpx_val = *(_Complex double*) src;
    532      1.1  mrg #ifdef HAVE_GFC_REAL_10
    533      1.1  mrg       else if (src_kind == 10)
    534      1.1  mrg 	cmpx_val = *(_Complex long double*) src;
    535      1.1  mrg #endif
    536      1.1  mrg #ifdef HAVE_GFC_REAL_16
    537      1.1  mrg       else if (src_kind == 16)
    538      1.1  mrg 	cmpx_val = *(complex128t*) src;
    539      1.1  mrg #endif
    540      1.1  mrg       else
    541      1.1  mrg 	goto error;
    542      1.1  mrg       break;
    543      1.1  mrg     default:
    544      1.1  mrg       goto error;
    545      1.1  mrg     }
    546      1.1  mrg 
    547      1.1  mrg   switch (dst_type)
    548      1.1  mrg     {
    549      1.1  mrg     case BT_INTEGER:
    550      1.1  mrg       if (src_type == BT_INTEGER)
    551      1.1  mrg 	{
    552      1.1  mrg 	  if (dst_kind == 1)
    553      1.1  mrg 	    *(int8_t*) dst = (int8_t) int_val;
    554      1.1  mrg 	  else if (dst_kind == 2)
    555      1.1  mrg 	    *(int16_t*) dst = (int16_t) int_val;
    556      1.1  mrg 	  else if (dst_kind == 4)
    557      1.1  mrg 	    *(int32_t*) dst = (int32_t) int_val;
    558      1.1  mrg 	  else if (dst_kind == 8)
    559      1.1  mrg 	    *(int64_t*) dst = (int64_t) int_val;
    560      1.1  mrg #ifdef HAVE_GFC_INTEGER_16
    561      1.1  mrg 	  else if (dst_kind == 16)
    562      1.1  mrg 	    *(int128t*) dst = (int128t) int_val;
    563      1.1  mrg #endif
    564      1.1  mrg 	  else
    565      1.1  mrg 	    goto error;
    566      1.1  mrg 	}
    567      1.1  mrg       else if (src_type == BT_REAL)
    568      1.1  mrg 	{
    569      1.1  mrg 	  if (dst_kind == 1)
    570      1.1  mrg 	    *(int8_t*) dst = (int8_t) real_val;
    571      1.1  mrg 	  else if (dst_kind == 2)
    572      1.1  mrg 	    *(int16_t*) dst = (int16_t) real_val;
    573      1.1  mrg 	  else if (dst_kind == 4)
    574      1.1  mrg 	    *(int32_t*) dst = (int32_t) real_val;
    575      1.1  mrg 	  else if (dst_kind == 8)
    576      1.1  mrg 	    *(int64_t*) dst = (int64_t) real_val;
    577      1.1  mrg #ifdef HAVE_GFC_INTEGER_16
    578      1.1  mrg 	  else if (dst_kind == 16)
    579      1.1  mrg 	    *(int128t*) dst = (int128t) real_val;
    580      1.1  mrg #endif
    581      1.1  mrg 	  else
    582      1.1  mrg 	    goto error;
    583      1.1  mrg 	}
    584      1.1  mrg       else if (src_type == BT_COMPLEX)
    585      1.1  mrg 	{
    586      1.1  mrg 	  if (dst_kind == 1)
    587      1.1  mrg 	    *(int8_t*) dst = (int8_t) cmpx_val;
    588      1.1  mrg 	  else if (dst_kind == 2)
    589      1.1  mrg 	    *(int16_t*) dst = (int16_t) cmpx_val;
    590      1.1  mrg 	  else if (dst_kind == 4)
    591      1.1  mrg 	    *(int32_t*) dst = (int32_t) cmpx_val;
    592      1.1  mrg 	  else if (dst_kind == 8)
    593      1.1  mrg 	    *(int64_t*) dst = (int64_t) cmpx_val;
    594      1.1  mrg #ifdef HAVE_GFC_INTEGER_16
    595      1.1  mrg 	  else if (dst_kind == 16)
    596      1.1  mrg 	    *(int128t*) dst = (int128t) cmpx_val;
    597      1.1  mrg #endif
    598      1.1  mrg 	  else
    599      1.1  mrg 	    goto error;
    600      1.1  mrg 	}
    601      1.1  mrg       else
    602      1.1  mrg 	goto error;
    603      1.1  mrg       return;
    604      1.1  mrg     case BT_REAL:
    605      1.1  mrg       if (src_type == BT_INTEGER)
    606      1.1  mrg 	{
    607      1.1  mrg 	  if (dst_kind == 4)
    608      1.1  mrg 	    *(float*) dst = (float) int_val;
    609      1.1  mrg 	  else if (dst_kind == 8)
    610      1.1  mrg 	    *(double*) dst = (double) int_val;
    611      1.1  mrg #ifdef HAVE_GFC_REAL_10
    612      1.1  mrg 	  else if (dst_kind == 10)
    613      1.1  mrg 	    *(long double*) dst = (long double) int_val;
    614      1.1  mrg #endif
    615      1.1  mrg #ifdef HAVE_GFC_REAL_16
    616      1.1  mrg 	  else if (dst_kind == 16)
    617      1.1  mrg 	    *(real128t*) dst = (real128t) int_val;
    618      1.1  mrg #endif
    619      1.1  mrg 	  else
    620      1.1  mrg 	    goto error;
    621      1.1  mrg 	}
    622      1.1  mrg       else if (src_type == BT_REAL)
    623      1.1  mrg 	{
    624      1.1  mrg 	  if (dst_kind == 4)
    625      1.1  mrg 	    *(float*) dst = (float) real_val;
    626      1.1  mrg 	  else if (dst_kind == 8)
    627      1.1  mrg 	    *(double*) dst = (double) real_val;
    628      1.1  mrg #ifdef HAVE_GFC_REAL_10
    629      1.1  mrg 	  else if (dst_kind == 10)
    630      1.1  mrg 	    *(long double*) dst = (long double) real_val;
    631      1.1  mrg #endif
    632      1.1  mrg #ifdef HAVE_GFC_REAL_16
    633      1.1  mrg 	  else if (dst_kind == 16)
    634      1.1  mrg 	    *(real128t*) dst = (real128t) real_val;
    635      1.1  mrg #endif
    636      1.1  mrg 	  else
    637      1.1  mrg 	    goto error;
    638      1.1  mrg 	}
    639      1.1  mrg       else if (src_type == BT_COMPLEX)
    640      1.1  mrg 	{
    641      1.1  mrg 	  if (dst_kind == 4)
    642      1.1  mrg 	    *(float*) dst = (float) cmpx_val;
    643      1.1  mrg 	  else if (dst_kind == 8)
    644      1.1  mrg 	    *(double*) dst = (double) cmpx_val;
    645      1.1  mrg #ifdef HAVE_GFC_REAL_10
    646      1.1  mrg 	  else if (dst_kind == 10)
    647      1.1  mrg 	    *(long double*) dst = (long double) cmpx_val;
    648      1.1  mrg #endif
    649      1.1  mrg #ifdef HAVE_GFC_REAL_16
    650      1.1  mrg 	  else if (dst_kind == 16)
    651      1.1  mrg 	    *(real128t*) dst = (real128t) cmpx_val;
    652      1.1  mrg #endif
    653      1.1  mrg 	  else
    654      1.1  mrg 	    goto error;
    655      1.1  mrg 	}
    656      1.1  mrg       return;
    657      1.1  mrg     case BT_COMPLEX:
    658      1.1  mrg       if (src_type == BT_INTEGER)
    659      1.1  mrg 	{
    660      1.1  mrg 	  if (dst_kind == 4)
    661      1.1  mrg 	    *(_Complex float*) dst = (_Complex float) int_val;
    662      1.1  mrg 	  else if (dst_kind == 8)
    663      1.1  mrg 	    *(_Complex double*) dst = (_Complex double) int_val;
    664      1.1  mrg #ifdef HAVE_GFC_REAL_10
    665      1.1  mrg 	  else if (dst_kind == 10)
    666      1.1  mrg 	    *(_Complex long double*) dst = (_Complex long double) int_val;
    667      1.1  mrg #endif
    668      1.1  mrg #ifdef HAVE_GFC_REAL_16
    669      1.1  mrg 	  else if (dst_kind == 16)
    670      1.1  mrg 	    *(complex128t*) dst = (complex128t) int_val;
    671      1.1  mrg #endif
    672      1.1  mrg 	  else
    673      1.1  mrg 	    goto error;
    674      1.1  mrg 	}
    675      1.1  mrg       else if (src_type == BT_REAL)
    676      1.1  mrg 	{
    677      1.1  mrg 	  if (dst_kind == 4)
    678      1.1  mrg 	    *(_Complex float*) dst = (_Complex float) real_val;
    679      1.1  mrg 	  else if (dst_kind == 8)
    680      1.1  mrg 	    *(_Complex double*) dst = (_Complex double) real_val;
    681      1.1  mrg #ifdef HAVE_GFC_REAL_10
    682      1.1  mrg 	  else if (dst_kind == 10)
    683      1.1  mrg 	    *(_Complex long double*) dst = (_Complex long double) real_val;
    684      1.1  mrg #endif
    685      1.1  mrg #ifdef HAVE_GFC_REAL_16
    686      1.1  mrg 	  else if (dst_kind == 16)
    687      1.1  mrg 	    *(complex128t*) dst = (complex128t) real_val;
    688      1.1  mrg #endif
    689      1.1  mrg 	  else
    690      1.1  mrg 	    goto error;
    691      1.1  mrg 	}
    692      1.1  mrg       else if (src_type == BT_COMPLEX)
    693      1.1  mrg 	{
    694      1.1  mrg 	  if (dst_kind == 4)
    695      1.1  mrg 	    *(_Complex float*) dst = (_Complex float) cmpx_val;
    696      1.1  mrg 	  else if (dst_kind == 8)
    697      1.1  mrg 	    *(_Complex double*) dst = (_Complex double) cmpx_val;
    698      1.1  mrg #ifdef HAVE_GFC_REAL_10
    699      1.1  mrg 	  else if (dst_kind == 10)
    700      1.1  mrg 	    *(_Complex long double*) dst = (_Complex long double) cmpx_val;
    701      1.1  mrg #endif
    702      1.1  mrg #ifdef HAVE_GFC_REAL_16
    703      1.1  mrg 	  else if (dst_kind == 16)
    704      1.1  mrg 	    *(complex128t*) dst = (complex128t) cmpx_val;
    705      1.1  mrg #endif
    706      1.1  mrg 	  else
    707      1.1  mrg 	    goto error;
    708      1.1  mrg 	}
    709      1.1  mrg       else
    710      1.1  mrg 	goto error;
    711      1.1  mrg       return;
    712      1.1  mrg     default:
    713      1.1  mrg       goto error;
    714      1.1  mrg     }
    715      1.1  mrg 
    716      1.1  mrg error:
    717      1.1  mrg   fprintf (stderr, "libcaf_single RUNTIME ERROR: Cannot convert type %d kind "
    718      1.1  mrg 	   "%d to type %d kind %d\n", src_type, src_kind, dst_type, dst_kind);
    719      1.1  mrg   if (stat)
    720      1.1  mrg     *stat = 1;
    721      1.1  mrg   else
    722      1.1  mrg     abort ();
    723      1.1  mrg }
    724      1.1  mrg 
    725      1.1  mrg 
    726      1.1  mrg void
    727      1.1  mrg _gfortran_caf_get (caf_token_t token, size_t offset,
    728      1.1  mrg 		   int image_index __attribute__ ((unused)),
    729      1.1  mrg 		   gfc_descriptor_t *src,
    730      1.1  mrg 		   caf_vector_t *src_vector __attribute__ ((unused)),
    731      1.1  mrg 		   gfc_descriptor_t *dest, int src_kind, int dst_kind,
    732      1.1  mrg 		   bool may_require_tmp, int *stat)
    733      1.1  mrg {
    734      1.1  mrg   /* FIXME: Handle vector subscripts.  */
    735      1.1  mrg   size_t i, k, size;
    736      1.1  mrg   int j;
    737      1.1  mrg   int rank = GFC_DESCRIPTOR_RANK (dest);
    738      1.1  mrg   size_t src_size = GFC_DESCRIPTOR_SIZE (src);
    739      1.1  mrg   size_t dst_size = GFC_DESCRIPTOR_SIZE (dest);
    740      1.1  mrg 
    741      1.1  mrg   if (stat)
    742      1.1  mrg     *stat = 0;
    743      1.1  mrg 
    744      1.1  mrg   if (rank == 0)
    745      1.1  mrg     {
    746      1.1  mrg       void *sr = (void *) ((char *) MEMTOK (token) + offset);
    747      1.1  mrg       if (GFC_DESCRIPTOR_TYPE (dest) == GFC_DESCRIPTOR_TYPE (src)
    748      1.1  mrg 	  && dst_kind == src_kind)
    749      1.1  mrg 	{
    750      1.1  mrg 	  memmove (GFC_DESCRIPTOR_DATA (dest), sr,
    751      1.1  mrg 		   dst_size > src_size ? src_size : dst_size);
    752      1.1  mrg 	  if (GFC_DESCRIPTOR_TYPE (dest) == BT_CHARACTER && dst_size > src_size)
    753      1.1  mrg 	    {
    754      1.1  mrg 	      if (dst_kind == 1)
    755      1.1  mrg 		memset ((void*)(char*) GFC_DESCRIPTOR_DATA (dest) + src_size,
    756      1.1  mrg 			' ', dst_size - src_size);
    757      1.1  mrg 	      else /* dst_kind == 4.  */
    758      1.1  mrg 		for (i = src_size/4; i < dst_size/4; i++)
    759      1.1  mrg 		  ((int32_t*) GFC_DESCRIPTOR_DATA (dest))[i] = (int32_t) ' ';
    760      1.1  mrg 	    }
    761      1.1  mrg 	}
    762      1.1  mrg       else if (GFC_DESCRIPTOR_TYPE (dest) == BT_CHARACTER && dst_kind == 1)
    763      1.1  mrg 	assign_char1_from_char4 (dst_size, src_size, GFC_DESCRIPTOR_DATA (dest),
    764      1.1  mrg 				 sr);
    765      1.1  mrg       else if (GFC_DESCRIPTOR_TYPE (dest) == BT_CHARACTER)
    766      1.1  mrg 	assign_char4_from_char1 (dst_size, src_size, GFC_DESCRIPTOR_DATA (dest),
    767      1.1  mrg 				 sr);
    768      1.1  mrg       else
    769      1.1  mrg 	convert_type (GFC_DESCRIPTOR_DATA (dest), GFC_DESCRIPTOR_TYPE (dest),
    770      1.1  mrg 		      dst_kind, sr, GFC_DESCRIPTOR_TYPE (src), src_kind, stat);
    771      1.1  mrg       return;
    772      1.1  mrg     }
    773      1.1  mrg 
    774      1.1  mrg   size = 1;
    775      1.1  mrg   for (j = 0; j < rank; j++)
    776      1.1  mrg     {
    777      1.1  mrg       ptrdiff_t dimextent = dest->dim[j]._ubound - dest->dim[j].lower_bound + 1;
    778      1.1  mrg       if (dimextent < 0)
    779      1.1  mrg 	dimextent = 0;
    780      1.1  mrg       size *= dimextent;
    781      1.1  mrg     }
    782      1.1  mrg 
    783      1.1  mrg   if (size == 0)
    784      1.1  mrg     return;
    785      1.1  mrg 
    786      1.1  mrg   if (may_require_tmp)
    787      1.1  mrg     {
    788      1.1  mrg       ptrdiff_t array_offset_sr, array_offset_dst;
    789      1.1  mrg       void *tmp = malloc (size*src_size);
    790      1.1  mrg 
    791      1.1  mrg       array_offset_dst = 0;
    792      1.1  mrg       for (i = 0; i < size; i++)
    793      1.1  mrg 	{
    794      1.1  mrg 	  ptrdiff_t array_offset_sr = 0;
    795      1.1  mrg 	  ptrdiff_t stride = 1;
    796      1.1  mrg 	  ptrdiff_t extent = 1;
    797      1.1  mrg 	  for (j = 0; j < GFC_DESCRIPTOR_RANK (src)-1; j++)
    798      1.1  mrg 	    {
    799      1.1  mrg 	      array_offset_sr += ((i / (extent*stride))
    800      1.1  mrg 				  % (src->dim[j]._ubound
    801      1.1  mrg 				    - src->dim[j].lower_bound + 1))
    802      1.1  mrg 				 * src->dim[j]._stride;
    803      1.1  mrg 	      extent = (src->dim[j]._ubound - src->dim[j].lower_bound + 1);
    804      1.1  mrg 	      stride = src->dim[j]._stride;
    805      1.1  mrg 	    }
    806      1.1  mrg 	  array_offset_sr += (i / extent) * src->dim[rank-1]._stride;
    807      1.1  mrg 	  void *sr = (void *)((char *) MEMTOK (token) + offset
    808      1.1  mrg 			  + array_offset_sr*GFC_DESCRIPTOR_SIZE (src));
    809      1.1  mrg           memcpy ((void *) ((char *) tmp + array_offset_dst), sr, src_size);
    810      1.1  mrg           array_offset_dst += src_size;
    811      1.1  mrg 	}
    812      1.1  mrg 
    813      1.1  mrg       array_offset_sr = 0;
    814      1.1  mrg       for (i = 0; i < size; i++)
    815      1.1  mrg 	{
    816      1.1  mrg 	  ptrdiff_t array_offset_dst = 0;
    817      1.1  mrg 	  ptrdiff_t stride = 1;
    818      1.1  mrg 	  ptrdiff_t extent = 1;
    819      1.1  mrg 	  for (j = 0; j < rank-1; j++)
    820      1.1  mrg 	    {
    821      1.1  mrg 	      array_offset_dst += ((i / (extent*stride))
    822      1.1  mrg 				   % (dest->dim[j]._ubound
    823      1.1  mrg 				      - dest->dim[j].lower_bound + 1))
    824      1.1  mrg 				  * dest->dim[j]._stride;
    825      1.1  mrg 	      extent = (dest->dim[j]._ubound - dest->dim[j].lower_bound + 1);
    826      1.1  mrg 	      stride = dest->dim[j]._stride;
    827      1.1  mrg 	    }
    828      1.1  mrg 	  array_offset_dst += (i / extent) * dest->dim[rank-1]._stride;
    829      1.1  mrg 	  void *dst = dest->base_addr
    830      1.1  mrg 		      + array_offset_dst*GFC_DESCRIPTOR_SIZE (dest);
    831      1.1  mrg           void *sr = tmp + array_offset_sr;
    832      1.1  mrg 
    833      1.1  mrg 	  if (GFC_DESCRIPTOR_TYPE (dest) == GFC_DESCRIPTOR_TYPE (src)
    834      1.1  mrg 	      && dst_kind == src_kind)
    835      1.1  mrg 	    {
    836      1.1  mrg 	      memmove (dst, sr, dst_size > src_size ? src_size : dst_size);
    837      1.1  mrg 	      if (GFC_DESCRIPTOR_TYPE (dest) == BT_CHARACTER
    838      1.1  mrg 	          && dst_size > src_size)
    839      1.1  mrg 		{
    840      1.1  mrg 		  if (dst_kind == 1)
    841      1.1  mrg 		    memset ((void*)(char*) dst + src_size, ' ',
    842      1.1  mrg 			    dst_size-src_size);
    843      1.1  mrg 		  else /* dst_kind == 4.  */
    844      1.1  mrg 		    for (k = src_size/4; k < dst_size/4; k++)
    845      1.1  mrg 		      ((int32_t*) dst)[k] = (int32_t) ' ';
    846      1.1  mrg 		}
    847      1.1  mrg 	    }
    848      1.1  mrg 	  else if (GFC_DESCRIPTOR_TYPE (dest) == BT_CHARACTER && dst_kind == 1)
    849      1.1  mrg 	    assign_char1_from_char4 (dst_size, src_size, dst, sr);
    850      1.1  mrg 	  else if (GFC_DESCRIPTOR_TYPE (dest) == BT_CHARACTER)
    851      1.1  mrg 	    assign_char4_from_char1 (dst_size, src_size, dst, sr);
    852      1.1  mrg 	  else
    853      1.1  mrg 	    convert_type (dst, GFC_DESCRIPTOR_TYPE (dest), dst_kind,
    854      1.1  mrg 			  sr, GFC_DESCRIPTOR_TYPE (src), src_kind, stat);
    855      1.1  mrg           array_offset_sr += src_size;
    856      1.1  mrg 	}
    857      1.1  mrg 
    858      1.1  mrg       free (tmp);
    859      1.1  mrg       return;
    860      1.1  mrg     }
    861      1.1  mrg 
    862      1.1  mrg   for (i = 0; i < size; i++)
    863      1.1  mrg     {
    864      1.1  mrg       ptrdiff_t array_offset_dst = 0;
    865      1.1  mrg       ptrdiff_t stride = 1;
    866      1.1  mrg       ptrdiff_t extent = 1;
    867      1.1  mrg       for (j = 0; j < rank-1; j++)
    868      1.1  mrg 	{
    869      1.1  mrg 	  array_offset_dst += ((i / (extent*stride))
    870      1.1  mrg 			       % (dest->dim[j]._ubound
    871      1.1  mrg 				  - dest->dim[j].lower_bound + 1))
    872      1.1  mrg 			      * dest->dim[j]._stride;
    873      1.1  mrg 	  extent = (dest->dim[j]._ubound - dest->dim[j].lower_bound + 1);
    874      1.1  mrg           stride = dest->dim[j]._stride;
    875      1.1  mrg 	}
    876      1.1  mrg       array_offset_dst += (i / extent) * dest->dim[rank-1]._stride;
    877      1.1  mrg       void *dst = dest->base_addr + array_offset_dst*GFC_DESCRIPTOR_SIZE (dest);
    878      1.1  mrg 
    879      1.1  mrg       ptrdiff_t array_offset_sr = 0;
    880      1.1  mrg       stride = 1;
    881      1.1  mrg       extent = 1;
    882      1.1  mrg       for (j = 0; j < GFC_DESCRIPTOR_RANK (src)-1; j++)
    883      1.1  mrg 	{
    884      1.1  mrg 	  array_offset_sr += ((i / (extent*stride))
    885      1.1  mrg 			       % (src->dim[j]._ubound
    886      1.1  mrg 				  - src->dim[j].lower_bound + 1))
    887      1.1  mrg 			      * src->dim[j]._stride;
    888      1.1  mrg 	  extent = (src->dim[j]._ubound - src->dim[j].lower_bound + 1);
    889      1.1  mrg 	  stride = src->dim[j]._stride;
    890      1.1  mrg 	}
    891      1.1  mrg       array_offset_sr += (i / extent) * src->dim[rank-1]._stride;
    892      1.1  mrg       void *sr = (void *)((char *) MEMTOK (token) + offset
    893      1.1  mrg 			  + array_offset_sr*GFC_DESCRIPTOR_SIZE (src));
    894      1.1  mrg 
    895      1.1  mrg       if (GFC_DESCRIPTOR_TYPE (dest) == GFC_DESCRIPTOR_TYPE (src)
    896      1.1  mrg 	  && dst_kind == src_kind)
    897      1.1  mrg 	{
    898      1.1  mrg 	  memmove (dst, sr, dst_size > src_size ? src_size : dst_size);
    899      1.1  mrg 	  if (GFC_DESCRIPTOR_TYPE (dest) == BT_CHARACTER && dst_size > src_size)
    900      1.1  mrg 	    {
    901      1.1  mrg 	      if (dst_kind == 1)
    902      1.1  mrg 		memset ((void*)(char*) dst + src_size, ' ', dst_size-src_size);
    903      1.1  mrg 	      else /* dst_kind == 4.  */
    904      1.1  mrg 		for (k = src_size/4; k < dst_size/4; k++)
    905      1.1  mrg 		  ((int32_t*) dst)[k] = (int32_t) ' ';
    906      1.1  mrg 	    }
    907      1.1  mrg 	}
    908      1.1  mrg       else if (GFC_DESCRIPTOR_TYPE (dest) == BT_CHARACTER && dst_kind == 1)
    909      1.1  mrg 	assign_char1_from_char4 (dst_size, src_size, dst, sr);
    910      1.1  mrg       else if (GFC_DESCRIPTOR_TYPE (dest) == BT_CHARACTER)
    911      1.1  mrg 	assign_char4_from_char1 (dst_size, src_size, dst, sr);
    912      1.1  mrg       else
    913      1.1  mrg 	convert_type (dst, GFC_DESCRIPTOR_TYPE (dest), dst_kind,
    914      1.1  mrg 		      sr, GFC_DESCRIPTOR_TYPE (src), src_kind, stat);
    915      1.1  mrg     }
    916      1.1  mrg }
    917      1.1  mrg 
    918      1.1  mrg 
    919      1.1  mrg void
    920      1.1  mrg _gfortran_caf_send (caf_token_t token, size_t offset,
    921      1.1  mrg 		    int image_index __attribute__ ((unused)),
    922      1.1  mrg 		    gfc_descriptor_t *dest,
    923      1.1  mrg 		    caf_vector_t *dst_vector __attribute__ ((unused)),
    924      1.1  mrg 		    gfc_descriptor_t *src, int dst_kind, int src_kind,
    925      1.1  mrg 		    bool may_require_tmp, int *stat)
    926      1.1  mrg {
    927      1.1  mrg   /* FIXME: Handle vector subscripts.  */
    928      1.1  mrg   size_t i, k, size;
    929      1.1  mrg   int j;
    930      1.1  mrg   int rank = GFC_DESCRIPTOR_RANK (dest);
    931      1.1  mrg   size_t src_size = GFC_DESCRIPTOR_SIZE (src);
    932      1.1  mrg   size_t dst_size = GFC_DESCRIPTOR_SIZE (dest);
    933      1.1  mrg 
    934      1.1  mrg   if (stat)
    935      1.1  mrg     *stat = 0;
    936      1.1  mrg 
    937      1.1  mrg   if (rank == 0)
    938      1.1  mrg     {
    939      1.1  mrg       void *dst = (void *) ((char *) MEMTOK (token) + offset);
    940      1.1  mrg       if (GFC_DESCRIPTOR_TYPE (dest) == GFC_DESCRIPTOR_TYPE (src)
    941      1.1  mrg 	  && dst_kind == src_kind)
    942      1.1  mrg 	{
    943      1.1  mrg 	  memmove (dst, GFC_DESCRIPTOR_DATA (src),
    944      1.1  mrg 		   dst_size > src_size ? src_size : dst_size);
    945      1.1  mrg 	  if (GFC_DESCRIPTOR_TYPE (dest) == BT_CHARACTER && dst_size > src_size)
    946      1.1  mrg 	    {
    947      1.1  mrg 	      if (dst_kind == 1)
    948      1.1  mrg 		memset ((void*)(char*) dst + src_size, ' ', dst_size-src_size);
    949      1.1  mrg 	      else /* dst_kind == 4.  */
    950      1.1  mrg 		for (i = src_size/4; i < dst_size/4; i++)
    951      1.1  mrg 		  ((int32_t*) dst)[i] = (int32_t) ' ';
    952      1.1  mrg 	    }
    953      1.1  mrg 	}
    954      1.1  mrg       else if (GFC_DESCRIPTOR_TYPE (dest) == BT_CHARACTER && dst_kind == 1)
    955      1.1  mrg 	assign_char1_from_char4 (dst_size, src_size, dst,
    956      1.1  mrg 				 GFC_DESCRIPTOR_DATA (src));
    957      1.1  mrg       else if (GFC_DESCRIPTOR_TYPE (dest) == BT_CHARACTER)
    958      1.1  mrg 	assign_char4_from_char1 (dst_size, src_size, dst,
    959      1.1  mrg 				 GFC_DESCRIPTOR_DATA (src));
    960      1.1  mrg       else
    961      1.1  mrg 	convert_type (dst, GFC_DESCRIPTOR_TYPE (dest), dst_kind,
    962      1.1  mrg 		      GFC_DESCRIPTOR_DATA (src), GFC_DESCRIPTOR_TYPE (src),
    963      1.1  mrg 		      src_kind, stat);
    964      1.1  mrg       return;
    965      1.1  mrg     }
    966      1.1  mrg 
    967      1.1  mrg   size = 1;
    968      1.1  mrg   for (j = 0; j < rank; j++)
    969      1.1  mrg     {
    970      1.1  mrg       ptrdiff_t dimextent = dest->dim[j]._ubound - dest->dim[j].lower_bound + 1;
    971      1.1  mrg       if (dimextent < 0)
    972      1.1  mrg 	dimextent = 0;
    973      1.1  mrg       size *= dimextent;
    974      1.1  mrg     }
    975      1.1  mrg 
    976      1.1  mrg   if (size == 0)
    977      1.1  mrg     return;
    978      1.1  mrg 
    979      1.1  mrg   if (may_require_tmp)
    980      1.1  mrg     {
    981      1.1  mrg       ptrdiff_t array_offset_sr, array_offset_dst;
    982      1.1  mrg       void *tmp;
    983      1.1  mrg 
    984      1.1  mrg       if (GFC_DESCRIPTOR_RANK (src) == 0)
    985      1.1  mrg 	{
    986      1.1  mrg 	  tmp = malloc (src_size);
    987      1.1  mrg 	  memcpy (tmp, GFC_DESCRIPTOR_DATA (src), src_size);
    988      1.1  mrg 	}
    989      1.1  mrg       else
    990      1.1  mrg 	{
    991      1.1  mrg 	  tmp = malloc (size*src_size);
    992      1.1  mrg 	  array_offset_dst = 0;
    993      1.1  mrg 	  for (i = 0; i < size; i++)
    994      1.1  mrg 	    {
    995      1.1  mrg 	      ptrdiff_t array_offset_sr = 0;
    996      1.1  mrg 	      ptrdiff_t stride = 1;
    997      1.1  mrg 	      ptrdiff_t extent = 1;
    998      1.1  mrg 	      for (j = 0; j < GFC_DESCRIPTOR_RANK (src)-1; j++)
    999      1.1  mrg 		{
   1000      1.1  mrg 		  array_offset_sr += ((i / (extent*stride))
   1001      1.1  mrg 				      % (src->dim[j]._ubound
   1002      1.1  mrg 					 - src->dim[j].lower_bound + 1))
   1003      1.1  mrg 				     * src->dim[j]._stride;
   1004      1.1  mrg 		  extent = (src->dim[j]._ubound - src->dim[j].lower_bound + 1);
   1005      1.1  mrg 		  stride = src->dim[j]._stride;
   1006      1.1  mrg 		}
   1007      1.1  mrg 	      array_offset_sr += (i / extent) * src->dim[rank-1]._stride;
   1008      1.1  mrg 	      void *sr = (void *) ((char *) src->base_addr
   1009      1.1  mrg 				   + array_offset_sr*GFC_DESCRIPTOR_SIZE (src));
   1010      1.1  mrg 	      memcpy ((void *) ((char *) tmp + array_offset_dst), sr, src_size);
   1011      1.1  mrg 	      array_offset_dst += src_size;
   1012      1.1  mrg 	    }
   1013      1.1  mrg 	}
   1014      1.1  mrg 
   1015      1.1  mrg       array_offset_sr = 0;
   1016      1.1  mrg       for (i = 0; i < size; i++)
   1017      1.1  mrg 	{
   1018      1.1  mrg 	  ptrdiff_t array_offset_dst = 0;
   1019      1.1  mrg 	  ptrdiff_t stride = 1;
   1020      1.1  mrg 	  ptrdiff_t extent = 1;
   1021      1.1  mrg 	  for (j = 0; j < rank-1; j++)
   1022      1.1  mrg 	    {
   1023      1.1  mrg 	      array_offset_dst += ((i / (extent*stride))
   1024      1.1  mrg 				   % (dest->dim[j]._ubound
   1025      1.1  mrg 				      - dest->dim[j].lower_bound + 1))
   1026      1.1  mrg 				  * dest->dim[j]._stride;
   1027      1.1  mrg 	  extent = (dest->dim[j]._ubound - dest->dim[j].lower_bound + 1);
   1028      1.1  mrg           stride = dest->dim[j]._stride;
   1029      1.1  mrg 	    }
   1030      1.1  mrg 	  array_offset_dst += (i / extent) * dest->dim[rank-1]._stride;
   1031      1.1  mrg 	  void *dst = (void *)((char *) MEMTOK (token) + offset
   1032      1.1  mrg 		      + array_offset_dst*GFC_DESCRIPTOR_SIZE (dest));
   1033      1.1  mrg           void *sr = tmp + array_offset_sr;
   1034      1.1  mrg 	  if (GFC_DESCRIPTOR_TYPE (dest) == GFC_DESCRIPTOR_TYPE (src)
   1035      1.1  mrg 	      && dst_kind == src_kind)
   1036      1.1  mrg 	    {
   1037      1.1  mrg 	      memmove (dst, sr,
   1038      1.1  mrg 		       dst_size > src_size ? src_size : dst_size);
   1039      1.1  mrg 	      if (GFC_DESCRIPTOR_TYPE (dest) == BT_CHARACTER
   1040      1.1  mrg 		  && dst_size > src_size)
   1041      1.1  mrg 		{
   1042      1.1  mrg 		  if (dst_kind == 1)
   1043      1.1  mrg 		    memset ((void*)(char*) dst + src_size, ' ',
   1044      1.1  mrg 			    dst_size-src_size);
   1045      1.1  mrg 		  else /* dst_kind == 4.  */
   1046      1.1  mrg 		    for (k = src_size/4; k < dst_size/4; k++)
   1047      1.1  mrg 		      ((int32_t*) dst)[k] = (int32_t) ' ';
   1048      1.1  mrg 		}
   1049      1.1  mrg 	    }
   1050      1.1  mrg 	  else if (GFC_DESCRIPTOR_TYPE (dest) == BT_CHARACTER && dst_kind == 1)
   1051      1.1  mrg 	    assign_char1_from_char4 (dst_size, src_size, dst, sr);
   1052      1.1  mrg 	  else if (GFC_DESCRIPTOR_TYPE (dest) == BT_CHARACTER)
   1053      1.1  mrg 	    assign_char4_from_char1 (dst_size, src_size, dst, sr);
   1054      1.1  mrg 	  else
   1055      1.1  mrg 	    convert_type (dst, GFC_DESCRIPTOR_TYPE (dest), dst_kind,
   1056      1.1  mrg 			  sr, GFC_DESCRIPTOR_TYPE (src), src_kind, stat);
   1057      1.1  mrg           if (GFC_DESCRIPTOR_RANK (src))
   1058      1.1  mrg 	    array_offset_sr += src_size;
   1059      1.1  mrg 	}
   1060      1.1  mrg       free (tmp);
   1061      1.1  mrg       return;
   1062      1.1  mrg     }
   1063      1.1  mrg 
   1064      1.1  mrg   for (i = 0; i < size; i++)
   1065      1.1  mrg     {
   1066      1.1  mrg       ptrdiff_t array_offset_dst = 0;
   1067      1.1  mrg       ptrdiff_t stride = 1;
   1068      1.1  mrg       ptrdiff_t extent = 1;
   1069      1.1  mrg       for (j = 0; j < rank-1; j++)
   1070      1.1  mrg 	{
   1071      1.1  mrg 	  array_offset_dst += ((i / (extent*stride))
   1072      1.1  mrg 			       % (dest->dim[j]._ubound
   1073      1.1  mrg 				  - dest->dim[j].lower_bound + 1))
   1074      1.1  mrg 			      * dest->dim[j]._stride;
   1075      1.1  mrg 	  extent = (dest->dim[j]._ubound - dest->dim[j].lower_bound + 1);
   1076      1.1  mrg           stride = dest->dim[j]._stride;
   1077      1.1  mrg 	}
   1078      1.1  mrg       array_offset_dst += (i / extent) * dest->dim[rank-1]._stride;
   1079      1.1  mrg       void *dst = (void *)((char *) MEMTOK (token) + offset
   1080      1.1  mrg 			   + array_offset_dst*GFC_DESCRIPTOR_SIZE (dest));
   1081      1.1  mrg       void *sr;
   1082      1.1  mrg       if (GFC_DESCRIPTOR_RANK (src) != 0)
   1083      1.1  mrg 	{
   1084      1.1  mrg 	  ptrdiff_t array_offset_sr = 0;
   1085      1.1  mrg 	  stride = 1;
   1086      1.1  mrg 	  extent = 1;
   1087      1.1  mrg 	  for (j = 0; j < GFC_DESCRIPTOR_RANK (src)-1; j++)
   1088      1.1  mrg 	    {
   1089      1.1  mrg 	      array_offset_sr += ((i / (extent*stride))
   1090      1.1  mrg 				  % (src->dim[j]._ubound
   1091      1.1  mrg 				     - src->dim[j].lower_bound + 1))
   1092      1.1  mrg 				 * src->dim[j]._stride;
   1093      1.1  mrg 	      extent = (src->dim[j]._ubound - src->dim[j].lower_bound + 1);
   1094      1.1  mrg 	      stride = src->dim[j]._stride;
   1095      1.1  mrg 	    }
   1096      1.1  mrg 	  array_offset_sr += (i / extent) * src->dim[rank-1]._stride;
   1097      1.1  mrg 	  sr = (void *)((char *) src->base_addr
   1098      1.1  mrg 			+ array_offset_sr*GFC_DESCRIPTOR_SIZE (src));
   1099      1.1  mrg 	}
   1100      1.1  mrg       else
   1101      1.1  mrg 	sr = src->base_addr;
   1102      1.1  mrg 
   1103      1.1  mrg       if (GFC_DESCRIPTOR_TYPE (dest) == GFC_DESCRIPTOR_TYPE (src)
   1104      1.1  mrg 	  && dst_kind == src_kind)
   1105      1.1  mrg 	{
   1106      1.1  mrg 	  memmove (dst, sr,
   1107      1.1  mrg 		   dst_size > src_size ? src_size : dst_size);
   1108      1.1  mrg 	  if (GFC_DESCRIPTOR_TYPE (dest) == BT_CHARACTER && dst_size > src_size)
   1109      1.1  mrg 	    {
   1110      1.1  mrg 	      if (dst_kind == 1)
   1111      1.1  mrg 		memset ((void*)(char*) dst + src_size, ' ', dst_size-src_size);
   1112      1.1  mrg 	      else /* dst_kind == 4.  */
   1113      1.1  mrg 		for (k = src_size/4; k < dst_size/4; k++)
   1114      1.1  mrg 		  ((int32_t*) dst)[k] = (int32_t) ' ';
   1115      1.1  mrg 	    }
   1116      1.1  mrg 	}
   1117      1.1  mrg       else if (GFC_DESCRIPTOR_TYPE (dest) == BT_CHARACTER && dst_kind == 1)
   1118      1.1  mrg 	assign_char1_from_char4 (dst_size, src_size, dst, sr);
   1119      1.1  mrg       else if (GFC_DESCRIPTOR_TYPE (dest) == BT_CHARACTER)
   1120      1.1  mrg 	assign_char4_from_char1 (dst_size, src_size, dst, sr);
   1121      1.1  mrg       else
   1122      1.1  mrg 	convert_type (dst, GFC_DESCRIPTOR_TYPE (dest), dst_kind,
   1123      1.1  mrg 		      sr, GFC_DESCRIPTOR_TYPE (src), src_kind, stat);
   1124      1.1  mrg     }
   1125      1.1  mrg }
   1126      1.1  mrg 
   1127      1.1  mrg 
   1128      1.1  mrg void
   1129      1.1  mrg _gfortran_caf_sendget (caf_token_t dst_token, size_t dst_offset,
   1130      1.1  mrg 		       int dst_image_index, gfc_descriptor_t *dest,
   1131      1.1  mrg 		       caf_vector_t *dst_vector, caf_token_t src_token,
   1132      1.1  mrg 		       size_t src_offset,
   1133      1.1  mrg 		       int src_image_index __attribute__ ((unused)),
   1134      1.1  mrg 		       gfc_descriptor_t *src,
   1135      1.1  mrg 		       caf_vector_t *src_vector __attribute__ ((unused)),
   1136      1.1  mrg 		       int dst_kind, int src_kind, bool may_require_tmp)
   1137      1.1  mrg {
   1138      1.1  mrg   /* FIXME: Handle vector subscript of 'src_vector'.  */
   1139      1.1  mrg   /* For a single image, src->base_addr should be the same as src_token + offset
   1140      1.1  mrg      but to play save, we do it properly.  */
   1141      1.1  mrg   void *src_base = GFC_DESCRIPTOR_DATA (src);
   1142      1.1  mrg   GFC_DESCRIPTOR_DATA (src) = (void *) ((char *) MEMTOK (src_token)
   1143      1.1  mrg 					+ src_offset);
   1144      1.1  mrg   _gfortran_caf_send (dst_token, dst_offset, dst_image_index, dest, dst_vector,
   1145      1.1  mrg 		      src, dst_kind, src_kind, may_require_tmp, NULL);
   1146      1.1  mrg   GFC_DESCRIPTOR_DATA (src) = src_base;
   1147      1.1  mrg }
   1148      1.1  mrg 
   1149      1.1  mrg 
   1150      1.1  mrg /* Emitted when a theorectically unreachable part is reached.  */
   1151      1.1  mrg const char unreachable[] = "Fatal error: unreachable alternative found.\n";
   1152      1.1  mrg 
   1153      1.1  mrg 
   1154      1.1  mrg static void
   1155      1.1  mrg copy_data (void *ds, void *sr, int dst_type, int src_type,
   1156      1.1  mrg 	   int dst_kind, int src_kind, size_t dst_size, size_t src_size,
   1157      1.1  mrg 	   size_t num, int *stat)
   1158      1.1  mrg {
   1159      1.1  mrg   size_t k;
   1160      1.1  mrg   if (dst_type == src_type && dst_kind == src_kind)
   1161      1.1  mrg     {
   1162      1.1  mrg       memmove (ds, sr, (dst_size > src_size ? src_size : dst_size) * num);
   1163      1.1  mrg       if ((dst_type == BT_CHARACTER || src_type == BT_CHARACTER)
   1164      1.1  mrg 	  && dst_size > src_size)
   1165      1.1  mrg 	{
   1166      1.1  mrg 	  if (dst_kind == 1)
   1167      1.1  mrg 	    memset ((void*)(char*) ds + src_size, ' ', dst_size-src_size);
   1168      1.1  mrg 	  else /* dst_kind == 4.  */
   1169      1.1  mrg 	    for (k = src_size/4; k < dst_size/4; k++)
   1170      1.1  mrg 	      ((int32_t*) ds)[k] = (int32_t) ' ';
   1171      1.1  mrg 	}
   1172      1.1  mrg     }
   1173      1.1  mrg   else if (dst_type == BT_CHARACTER && dst_kind == 1)
   1174      1.1  mrg     assign_char1_from_char4 (dst_size, src_size, ds, sr);
   1175      1.1  mrg   else if (dst_type == BT_CHARACTER)
   1176      1.1  mrg     assign_char4_from_char1 (dst_size, src_size, ds, sr);
   1177      1.1  mrg   else
   1178      1.1  mrg     for (k = 0; k < num; ++k)
   1179      1.1  mrg       {
   1180      1.1  mrg 	convert_type (ds, dst_type, dst_kind, sr, src_type, src_kind, stat);
   1181      1.1  mrg 	ds += dst_size;
   1182      1.1  mrg 	sr += src_size;
   1183      1.1  mrg       }
   1184      1.1  mrg }
   1185      1.1  mrg 
   1186      1.1  mrg 
   1187      1.1  mrg #define COMPUTE_NUM_ITEMS(num, stride, lb, ub) \
   1188      1.1  mrg   do { \
   1189      1.1  mrg     index_type abs_stride = (stride) > 0 ? (stride) : -(stride); \
   1190      1.1  mrg     num = (stride) > 0 ? (ub) + 1 - (lb) : (lb) + 1 - (ub); \
   1191      1.1  mrg     if (num <= 0 || abs_stride < 1) return; \
   1192      1.1  mrg     num = (abs_stride > 1) ? (1 + (num - 1) / abs_stride) : num; \
   1193      1.1  mrg   } while (0)
   1194      1.1  mrg 
   1195      1.1  mrg 
   1196      1.1  mrg static void
   1197      1.1  mrg get_for_ref (caf_reference_t *ref, size_t *i, size_t *dst_index,
   1198      1.1  mrg 	     caf_single_token_t single_token, gfc_descriptor_t *dst,
   1199      1.1  mrg 	     gfc_descriptor_t *src, void *ds, void *sr,
   1200      1.1  mrg 	     int dst_kind, int src_kind, size_t dst_dim, size_t src_dim,
   1201      1.1  mrg 	     size_t num, int *stat, int src_type)
   1202      1.1  mrg {
   1203      1.1  mrg   ptrdiff_t extent_src = 1, array_offset_src = 0, stride_src;
   1204      1.1  mrg   size_t next_dst_dim;
   1205      1.1  mrg 
   1206      1.1  mrg   if (unlikely (ref == NULL))
   1207      1.1  mrg     /* May be we should issue an error here, because this case should not
   1208      1.1  mrg        occur.  */
   1209      1.1  mrg     return;
   1210      1.1  mrg 
   1211      1.1  mrg   if (ref->next == NULL)
   1212      1.1  mrg     {
   1213      1.1  mrg       size_t dst_size = GFC_DESCRIPTOR_SIZE (dst);
   1214      1.1  mrg       ptrdiff_t array_offset_dst = 0;;
   1215      1.1  mrg       size_t dst_rank = GFC_DESCRIPTOR_RANK (dst);
   1216      1.1  mrg 
   1217      1.1  mrg       switch (ref->type)
   1218      1.1  mrg 	{
   1219      1.1  mrg 	case CAF_REF_COMPONENT:
   1220      1.1  mrg 	  /* Because the token is always registered after the component, its
   1221      1.1  mrg 	     offset is always greater zero.  */
   1222      1.1  mrg 	  if (ref->u.c.caf_token_offset > 0)
   1223      1.1  mrg 	    /* Note, that sr is dereffed here.  */
   1224      1.1  mrg 	    copy_data (ds, *(void **)(sr + ref->u.c.offset),
   1225      1.1  mrg 		       GFC_DESCRIPTOR_TYPE (dst), src_type,
   1226      1.1  mrg 		       dst_kind, src_kind, dst_size, ref->item_size, 1, stat);
   1227      1.1  mrg 	  else
   1228      1.1  mrg 	    copy_data (ds, sr + ref->u.c.offset,
   1229      1.1  mrg 		       GFC_DESCRIPTOR_TYPE (dst), src_type,
   1230      1.1  mrg 		       dst_kind, src_kind, dst_size, ref->item_size, 1, stat);
   1231      1.1  mrg 	  ++(*i);
   1232      1.1  mrg 	  return;
   1233      1.1  mrg 	case CAF_REF_STATIC_ARRAY:
   1234      1.1  mrg 	  /* Intentionally fall through.  */
   1235      1.1  mrg 	case CAF_REF_ARRAY:
   1236      1.1  mrg 	  if (ref->u.a.mode[src_dim] == CAF_ARR_REF_NONE)
   1237      1.1  mrg 	    {
   1238      1.1  mrg 	      for (size_t d = 0; d < dst_rank; ++d)
   1239      1.1  mrg 		array_offset_dst += dst_index[d];
   1240      1.1  mrg 	      copy_data (ds + array_offset_dst * dst_size, sr,
   1241      1.1  mrg 			 GFC_DESCRIPTOR_TYPE (dst), src_type,
   1242      1.1  mrg 			 dst_kind, src_kind, dst_size, ref->item_size, num,
   1243      1.1  mrg 			 stat);
   1244      1.1  mrg 	      *i += num;
   1245      1.1  mrg 	      return;
   1246      1.1  mrg 	    }
   1247      1.1  mrg 	  break;
   1248      1.1  mrg 	default:
   1249      1.1  mrg 	  caf_runtime_error (unreachable);
   1250      1.1  mrg 	}
   1251      1.1  mrg     }
   1252      1.1  mrg 
   1253      1.1  mrg   switch (ref->type)
   1254      1.1  mrg     {
   1255      1.1  mrg     case CAF_REF_COMPONENT:
   1256      1.1  mrg       if (ref->u.c.caf_token_offset > 0)
   1257      1.1  mrg 	{
   1258      1.1  mrg 	  single_token = *(caf_single_token_t*)(sr + ref->u.c.caf_token_offset);
   1259      1.1  mrg 
   1260      1.1  mrg 	  if (ref->next && ref->next->type == CAF_REF_ARRAY)
   1261      1.1  mrg 	    src = single_token->desc;
   1262      1.1  mrg 	  else
   1263      1.1  mrg 	    src = NULL;
   1264      1.1  mrg 
   1265      1.1  mrg 	  if (ref->next && ref->next->type == CAF_REF_COMPONENT)
   1266      1.1  mrg 	    /* The currently ref'ed component was allocatabe (caf_token_offset
   1267      1.1  mrg 	       > 0) and the next ref is a component, too, then the new sr has to
   1268      1.1  mrg 	       be dereffed.  (static arrays cannot be allocatable or they
   1269      1.1  mrg 	       become an array with descriptor.  */
   1270      1.1  mrg 	    sr = *(void **)(sr + ref->u.c.offset);
   1271      1.1  mrg 	  else
   1272      1.1  mrg 	    sr += ref->u.c.offset;
   1273      1.1  mrg 
   1274      1.1  mrg 	  get_for_ref (ref->next, i, dst_index, single_token, dst, src,
   1275      1.1  mrg 		       ds, sr, dst_kind, src_kind, dst_dim, 0,
   1276      1.1  mrg 		       1, stat, src_type);
   1277      1.1  mrg 	}
   1278      1.1  mrg       else
   1279      1.1  mrg 	get_for_ref (ref->next, i, dst_index, single_token, dst,
   1280      1.1  mrg 		     (gfc_descriptor_t *)(sr + ref->u.c.offset), ds,
   1281      1.1  mrg 		     sr + ref->u.c.offset, dst_kind, src_kind, dst_dim, 0, 1,
   1282      1.1  mrg 		     stat, src_type);
   1283      1.1  mrg       return;
   1284      1.1  mrg     case CAF_REF_ARRAY:
   1285      1.1  mrg       if (ref->u.a.mode[src_dim] == CAF_ARR_REF_NONE)
   1286      1.1  mrg 	{
   1287      1.1  mrg 	  get_for_ref (ref->next, i, dst_index, single_token, dst,
   1288      1.1  mrg 		       src, ds, sr, dst_kind, src_kind,
   1289      1.1  mrg 		       dst_dim, 0, 1, stat, src_type);
   1290      1.1  mrg 	  return;
   1291      1.1  mrg 	}
   1292      1.1  mrg       /* Only when on the left most index switch the data pointer to
   1293      1.1  mrg 	 the array's data pointer.  */
   1294      1.1  mrg       if (src_dim == 0)
   1295      1.1  mrg 	sr = GFC_DESCRIPTOR_DATA (src);
   1296      1.1  mrg       switch (ref->u.a.mode[src_dim])
   1297      1.1  mrg 	{
   1298      1.1  mrg 	case CAF_ARR_REF_VECTOR:
   1299      1.1  mrg 	  extent_src = GFC_DIMENSION_EXTENT (src->dim[src_dim]);
   1300      1.1  mrg 	  array_offset_src = 0;
   1301      1.1  mrg 	  dst_index[dst_dim] = 0;
   1302      1.1  mrg 	  for (size_t idx = 0; idx < ref->u.a.dim[src_dim].v.nvec;
   1303      1.1  mrg 	       ++idx)
   1304      1.1  mrg 	    {
   1305      1.1  mrg #define KINDCASE(kind, type) case kind: \
   1306      1.1  mrg 	      array_offset_src = (((index_type) \
   1307      1.1  mrg 		  ((type *)ref->u.a.dim[src_dim].v.vector)[idx]) \
   1308      1.1  mrg 		  - GFC_DIMENSION_LBOUND (src->dim[src_dim])) \
   1309      1.1  mrg 		  * GFC_DIMENSION_STRIDE (src->dim[src_dim]); \
   1310      1.1  mrg 	      break
   1311      1.1  mrg 
   1312      1.1  mrg 	      switch (ref->u.a.dim[src_dim].v.kind)
   1313      1.1  mrg 		{
   1314      1.1  mrg 		KINDCASE (1, GFC_INTEGER_1);
   1315      1.1  mrg 		KINDCASE (2, GFC_INTEGER_2);
   1316      1.1  mrg 		KINDCASE (4, GFC_INTEGER_4);
   1317      1.1  mrg #ifdef HAVE_GFC_INTEGER_8
   1318      1.1  mrg 		KINDCASE (8, GFC_INTEGER_8);
   1319      1.1  mrg #endif
   1320      1.1  mrg #ifdef HAVE_GFC_INTEGER_16
   1321      1.1  mrg 		KINDCASE (16, GFC_INTEGER_16);
   1322      1.1  mrg #endif
   1323      1.1  mrg 		default:
   1324      1.1  mrg 		  caf_runtime_error (unreachable);
   1325      1.1  mrg 		  return;
   1326      1.1  mrg 		}
   1327      1.1  mrg #undef KINDCASE
   1328      1.1  mrg 
   1329      1.1  mrg 	      get_for_ref (ref, i, dst_index, single_token, dst, src,
   1330      1.1  mrg 			   ds, sr + array_offset_src * ref->item_size,
   1331      1.1  mrg 			   dst_kind, src_kind, dst_dim + 1, src_dim + 1,
   1332      1.1  mrg 			   1, stat, src_type);
   1333      1.1  mrg 	      dst_index[dst_dim]
   1334      1.1  mrg 		  += GFC_DIMENSION_STRIDE (dst->dim[dst_dim]);
   1335      1.1  mrg 	    }
   1336      1.1  mrg 	  return;
   1337      1.1  mrg 	case CAF_ARR_REF_FULL:
   1338      1.1  mrg 	  COMPUTE_NUM_ITEMS (extent_src,
   1339      1.1  mrg 			     ref->u.a.dim[src_dim].s.stride,
   1340      1.1  mrg 			     GFC_DIMENSION_LBOUND (src->dim[src_dim]),
   1341      1.1  mrg 			     GFC_DIMENSION_UBOUND (src->dim[src_dim]));
   1342      1.1  mrg 	  stride_src = src->dim[src_dim]._stride
   1343      1.1  mrg 	      * ref->u.a.dim[src_dim].s.stride;
   1344      1.1  mrg 	  array_offset_src = 0;
   1345      1.1  mrg 	  dst_index[dst_dim] = 0;
   1346      1.1  mrg 	  for (index_type idx = 0; idx < extent_src;
   1347      1.1  mrg 	       ++idx, array_offset_src += stride_src)
   1348      1.1  mrg 	    {
   1349      1.1  mrg 	      get_for_ref (ref, i, dst_index, single_token, dst, src,
   1350      1.1  mrg 			   ds, sr + array_offset_src * ref->item_size,
   1351      1.1  mrg 			   dst_kind, src_kind, dst_dim + 1, src_dim + 1,
   1352      1.1  mrg 			   1, stat, src_type);
   1353      1.1  mrg 	      dst_index[dst_dim]
   1354      1.1  mrg 		  += GFC_DIMENSION_STRIDE (dst->dim[dst_dim]);
   1355      1.1  mrg 	    }
   1356      1.1  mrg 	  return;
   1357      1.1  mrg 	case CAF_ARR_REF_RANGE:
   1358      1.1  mrg 	  COMPUTE_NUM_ITEMS (extent_src,
   1359      1.1  mrg 			     ref->u.a.dim[src_dim].s.stride,
   1360      1.1  mrg 			     ref->u.a.dim[src_dim].s.start,
   1361      1.1  mrg 			     ref->u.a.dim[src_dim].s.end);
   1362      1.1  mrg 	  array_offset_src = (ref->u.a.dim[src_dim].s.start
   1363      1.1  mrg 			      - GFC_DIMENSION_LBOUND (src->dim[src_dim]))
   1364      1.1  mrg 	      * GFC_DIMENSION_STRIDE (src->dim[src_dim]);
   1365      1.1  mrg 	  stride_src = GFC_DIMENSION_STRIDE (src->dim[src_dim])
   1366      1.1  mrg 	      * ref->u.a.dim[src_dim].s.stride;
   1367      1.1  mrg 	  dst_index[dst_dim] = 0;
   1368      1.1  mrg 	  /* Increase the dst_dim only, when the src_extent is greater one
   1369      1.1  mrg 	     or src and dst extent are both one.  Don't increase when the scalar
   1370      1.1  mrg 	     source is not present in the dst.  */
   1371      1.1  mrg 	  next_dst_dim = extent_src > 1
   1372      1.1  mrg 	      || (GFC_DIMENSION_EXTENT (dst->dim[dst_dim]) == 1
   1373      1.1  mrg 		  && extent_src == 1) ? (dst_dim + 1) : dst_dim;
   1374      1.1  mrg 	  for (index_type idx = 0; idx < extent_src; ++idx)
   1375      1.1  mrg 	    {
   1376      1.1  mrg 	      get_for_ref (ref, i, dst_index, single_token, dst, src,
   1377      1.1  mrg 			   ds, sr + array_offset_src * ref->item_size,
   1378      1.1  mrg 			   dst_kind, src_kind, next_dst_dim, src_dim + 1,
   1379      1.1  mrg 			   1, stat, src_type);
   1380      1.1  mrg 	      dst_index[dst_dim]
   1381      1.1  mrg 		  += GFC_DIMENSION_STRIDE (dst->dim[dst_dim]);
   1382      1.1  mrg 	      array_offset_src += stride_src;
   1383      1.1  mrg 	    }
   1384      1.1  mrg 	  return;
   1385      1.1  mrg 	case CAF_ARR_REF_SINGLE:
   1386      1.1  mrg 	  array_offset_src = (ref->u.a.dim[src_dim].s.start
   1387      1.1  mrg 			      - src->dim[src_dim].lower_bound)
   1388      1.1  mrg 	      * GFC_DIMENSION_STRIDE (src->dim[src_dim]);
   1389      1.1  mrg 	  dst_index[dst_dim] = 0;
   1390      1.1  mrg 	  get_for_ref (ref, i, dst_index, single_token, dst, src, ds,
   1391      1.1  mrg 		       sr + array_offset_src * ref->item_size,
   1392      1.1  mrg 		       dst_kind, src_kind, dst_dim, src_dim + 1, 1,
   1393      1.1  mrg 		       stat, src_type);
   1394      1.1  mrg 	  return;
   1395      1.1  mrg 	case CAF_ARR_REF_OPEN_END:
   1396      1.1  mrg 	  COMPUTE_NUM_ITEMS (extent_src,
   1397      1.1  mrg 			     ref->u.a.dim[src_dim].s.stride,
   1398      1.1  mrg 			     ref->u.a.dim[src_dim].s.start,
   1399      1.1  mrg 			     GFC_DIMENSION_UBOUND (src->dim[src_dim]));
   1400      1.1  mrg 	  stride_src = GFC_DIMENSION_STRIDE (src->dim[src_dim])
   1401      1.1  mrg 	      * ref->u.a.dim[src_dim].s.stride;
   1402      1.1  mrg 	  array_offset_src = (ref->u.a.dim[src_dim].s.start
   1403      1.1  mrg 			      - GFC_DIMENSION_LBOUND (src->dim[src_dim]))
   1404      1.1  mrg 	      * GFC_DIMENSION_STRIDE (src->dim[src_dim]);
   1405      1.1  mrg 	  dst_index[dst_dim] = 0;
   1406      1.1  mrg 	  for (index_type idx = 0; idx < extent_src; ++idx)
   1407      1.1  mrg 	    {
   1408      1.1  mrg 	      get_for_ref (ref, i, dst_index, single_token, dst, src,
   1409      1.1  mrg 			   ds, sr + array_offset_src * ref->item_size,
   1410      1.1  mrg 			   dst_kind, src_kind, dst_dim + 1, src_dim + 1,
   1411      1.1  mrg 			   1, stat, src_type);
   1412      1.1  mrg 	      dst_index[dst_dim]
   1413      1.1  mrg 		  += GFC_DIMENSION_STRIDE (dst->dim[dst_dim]);
   1414      1.1  mrg 	      array_offset_src += stride_src;
   1415      1.1  mrg 	    }
   1416      1.1  mrg 	  return;
   1417      1.1  mrg 	case CAF_ARR_REF_OPEN_START:
   1418      1.1  mrg 	  COMPUTE_NUM_ITEMS (extent_src,
   1419      1.1  mrg 			     ref->u.a.dim[src_dim].s.stride,
   1420      1.1  mrg 			     GFC_DIMENSION_LBOUND (src->dim[src_dim]),
   1421      1.1  mrg 			     ref->u.a.dim[src_dim].s.end);
   1422      1.1  mrg 	  stride_src = GFC_DIMENSION_STRIDE (src->dim[src_dim])
   1423      1.1  mrg 	      * ref->u.a.dim[src_dim].s.stride;
   1424      1.1  mrg 	  array_offset_src = 0;
   1425      1.1  mrg 	  dst_index[dst_dim] = 0;
   1426      1.1  mrg 	  for (index_type idx = 0; idx < extent_src; ++idx)
   1427      1.1  mrg 	    {
   1428      1.1  mrg 	      get_for_ref (ref, i, dst_index, single_token, dst, src,
   1429      1.1  mrg 			   ds, sr + array_offset_src * ref->item_size,
   1430      1.1  mrg 			   dst_kind, src_kind, dst_dim + 1, src_dim + 1,
   1431      1.1  mrg 			   1, stat, src_type);
   1432      1.1  mrg 	      dst_index[dst_dim]
   1433      1.1  mrg 		  += GFC_DIMENSION_STRIDE (dst->dim[dst_dim]);
   1434      1.1  mrg 	      array_offset_src += stride_src;
   1435      1.1  mrg 	    }
   1436      1.1  mrg 	  return;
   1437      1.1  mrg 	default:
   1438      1.1  mrg 	  caf_runtime_error (unreachable);
   1439      1.1  mrg 	}
   1440      1.1  mrg       return;
   1441      1.1  mrg     case CAF_REF_STATIC_ARRAY:
   1442      1.1  mrg       if (ref->u.a.mode[src_dim] == CAF_ARR_REF_NONE)
   1443      1.1  mrg 	{
   1444      1.1  mrg 	  get_for_ref (ref->next, i, dst_index, single_token, dst,
   1445      1.1  mrg 		       NULL, ds, sr, dst_kind, src_kind,
   1446      1.1  mrg 		       dst_dim, 0, 1, stat, src_type);
   1447      1.1  mrg 	  return;
   1448      1.1  mrg 	}
   1449      1.1  mrg       switch (ref->u.a.mode[src_dim])
   1450      1.1  mrg 	{
   1451      1.1  mrg 	case CAF_ARR_REF_VECTOR:
   1452      1.1  mrg 	  array_offset_src = 0;
   1453      1.1  mrg 	  dst_index[dst_dim] = 0;
   1454      1.1  mrg 	  for (size_t idx = 0; idx < ref->u.a.dim[src_dim].v.nvec;
   1455      1.1  mrg 	       ++idx)
   1456      1.1  mrg 	    {
   1457      1.1  mrg #define KINDCASE(kind, type) case kind: \
   1458      1.1  mrg 	     array_offset_src = ((type *)ref->u.a.dim[src_dim].v.vector)[idx]; \
   1459      1.1  mrg 	      break
   1460      1.1  mrg 
   1461      1.1  mrg 	      switch (ref->u.a.dim[src_dim].v.kind)
   1462      1.1  mrg 		{
   1463      1.1  mrg 		KINDCASE (1, GFC_INTEGER_1);
   1464      1.1  mrg 		KINDCASE (2, GFC_INTEGER_2);
   1465      1.1  mrg 		KINDCASE (4, GFC_INTEGER_4);
   1466      1.1  mrg #ifdef HAVE_GFC_INTEGER_8
   1467      1.1  mrg 		KINDCASE (8, GFC_INTEGER_8);
   1468      1.1  mrg #endif
   1469      1.1  mrg #ifdef HAVE_GFC_INTEGER_16
   1470      1.1  mrg 		KINDCASE (16, GFC_INTEGER_16);
   1471      1.1  mrg #endif
   1472      1.1  mrg 		default:
   1473      1.1  mrg 		  caf_runtime_error (unreachable);
   1474      1.1  mrg 		  return;
   1475      1.1  mrg 		}
   1476      1.1  mrg #undef KINDCASE
   1477      1.1  mrg 
   1478      1.1  mrg 	      get_for_ref (ref, i, dst_index, single_token, dst, NULL,
   1479      1.1  mrg 			   ds, sr + array_offset_src * ref->item_size,
   1480      1.1  mrg 			   dst_kind, src_kind, dst_dim + 1, src_dim + 1,
   1481      1.1  mrg 			   1, stat, src_type);
   1482      1.1  mrg 	      dst_index[dst_dim]
   1483      1.1  mrg 		  += GFC_DIMENSION_STRIDE (dst->dim[dst_dim]);
   1484      1.1  mrg 	    }
   1485      1.1  mrg 	  return;
   1486      1.1  mrg 	case CAF_ARR_REF_FULL:
   1487      1.1  mrg 	  dst_index[dst_dim] = 0;
   1488      1.1  mrg 	  for (array_offset_src = 0 ;
   1489      1.1  mrg 	       array_offset_src <= ref->u.a.dim[src_dim].s.end;
   1490      1.1  mrg 	       array_offset_src += ref->u.a.dim[src_dim].s.stride)
   1491      1.1  mrg 	    {
   1492      1.1  mrg 	      get_for_ref (ref, i, dst_index, single_token, dst, NULL,
   1493      1.1  mrg 			   ds, sr + array_offset_src * ref->item_size,
   1494      1.1  mrg 			   dst_kind, src_kind, dst_dim + 1, src_dim + 1,
   1495      1.1  mrg 			   1, stat, src_type);
   1496      1.1  mrg 	      dst_index[dst_dim]
   1497      1.1  mrg 		  += GFC_DIMENSION_STRIDE (dst->dim[dst_dim]);
   1498      1.1  mrg 	    }
   1499      1.1  mrg 	  return;
   1500      1.1  mrg 	case CAF_ARR_REF_RANGE:
   1501      1.1  mrg 	  COMPUTE_NUM_ITEMS (extent_src,
   1502      1.1  mrg 			     ref->u.a.dim[src_dim].s.stride,
   1503      1.1  mrg 			     ref->u.a.dim[src_dim].s.start,
   1504      1.1  mrg 			     ref->u.a.dim[src_dim].s.end);
   1505      1.1  mrg 	  array_offset_src = ref->u.a.dim[src_dim].s.start;
   1506      1.1  mrg 	  dst_index[dst_dim] = 0;
   1507      1.1  mrg 	  for (index_type idx = 0; idx < extent_src; ++idx)
   1508      1.1  mrg 	    {
   1509      1.1  mrg 	      get_for_ref (ref, i, dst_index, single_token, dst, NULL,
   1510      1.1  mrg 			   ds, sr + array_offset_src * ref->item_size,
   1511      1.1  mrg 			   dst_kind, src_kind, dst_dim + 1, src_dim + 1,
   1512      1.1  mrg 			   1, stat, src_type);
   1513      1.1  mrg 	      dst_index[dst_dim]
   1514      1.1  mrg 		  += GFC_DIMENSION_STRIDE (dst->dim[dst_dim]);
   1515      1.1  mrg 	      array_offset_src += ref->u.a.dim[src_dim].s.stride;
   1516      1.1  mrg 	    }
   1517      1.1  mrg 	  return;
   1518      1.1  mrg 	case CAF_ARR_REF_SINGLE:
   1519      1.1  mrg 	  array_offset_src = ref->u.a.dim[src_dim].s.start;
   1520      1.1  mrg 	  get_for_ref (ref, i, dst_index, single_token, dst, NULL, ds,
   1521      1.1  mrg 		       sr + array_offset_src * ref->item_size,
   1522      1.1  mrg 		       dst_kind, src_kind, dst_dim, src_dim + 1, 1,
   1523      1.1  mrg 		       stat, src_type);
   1524      1.1  mrg 	  return;
   1525      1.1  mrg 	/* The OPEN_* are mapped to a RANGE and therefore cannot occur.  */
   1526      1.1  mrg 	case CAF_ARR_REF_OPEN_END:
   1527      1.1  mrg 	case CAF_ARR_REF_OPEN_START:
   1528      1.1  mrg 	default:
   1529      1.1  mrg 	  caf_runtime_error (unreachable);
   1530      1.1  mrg 	}
   1531      1.1  mrg       return;
   1532      1.1  mrg     default:
   1533      1.1  mrg       caf_runtime_error (unreachable);
   1534      1.1  mrg     }
   1535      1.1  mrg }
   1536      1.1  mrg 
   1537      1.1  mrg 
   1538      1.1  mrg void
   1539      1.1  mrg _gfortran_caf_get_by_ref (caf_token_t token,
   1540      1.1  mrg 			  int image_index __attribute__ ((unused)),
   1541      1.1  mrg 			  gfc_descriptor_t *dst, caf_reference_t *refs,
   1542      1.1  mrg 			  int dst_kind, int src_kind,
   1543      1.1  mrg 			  bool may_require_tmp __attribute__ ((unused)),
   1544      1.1  mrg 			  bool dst_reallocatable, int *stat,
   1545      1.1  mrg 			  int src_type)
   1546      1.1  mrg {
   1547      1.1  mrg   const char vecrefunknownkind[] = "libcaf_single::caf_get_by_ref(): "
   1548      1.1  mrg 				   "unknown kind in vector-ref.\n";
   1549      1.1  mrg   const char unknownreftype[] = "libcaf_single::caf_get_by_ref(): "
   1550      1.1  mrg 				"unknown reference type.\n";
   1551      1.1  mrg   const char unknownarrreftype[] = "libcaf_single::caf_get_by_ref(): "
   1552      1.1  mrg 				   "unknown array reference type.\n";
   1553      1.1  mrg   const char rankoutofrange[] = "libcaf_single::caf_get_by_ref(): "
   1554      1.1  mrg 				"rank out of range.\n";
   1555      1.1  mrg   const char extentoutofrange[] = "libcaf_single::caf_get_by_ref(): "
   1556      1.1  mrg 				  "extent out of range.\n";
   1557      1.1  mrg   const char cannotallocdst[] = "libcaf_single::caf_get_by_ref(): "
   1558      1.1  mrg 				"cannot allocate memory.\n";
   1559      1.1  mrg   const char nonallocextentmismatch[] = "libcaf_single::caf_get_by_ref(): "
   1560      1.1  mrg       "extent of non-allocatable arrays mismatch (%lu != %lu).\n";
   1561      1.1  mrg   const char doublearrayref[] = "libcaf_single::caf_get_by_ref(): "
   1562      1.1  mrg       "two or more array part references are not supported.\n";
   1563      1.1  mrg   size_t size, i;
   1564      1.1  mrg   size_t dst_index[GFC_MAX_DIMENSIONS];
   1565      1.1  mrg   int dst_rank = GFC_DESCRIPTOR_RANK (dst);
   1566      1.1  mrg   int dst_cur_dim = 0;
   1567      1.1  mrg   size_t src_size = 0;
   1568      1.1  mrg   caf_single_token_t single_token = TOKEN (token);
   1569      1.1  mrg   void *memptr = single_token->memptr;
   1570      1.1  mrg   gfc_descriptor_t *src = single_token->desc;
   1571      1.1  mrg   caf_reference_t *riter = refs;
   1572      1.1  mrg   long delta;
   1573      1.1  mrg   /* Reallocation of dst.data is needed (e.g., array to small).  */
   1574      1.1  mrg   bool realloc_needed;
   1575      1.1  mrg   /* Reallocation of dst.data is required, because data is not alloced at
   1576      1.1  mrg      all.  */
   1577      1.1  mrg   bool realloc_required;
   1578      1.1  mrg   bool extent_mismatch = false;
   1579      1.1  mrg   /* Set when the first non-scalar array reference is encountered.  */
   1580      1.1  mrg   bool in_array_ref = false;
   1581      1.1  mrg   bool array_extent_fixed = false;
   1582      1.1  mrg   realloc_needed = realloc_required = GFC_DESCRIPTOR_DATA (dst) == NULL;
   1583      1.1  mrg 
   1584      1.1  mrg   assert (!realloc_needed || dst_reallocatable);
   1585      1.1  mrg 
   1586      1.1  mrg   if (stat)
   1587      1.1  mrg     *stat = 0;
   1588      1.1  mrg 
   1589      1.1  mrg   /* Compute the size of the result.  In the beginning size just counts the
   1590      1.1  mrg      number of elements.  */
   1591      1.1  mrg   size = 1;
   1592      1.1  mrg   while (riter)
   1593      1.1  mrg     {
   1594      1.1  mrg       switch (riter->type)
   1595      1.1  mrg 	{
   1596      1.1  mrg 	case CAF_REF_COMPONENT:
   1597      1.1  mrg 	  if (riter->u.c.caf_token_offset)
   1598      1.1  mrg 	    {
   1599      1.1  mrg 	      single_token = *(caf_single_token_t*)
   1600      1.1  mrg 					 (memptr + riter->u.c.caf_token_offset);
   1601      1.1  mrg 	      memptr = single_token->memptr;
   1602      1.1  mrg 	      src = single_token->desc;
   1603      1.1  mrg 	    }
   1604      1.1  mrg 	  else
   1605      1.1  mrg 	    {
   1606      1.1  mrg 	      memptr += riter->u.c.offset;
   1607      1.1  mrg 	      /* When the next ref is an array ref, assume there is an
   1608      1.1  mrg 		 array descriptor at memptr.  Note, static arrays do not have
   1609      1.1  mrg 		 a descriptor.  */
   1610      1.1  mrg 	      if (riter->next && riter->next->type == CAF_REF_ARRAY)
   1611      1.1  mrg 		src = (gfc_descriptor_t *)memptr;
   1612      1.1  mrg 	      else
   1613      1.1  mrg 		src = NULL;
   1614      1.1  mrg 	    }
   1615      1.1  mrg 	  break;
   1616      1.1  mrg 	case CAF_REF_ARRAY:
   1617      1.1  mrg 	  for (i = 0; riter->u.a.mode[i] != CAF_ARR_REF_NONE; ++i)
   1618      1.1  mrg 	    {
   1619      1.1  mrg 	      switch (riter->u.a.mode[i])
   1620      1.1  mrg 		{
   1621      1.1  mrg 		case CAF_ARR_REF_VECTOR:
   1622      1.1  mrg 		  delta = riter->u.a.dim[i].v.nvec;
   1623      1.1  mrg #define KINDCASE(kind, type) case kind: \
   1624      1.1  mrg 		    memptr += (((index_type) \
   1625      1.1  mrg 			((type *)riter->u.a.dim[i].v.vector)[0]) \
   1626      1.1  mrg 			- GFC_DIMENSION_LBOUND (src->dim[i])) \
   1627      1.1  mrg 			* GFC_DIMENSION_STRIDE (src->dim[i]) \
   1628      1.1  mrg 			* riter->item_size; \
   1629      1.1  mrg 		    break
   1630      1.1  mrg 
   1631      1.1  mrg 		  switch (riter->u.a.dim[i].v.kind)
   1632      1.1  mrg 		    {
   1633      1.1  mrg 		    KINDCASE (1, GFC_INTEGER_1);
   1634      1.1  mrg 		    KINDCASE (2, GFC_INTEGER_2);
   1635      1.1  mrg 		    KINDCASE (4, GFC_INTEGER_4);
   1636      1.1  mrg #ifdef HAVE_GFC_INTEGER_8
   1637      1.1  mrg 		    KINDCASE (8, GFC_INTEGER_8);
   1638      1.1  mrg #endif
   1639      1.1  mrg #ifdef HAVE_GFC_INTEGER_16
   1640      1.1  mrg 		    KINDCASE (16, GFC_INTEGER_16);
   1641      1.1  mrg #endif
   1642      1.1  mrg 		    default:
   1643      1.1  mrg 		      caf_internal_error (vecrefunknownkind, stat, NULL, 0);
   1644      1.1  mrg 		      return;
   1645      1.1  mrg 		    }
   1646      1.1  mrg #undef KINDCASE
   1647      1.1  mrg 		  break;
   1648      1.1  mrg 		case CAF_ARR_REF_FULL:
   1649      1.1  mrg 		  COMPUTE_NUM_ITEMS (delta,
   1650      1.1  mrg 				     riter->u.a.dim[i].s.stride,
   1651      1.1  mrg 				     GFC_DIMENSION_LBOUND (src->dim[i]),
   1652      1.1  mrg 				     GFC_DIMENSION_UBOUND (src->dim[i]));
   1653      1.1  mrg 		  /* The memptr stays unchanged when ref'ing the first element
   1654      1.1  mrg 		     in a dimension.  */
   1655      1.1  mrg 		  break;
   1656      1.1  mrg 		case CAF_ARR_REF_RANGE:
   1657      1.1  mrg 		  COMPUTE_NUM_ITEMS (delta,
   1658      1.1  mrg 				     riter->u.a.dim[i].s.stride,
   1659      1.1  mrg 				     riter->u.a.dim[i].s.start,
   1660      1.1  mrg 				     riter->u.a.dim[i].s.end);
   1661      1.1  mrg 		  memptr += (riter->u.a.dim[i].s.start
   1662      1.1  mrg 			     - GFC_DIMENSION_LBOUND (src->dim[i]))
   1663      1.1  mrg 		      * GFC_DIMENSION_STRIDE (src->dim[i])
   1664      1.1  mrg 		      * riter->item_size;
   1665      1.1  mrg 		  break;
   1666      1.1  mrg 		case CAF_ARR_REF_SINGLE:
   1667      1.1  mrg 		  delta = 1;
   1668      1.1  mrg 		  memptr += (riter->u.a.dim[i].s.start
   1669      1.1  mrg 			     - GFC_DIMENSION_LBOUND (src->dim[i]))
   1670      1.1  mrg 		      * GFC_DIMENSION_STRIDE (src->dim[i])
   1671      1.1  mrg 		      * riter->item_size;
   1672      1.1  mrg 		  break;
   1673      1.1  mrg 		case CAF_ARR_REF_OPEN_END:
   1674      1.1  mrg 		  COMPUTE_NUM_ITEMS (delta,
   1675      1.1  mrg 				     riter->u.a.dim[i].s.stride,
   1676      1.1  mrg 				     riter->u.a.dim[i].s.start,
   1677      1.1  mrg 				     GFC_DIMENSION_UBOUND (src->dim[i]));
   1678      1.1  mrg 		  memptr += (riter->u.a.dim[i].s.start
   1679      1.1  mrg 			     - GFC_DIMENSION_LBOUND (src->dim[i]))
   1680      1.1  mrg 		      * GFC_DIMENSION_STRIDE (src->dim[i])
   1681      1.1  mrg 		      * riter->item_size;
   1682      1.1  mrg 		  break;
   1683      1.1  mrg 		case CAF_ARR_REF_OPEN_START:
   1684      1.1  mrg 		  COMPUTE_NUM_ITEMS (delta,
   1685      1.1  mrg 				     riter->u.a.dim[i].s.stride,
   1686      1.1  mrg 				     GFC_DIMENSION_LBOUND (src->dim[i]),
   1687      1.1  mrg 				     riter->u.a.dim[i].s.end);
   1688      1.1  mrg 		  /* The memptr stays unchanged when ref'ing the first element
   1689      1.1  mrg 		     in a dimension.  */
   1690      1.1  mrg 		  break;
   1691      1.1  mrg 		default:
   1692      1.1  mrg 		  caf_internal_error (unknownarrreftype, stat, NULL, 0);
   1693      1.1  mrg 		  return;
   1694      1.1  mrg 		}
   1695      1.1  mrg 	      if (delta <= 0)
   1696      1.1  mrg 		return;
   1697      1.1  mrg 	      /* Check the various properties of the destination array.
   1698      1.1  mrg 		 Is an array expected and present?  */
   1699      1.1  mrg 	      if (delta > 1 && dst_rank == 0)
   1700      1.1  mrg 		{
   1701      1.1  mrg 		  /* No, an array is required, but not provided.  */
   1702      1.1  mrg 		  caf_internal_error (extentoutofrange, stat, NULL, 0);
   1703      1.1  mrg 		  return;
   1704      1.1  mrg 		}
   1705      1.1  mrg 	      /* Special mode when called by __caf_sendget_by_ref ().  */
   1706      1.1  mrg 	      if (dst_rank == -1 && GFC_DESCRIPTOR_DATA (dst) == NULL)
   1707      1.1  mrg 		{
   1708      1.1  mrg 		  dst_rank = dst_cur_dim + 1;
   1709      1.1  mrg 		  GFC_DESCRIPTOR_RANK (dst) = dst_rank;
   1710      1.1  mrg 		  GFC_DESCRIPTOR_SIZE (dst) = dst_kind;
   1711      1.1  mrg 		}
   1712      1.1  mrg 	      /* When dst is an array.  */
   1713      1.1  mrg 	      if (dst_rank > 0)
   1714      1.1  mrg 		{
   1715      1.1  mrg 		  /* Check that dst_cur_dim is valid for dst.  Can be
   1716      1.1  mrg 		     superceeded only by scalar data.  */
   1717      1.1  mrg 		  if (dst_cur_dim >= dst_rank && delta != 1)
   1718      1.1  mrg 		    {
   1719      1.1  mrg 		      caf_internal_error (rankoutofrange, stat, NULL, 0);
   1720      1.1  mrg 		      return;
   1721      1.1  mrg 		    }
   1722      1.1  mrg 		  /* Do further checks, when the source is not scalar.  */
   1723      1.1  mrg 		  else if (delta != 1)
   1724      1.1  mrg 		    {
   1725      1.1  mrg 		      /* Check that the extent is not scalar and we are not in
   1726      1.1  mrg 			 an array ref for the dst side.  */
   1727      1.1  mrg 		      if (!in_array_ref)
   1728      1.1  mrg 			{
   1729      1.1  mrg 			  /* Check that this is the non-scalar extent.  */
   1730      1.1  mrg 			  if (!array_extent_fixed)
   1731      1.1  mrg 			    {
   1732      1.1  mrg 			      /* In an array extent now.  */
   1733      1.1  mrg 			      in_array_ref = true;
   1734      1.1  mrg 			      /* Check that we haven't skipped any scalar
   1735      1.1  mrg 				 dimensions yet and that the dst is
   1736      1.1  mrg 				 compatible.  */
   1737      1.1  mrg 			      if (i > 0
   1738      1.1  mrg 				  && dst_rank == GFC_DESCRIPTOR_RANK (src))
   1739      1.1  mrg 				{
   1740      1.1  mrg 				  if (dst_reallocatable)
   1741      1.1  mrg 				    {
   1742      1.1  mrg 				      /* Dst is reallocatable, which means that
   1743      1.1  mrg 					 the bounds are not set.  Set them.  */
   1744      1.1  mrg 				      for (dst_cur_dim= 0; dst_cur_dim < (int)i;
   1745      1.1  mrg 					   ++dst_cur_dim)
   1746      1.1  mrg 				       GFC_DIMENSION_SET (dst->dim[dst_cur_dim],
   1747      1.1  mrg 							  1, 1, 1);
   1748      1.1  mrg 				    }
   1749      1.1  mrg 				  else
   1750      1.1  mrg 				    dst_cur_dim = i;
   1751      1.1  mrg 				}
   1752      1.1  mrg 			      /* Else press thumbs, that there are enough
   1753      1.1  mrg 				 dimensional refs to come.  Checked below.  */
   1754      1.1  mrg 			    }
   1755      1.1  mrg 			  else
   1756      1.1  mrg 			    {
   1757      1.1  mrg 			      caf_internal_error (doublearrayref, stat, NULL,
   1758      1.1  mrg 						  0);
   1759      1.1  mrg 			      return;
   1760      1.1  mrg 			    }
   1761      1.1  mrg 			}
   1762      1.1  mrg 		      /* When the realloc is required, then no extent may have
   1763      1.1  mrg 			 been set.  */
   1764      1.1  mrg 		      extent_mismatch = realloc_required
   1765      1.1  mrg 			  || GFC_DESCRIPTOR_EXTENT (dst, dst_cur_dim) != delta;
   1766      1.1  mrg 		      /* When it already known, that a realloc is needed or
   1767      1.1  mrg 			 the extent does not match the needed one.  */
   1768      1.1  mrg 		      if (realloc_required || realloc_needed
   1769      1.1  mrg 			  || extent_mismatch)
   1770      1.1  mrg 			{
   1771      1.1  mrg 			  /* Check whether dst is reallocatable.  */
   1772      1.1  mrg 			  if (unlikely (!dst_reallocatable))
   1773      1.1  mrg 			    {
   1774      1.1  mrg 			      caf_internal_error (nonallocextentmismatch, stat,
   1775      1.1  mrg 						  NULL, 0, delta,
   1776      1.1  mrg 						  GFC_DESCRIPTOR_EXTENT (dst,
   1777      1.1  mrg 								  dst_cur_dim));
   1778      1.1  mrg 			      return;
   1779      1.1  mrg 			    }
   1780      1.1  mrg 			  /* Only report an error, when the extent needs to be
   1781      1.1  mrg 			     modified, which is not allowed.  */
   1782      1.1  mrg 			  else if (!dst_reallocatable && extent_mismatch)
   1783      1.1  mrg 			    {
   1784      1.1  mrg 			      caf_internal_error (extentoutofrange, stat, NULL,
   1785      1.1  mrg 						  0);
   1786      1.1  mrg 			      return;
   1787      1.1  mrg 			    }
   1788      1.1  mrg 			  realloc_needed = true;
   1789      1.1  mrg 			}
   1790      1.1  mrg 		      /* Only change the extent when it does not match.  This is
   1791      1.1  mrg 			 to prevent resetting given array bounds.  */
   1792      1.1  mrg 		      if (extent_mismatch)
   1793      1.1  mrg 			GFC_DIMENSION_SET (dst->dim[dst_cur_dim], 1, delta,
   1794      1.1  mrg 					   size);
   1795      1.1  mrg 		    }
   1796      1.1  mrg 
   1797      1.1  mrg 		  /* Only increase the dim counter, when in an array ref.  */
   1798      1.1  mrg 		  if (in_array_ref && dst_cur_dim < dst_rank)
   1799      1.1  mrg 		    ++dst_cur_dim;
   1800      1.1  mrg 		}
   1801      1.1  mrg 	      size *= (index_type)delta;
   1802      1.1  mrg 	    }
   1803      1.1  mrg 	  if (in_array_ref)
   1804      1.1  mrg 	    {
   1805      1.1  mrg 	      array_extent_fixed = true;
   1806      1.1  mrg 	      in_array_ref = false;
   1807      1.1  mrg 	      /* Check, if we got less dimensional refs than the rank of dst
   1808      1.1  mrg 		 expects.  */
   1809      1.1  mrg 	      assert (dst_cur_dim == GFC_DESCRIPTOR_RANK (dst));
   1810      1.1  mrg 	    }
   1811      1.1  mrg 	  break;
   1812      1.1  mrg 	case CAF_REF_STATIC_ARRAY:
   1813      1.1  mrg 	  for (i = 0; riter->u.a.mode[i] != CAF_ARR_REF_NONE; ++i)
   1814      1.1  mrg 	    {
   1815      1.1  mrg 	      switch (riter->u.a.mode[i])
   1816      1.1  mrg 		{
   1817      1.1  mrg 		case CAF_ARR_REF_VECTOR:
   1818      1.1  mrg 		  delta = riter->u.a.dim[i].v.nvec;
   1819      1.1  mrg #define KINDCASE(kind, type) case kind: \
   1820      1.1  mrg 		    memptr += ((type *)riter->u.a.dim[i].v.vector)[0] \
   1821      1.1  mrg 			* riter->item_size; \
   1822      1.1  mrg 		    break
   1823      1.1  mrg 
   1824      1.1  mrg 		  switch (riter->u.a.dim[i].v.kind)
   1825      1.1  mrg 		    {
   1826      1.1  mrg 		    KINDCASE (1, GFC_INTEGER_1);
   1827      1.1  mrg 		    KINDCASE (2, GFC_INTEGER_2);
   1828      1.1  mrg 		    KINDCASE (4, GFC_INTEGER_4);
   1829      1.1  mrg #ifdef HAVE_GFC_INTEGER_8
   1830      1.1  mrg 		    KINDCASE (8, GFC_INTEGER_8);
   1831      1.1  mrg #endif
   1832      1.1  mrg #ifdef HAVE_GFC_INTEGER_16
   1833      1.1  mrg 		    KINDCASE (16, GFC_INTEGER_16);
   1834      1.1  mrg #endif
   1835      1.1  mrg 		    default:
   1836      1.1  mrg 		      caf_internal_error (vecrefunknownkind, stat, NULL, 0);
   1837      1.1  mrg 		      return;
   1838      1.1  mrg 		    }
   1839      1.1  mrg #undef KINDCASE
   1840      1.1  mrg 		  break;
   1841      1.1  mrg 		case CAF_ARR_REF_FULL:
   1842      1.1  mrg 		  delta = riter->u.a.dim[i].s.end / riter->u.a.dim[i].s.stride
   1843      1.1  mrg 		      + 1;
   1844      1.1  mrg 		  /* The memptr stays unchanged when ref'ing the first element
   1845      1.1  mrg 		     in a dimension.  */
   1846      1.1  mrg 		  break;
   1847      1.1  mrg 		case CAF_ARR_REF_RANGE:
   1848      1.1  mrg 		  COMPUTE_NUM_ITEMS (delta,
   1849      1.1  mrg 				     riter->u.a.dim[i].s.stride,
   1850      1.1  mrg 				     riter->u.a.dim[i].s.start,
   1851      1.1  mrg 				     riter->u.a.dim[i].s.end);
   1852      1.1  mrg 		  memptr += riter->u.a.dim[i].s.start
   1853      1.1  mrg 		      * riter->u.a.dim[i].s.stride
   1854      1.1  mrg 		      * riter->item_size;
   1855      1.1  mrg 		  break;
   1856      1.1  mrg 		case CAF_ARR_REF_SINGLE:
   1857      1.1  mrg 		  delta = 1;
   1858      1.1  mrg 		  memptr += riter->u.a.dim[i].s.start
   1859      1.1  mrg 		      * riter->u.a.dim[i].s.stride
   1860      1.1  mrg 		      * riter->item_size;
   1861      1.1  mrg 		  break;
   1862      1.1  mrg 		case CAF_ARR_REF_OPEN_END:
   1863      1.1  mrg 		  /* This and OPEN_START are mapped to a RANGE and therefore
   1864      1.1  mrg 		     cannot occur here.  */
   1865      1.1  mrg 		case CAF_ARR_REF_OPEN_START:
   1866      1.1  mrg 		default:
   1867      1.1  mrg 		  caf_internal_error (unknownarrreftype, stat, NULL, 0);
   1868      1.1  mrg 		  return;
   1869      1.1  mrg 		}
   1870      1.1  mrg 	      if (delta <= 0)
   1871      1.1  mrg 		return;
   1872      1.1  mrg 	      /* Check the various properties of the destination array.
   1873      1.1  mrg 		 Is an array expected and present?  */
   1874      1.1  mrg 	      if (delta > 1 && dst_rank == 0)
   1875      1.1  mrg 		{
   1876      1.1  mrg 		  /* No, an array is required, but not provided.  */
   1877      1.1  mrg 		  caf_internal_error (extentoutofrange, stat, NULL, 0);
   1878      1.1  mrg 		  return;
   1879      1.1  mrg 		}
   1880      1.1  mrg 	      /* Special mode when called by __caf_sendget_by_ref ().  */
   1881      1.1  mrg 	      if (dst_rank == -1 && GFC_DESCRIPTOR_DATA (dst) == NULL)
   1882      1.1  mrg 		{
   1883      1.1  mrg 		  dst_rank = dst_cur_dim + 1;
   1884      1.1  mrg 		  GFC_DESCRIPTOR_RANK (dst) = dst_rank;
   1885      1.1  mrg 		  GFC_DESCRIPTOR_SIZE (dst) = dst_kind;
   1886      1.1  mrg 		}
   1887      1.1  mrg 	      /* When dst is an array.  */
   1888      1.1  mrg 	      if (dst_rank > 0)
   1889      1.1  mrg 		{
   1890      1.1  mrg 		  /* Check that dst_cur_dim is valid for dst.  Can be
   1891      1.1  mrg 		     superceeded only by scalar data.  */
   1892      1.1  mrg 		  if (dst_cur_dim >= dst_rank && delta != 1)
   1893      1.1  mrg 		    {
   1894      1.1  mrg 		      caf_internal_error (rankoutofrange, stat, NULL, 0);
   1895      1.1  mrg 		      return;
   1896      1.1  mrg 		    }
   1897      1.1  mrg 		  /* Do further checks, when the source is not scalar.  */
   1898      1.1  mrg 		  else if (delta != 1)
   1899      1.1  mrg 		    {
   1900      1.1  mrg 		      /* Check that the extent is not scalar and we are not in
   1901      1.1  mrg 			 an array ref for the dst side.  */
   1902      1.1  mrg 		      if (!in_array_ref)
   1903      1.1  mrg 			{
   1904      1.1  mrg 			  /* Check that this is the non-scalar extent.  */
   1905      1.1  mrg 			  if (!array_extent_fixed)
   1906      1.1  mrg 			    {
   1907      1.1  mrg 			      /* In an array extent now.  */
   1908      1.1  mrg 			      in_array_ref = true;
   1909      1.1  mrg 			      /* The dst is not reallocatable, so nothing more
   1910      1.1  mrg 				 to do, then correct the dim counter.  */
   1911      1.1  mrg 			      dst_cur_dim = i;
   1912      1.1  mrg 			    }
   1913      1.1  mrg 			  else
   1914      1.1  mrg 			    {
   1915      1.1  mrg 			      caf_internal_error (doublearrayref, stat, NULL,
   1916      1.1  mrg 						  0);
   1917      1.1  mrg 			      return;
   1918      1.1  mrg 			    }
   1919      1.1  mrg 			}
   1920      1.1  mrg 		      /* When the realloc is required, then no extent may have
   1921      1.1  mrg 			 been set.  */
   1922      1.1  mrg 		      extent_mismatch = realloc_required
   1923      1.1  mrg 			  || GFC_DESCRIPTOR_EXTENT (dst, dst_cur_dim) != delta;
   1924      1.1  mrg 		      /* When it is already known, that a realloc is needed or
   1925      1.1  mrg 			 the extent does not match the needed one.  */
   1926      1.1  mrg 		      if (realloc_required || realloc_needed
   1927      1.1  mrg 			  || extent_mismatch)
   1928      1.1  mrg 			{
   1929      1.1  mrg 			  /* Check whether dst is reallocatable.  */
   1930      1.1  mrg 			  if (unlikely (!dst_reallocatable))
   1931      1.1  mrg 			    {
   1932      1.1  mrg 			      caf_internal_error (nonallocextentmismatch, stat,
   1933      1.1  mrg 						  NULL, 0, delta,
   1934      1.1  mrg 						  GFC_DESCRIPTOR_EXTENT (dst,
   1935      1.1  mrg 								  dst_cur_dim));
   1936      1.1  mrg 			      return;
   1937      1.1  mrg 			    }
   1938      1.1  mrg 			  /* Only report an error, when the extent needs to be
   1939      1.1  mrg 			     modified, which is not allowed.  */
   1940      1.1  mrg 			  else if (!dst_reallocatable && extent_mismatch)
   1941      1.1  mrg 			    {
   1942      1.1  mrg 			      caf_internal_error (extentoutofrange, stat, NULL,
   1943      1.1  mrg 						  0);
   1944      1.1  mrg 			      return;
   1945      1.1  mrg 			    }
   1946      1.1  mrg 			  realloc_needed = true;
   1947      1.1  mrg 			}
   1948      1.1  mrg 		      /* Only change the extent when it does not match.  This is
   1949      1.1  mrg 			 to prevent resetting given array bounds.  */
   1950      1.1  mrg 		      if (extent_mismatch)
   1951      1.1  mrg 			GFC_DIMENSION_SET (dst->dim[dst_cur_dim], 1, delta,
   1952      1.1  mrg 					   size);
   1953      1.1  mrg 		    }
   1954      1.1  mrg 		  /* Only increase the dim counter, when in an array ref.  */
   1955      1.1  mrg 		  if (in_array_ref && dst_cur_dim < dst_rank)
   1956      1.1  mrg 		    ++dst_cur_dim;
   1957      1.1  mrg 		}
   1958      1.1  mrg 	      size *= (index_type)delta;
   1959      1.1  mrg 	    }
   1960      1.1  mrg 	  if (in_array_ref)
   1961      1.1  mrg 	    {
   1962      1.1  mrg 	      array_extent_fixed = true;
   1963      1.1  mrg 	      in_array_ref = false;
   1964      1.1  mrg 	      /* Check, if we got less dimensional refs than the rank of dst
   1965      1.1  mrg 		 expects.  */
   1966      1.1  mrg 	      assert (dst_cur_dim == GFC_DESCRIPTOR_RANK (dst));
   1967      1.1  mrg 	    }
   1968      1.1  mrg 	  break;
   1969      1.1  mrg 	default:
   1970      1.1  mrg 	  caf_internal_error (unknownreftype, stat, NULL, 0);
   1971      1.1  mrg 	  return;
   1972      1.1  mrg 	}
   1973      1.1  mrg       src_size = riter->item_size;
   1974      1.1  mrg       riter = riter->next;
   1975      1.1  mrg     }
   1976      1.1  mrg   if (size == 0 || src_size == 0)
   1977      1.1  mrg     return;
   1978      1.1  mrg   /* Postcondition:
   1979      1.1  mrg      - size contains the number of elements to store in the destination array,
   1980      1.1  mrg      - src_size gives the size in bytes of each item in the destination array.
   1981      1.1  mrg   */
   1982      1.1  mrg 
   1983      1.1  mrg   if (realloc_needed)
   1984      1.1  mrg     {
   1985      1.1  mrg       if (!array_extent_fixed)
   1986      1.1  mrg 	{
   1987      1.1  mrg 	  assert (size == 1);
   1988      1.1  mrg 	  /* Special mode when called by __caf_sendget_by_ref ().  */
   1989      1.1  mrg 	  if (dst_rank == -1 && GFC_DESCRIPTOR_DATA (dst) == NULL)
   1990      1.1  mrg 	    {
   1991      1.1  mrg 	      dst_rank = dst_cur_dim + 1;
   1992      1.1  mrg 	      GFC_DESCRIPTOR_RANK (dst) = dst_rank;
   1993      1.1  mrg 	      GFC_DESCRIPTOR_SIZE (dst) = dst_kind;
   1994      1.1  mrg 	    }
   1995      1.1  mrg 	  /* This can happen only, when the result is scalar.  */
   1996      1.1  mrg 	  for (dst_cur_dim = 0; dst_cur_dim < dst_rank; ++dst_cur_dim)
   1997      1.1  mrg 	    GFC_DIMENSION_SET (dst->dim[dst_cur_dim], 1, 1, 1);
   1998      1.1  mrg 	}
   1999      1.1  mrg 
   2000      1.1  mrg       GFC_DESCRIPTOR_DATA (dst) = malloc (size * GFC_DESCRIPTOR_SIZE (dst));
   2001      1.1  mrg       if (unlikely (GFC_DESCRIPTOR_DATA (dst) == NULL))
   2002      1.1  mrg 	{
   2003      1.1  mrg 	  caf_internal_error (cannotallocdst, stat, NULL, 0);
   2004      1.1  mrg 	  return;
   2005      1.1  mrg 	}
   2006      1.1  mrg     }
   2007      1.1  mrg 
   2008      1.1  mrg   /* Reset the token.  */
   2009      1.1  mrg   single_token = TOKEN (token);
   2010      1.1  mrg   memptr = single_token->memptr;
   2011      1.1  mrg   src = single_token->desc;
   2012      1.1  mrg   memset(dst_index, 0, sizeof (dst_index));
   2013      1.1  mrg   i = 0;
   2014      1.1  mrg   get_for_ref (refs, &i, dst_index, single_token, dst, src,
   2015      1.1  mrg 	       GFC_DESCRIPTOR_DATA (dst), memptr, dst_kind, src_kind, 0, 0,
   2016      1.1  mrg 	       1, stat, src_type);
   2017      1.1  mrg }
   2018      1.1  mrg 
   2019      1.1  mrg 
   2020      1.1  mrg static void
   2021      1.1  mrg send_by_ref (caf_reference_t *ref, size_t *i, size_t *src_index,
   2022      1.1  mrg 	     caf_single_token_t single_token, gfc_descriptor_t *dst,
   2023      1.1  mrg 	     gfc_descriptor_t *src, void *ds, void *sr,
   2024      1.1  mrg 	     int dst_kind, int src_kind, size_t dst_dim, size_t src_dim,
   2025      1.1  mrg 	     size_t num, size_t size, int *stat, int dst_type)
   2026      1.1  mrg {
   2027      1.1  mrg   const char vecrefunknownkind[] = "libcaf_single::caf_send_by_ref(): "
   2028      1.1  mrg       "unknown kind in vector-ref.\n";
   2029      1.1  mrg   ptrdiff_t extent_dst = 1, array_offset_dst = 0, stride_dst;
   2030      1.1  mrg   const size_t src_rank = GFC_DESCRIPTOR_RANK (src);
   2031      1.1  mrg 
   2032      1.1  mrg   if (unlikely (ref == NULL))
   2033      1.1  mrg     /* May be we should issue an error here, because this case should not
   2034      1.1  mrg        occur.  */
   2035      1.1  mrg     return;
   2036      1.1  mrg 
   2037      1.1  mrg   if (ref->next == NULL)
   2038      1.1  mrg     {
   2039      1.1  mrg       size_t src_size = GFC_DESCRIPTOR_SIZE (src);
   2040      1.1  mrg       ptrdiff_t array_offset_src = 0;;
   2041      1.1  mrg 
   2042      1.1  mrg       switch (ref->type)
   2043      1.1  mrg 	{
   2044      1.1  mrg 	case CAF_REF_COMPONENT:
   2045      1.1  mrg 	  if (ref->u.c.caf_token_offset > 0)
   2046      1.1  mrg 	    {
   2047      1.1  mrg 	      if (*(void**)(ds + ref->u.c.offset) == NULL)
   2048      1.1  mrg 		{
   2049      1.1  mrg 		  /* Create a scalar temporary array descriptor.  */
   2050      1.1  mrg 		  gfc_descriptor_t static_dst;
   2051      1.1  mrg 		  GFC_DESCRIPTOR_DATA (&static_dst) = NULL;
   2052      1.1  mrg 		  GFC_DESCRIPTOR_DTYPE (&static_dst)
   2053      1.1  mrg 		      = GFC_DESCRIPTOR_DTYPE (src);
   2054      1.1  mrg 		  /* The component can be allocated now, because it is a
   2055      1.1  mrg 		     scalar.  */
   2056      1.1  mrg 		  _gfortran_caf_register (ref->item_size,
   2057      1.1  mrg 					  CAF_REGTYPE_COARRAY_ALLOC,
   2058      1.1  mrg 					  ds + ref->u.c.caf_token_offset,
   2059      1.1  mrg 					  &static_dst, stat, NULL, 0);
   2060      1.1  mrg 		  single_token = *(caf_single_token_t *)
   2061      1.1  mrg 					       (ds + ref->u.c.caf_token_offset);
   2062      1.1  mrg 		  /* In case of an error in allocation return.  When stat is
   2063      1.1  mrg 		     NULL, then register_component() terminates on error.  */
   2064      1.1  mrg 		  if (stat != NULL && *stat)
   2065      1.1  mrg 		    return;
   2066      1.1  mrg 		  /* Publish the allocated memory.  */
   2067      1.1  mrg 		  *((void **)(ds + ref->u.c.offset))
   2068      1.1  mrg 		      = GFC_DESCRIPTOR_DATA (&static_dst);
   2069      1.1  mrg 		  ds = GFC_DESCRIPTOR_DATA (&static_dst);
   2070      1.1  mrg 		  /* Set the type from the src.  */
   2071      1.1  mrg 		  dst_type = GFC_DESCRIPTOR_TYPE (src);
   2072      1.1  mrg 		}
   2073      1.1  mrg 	      else
   2074      1.1  mrg 		{
   2075      1.1  mrg 		  single_token = *(caf_single_token_t *)
   2076      1.1  mrg 					       (ds + ref->u.c.caf_token_offset);
   2077      1.1  mrg 		  dst = single_token->desc;
   2078      1.1  mrg 		  if (dst)
   2079      1.1  mrg 		    {
   2080      1.1  mrg 		      ds = GFC_DESCRIPTOR_DATA (dst);
   2081      1.1  mrg 		      dst_type = GFC_DESCRIPTOR_TYPE (dst);
   2082      1.1  mrg 		    }
   2083      1.1  mrg 		  else
   2084      1.1  mrg 		    ds = *(void **)(ds + ref->u.c.offset);
   2085      1.1  mrg 		}
   2086      1.1  mrg 	      copy_data (ds, sr, dst_type, GFC_DESCRIPTOR_TYPE (src),
   2087      1.1  mrg 			 dst_kind, src_kind, ref->item_size, src_size, 1, stat);
   2088      1.1  mrg 	    }
   2089      1.1  mrg 	  else
   2090      1.1  mrg 	    copy_data (ds + ref->u.c.offset, sr, dst_type,
   2091      1.1  mrg 		       GFC_DESCRIPTOR_TYPE (src),
   2092      1.1  mrg 		       dst_kind, src_kind, ref->item_size, src_size, 1, stat);
   2093      1.1  mrg 	  ++(*i);
   2094      1.1  mrg 	  return;
   2095      1.1  mrg 	case CAF_REF_STATIC_ARRAY:
   2096      1.1  mrg 	  /* Intentionally fall through.  */
   2097      1.1  mrg 	case CAF_REF_ARRAY:
   2098      1.1  mrg 	  if (ref->u.a.mode[dst_dim] == CAF_ARR_REF_NONE)
   2099      1.1  mrg 	    {
   2100      1.1  mrg 	      if (src_rank > 0)
   2101      1.1  mrg 		{
   2102      1.1  mrg 		  for (size_t d = 0; d < src_rank; ++d)
   2103      1.1  mrg 		    array_offset_src += src_index[d];
   2104      1.1  mrg 		  copy_data (ds, sr + array_offset_src * src_size,
   2105      1.1  mrg 			     dst_type, GFC_DESCRIPTOR_TYPE (src), dst_kind,
   2106      1.1  mrg 			     src_kind, ref->item_size, src_size, num, stat);
   2107      1.1  mrg 		}
   2108      1.1  mrg 	      else
   2109      1.1  mrg 		copy_data (ds, sr, dst_type, GFC_DESCRIPTOR_TYPE (src),
   2110      1.1  mrg 			   dst_kind, src_kind, ref->item_size, src_size, num,
   2111      1.1  mrg 			   stat);
   2112      1.1  mrg 	      *i += num;
   2113      1.1  mrg 	      return;
   2114      1.1  mrg 	    }
   2115      1.1  mrg 	  break;
   2116      1.1  mrg 	default:
   2117      1.1  mrg 	  caf_runtime_error (unreachable);
   2118      1.1  mrg 	}
   2119      1.1  mrg     }
   2120      1.1  mrg 
   2121      1.1  mrg   switch (ref->type)
   2122      1.1  mrg     {
   2123      1.1  mrg     case CAF_REF_COMPONENT:
   2124      1.1  mrg       if (ref->u.c.caf_token_offset > 0)
   2125      1.1  mrg 	{
   2126      1.1  mrg 	  if (*(void**)(ds + ref->u.c.offset) == NULL)
   2127      1.1  mrg 	    {
   2128      1.1  mrg 	      /* This component refs an unallocated array.  Non-arrays are
   2129      1.1  mrg 		 caught in the if (!ref->next) above.  */
   2130      1.1  mrg 	      dst = (gfc_descriptor_t *)(ds + ref->u.c.offset);
   2131      1.1  mrg 	      /* Assume that the rank and the dimensions fit for copying src
   2132      1.1  mrg 		 to dst.  */
   2133      1.1  mrg 	      GFC_DESCRIPTOR_DTYPE (dst) = GFC_DESCRIPTOR_DTYPE (src);
   2134      1.1  mrg 	      dst->offset = 0;
   2135      1.1  mrg 	      stride_dst = 1;
   2136      1.1  mrg 	      for (size_t d = 0; d < src_rank; ++d)
   2137      1.1  mrg 		{
   2138      1.1  mrg 		  extent_dst = GFC_DIMENSION_EXTENT (src->dim[d]);
   2139      1.1  mrg 		  GFC_DIMENSION_LBOUND (dst->dim[d]) = 0;
   2140      1.1  mrg 		  GFC_DIMENSION_UBOUND (dst->dim[d]) = extent_dst - 1;
   2141      1.1  mrg 		  GFC_DIMENSION_STRIDE (dst->dim[d]) = stride_dst;
   2142      1.1  mrg 		  stride_dst *= extent_dst;
   2143      1.1  mrg 		}
   2144      1.1  mrg 	      /* Null the data-pointer to make register_component allocate
   2145      1.1  mrg 		 its own memory.  */
   2146      1.1  mrg 	      GFC_DESCRIPTOR_DATA (dst) = NULL;
   2147      1.1  mrg 
   2148      1.1  mrg 	      /* The size of the array is given by size.  */
   2149      1.1  mrg 	      _gfortran_caf_register (size * ref->item_size,
   2150      1.1  mrg 				      CAF_REGTYPE_COARRAY_ALLOC,
   2151      1.1  mrg 				      ds + ref->u.c.caf_token_offset,
   2152      1.1  mrg 				      dst, stat, NULL, 0);
   2153      1.1  mrg 	      /* In case of an error in allocation return.  When stat is
   2154      1.1  mrg 		 NULL, then register_component() terminates on error.  */
   2155      1.1  mrg 	      if (stat != NULL && *stat)
   2156      1.1  mrg 		return;
   2157      1.1  mrg 	    }
   2158      1.1  mrg 	  single_token = *(caf_single_token_t*)(ds + ref->u.c.caf_token_offset);
   2159      1.1  mrg 	  /* When a component is allocatable (caf_token_offset != 0) and not an
   2160      1.1  mrg 	     array (ref->next->type == CAF_REF_COMPONENT), then ds has to be
   2161      1.1  mrg 	     dereffed.  */
   2162      1.1  mrg 	  if (ref->next && ref->next->type == CAF_REF_COMPONENT)
   2163      1.1  mrg 	    ds = *(void **)(ds + ref->u.c.offset);
   2164      1.1  mrg 	  else
   2165      1.1  mrg 	    ds += ref->u.c.offset;
   2166      1.1  mrg 
   2167      1.1  mrg 	  send_by_ref (ref->next, i, src_index, single_token,
   2168      1.1  mrg 		       single_token->desc, src, ds, sr,
   2169      1.1  mrg 		       dst_kind, src_kind, 0, src_dim, 1, size, stat, dst_type);
   2170      1.1  mrg 	}
   2171      1.1  mrg       else
   2172      1.1  mrg 	send_by_ref (ref->next, i, src_index, single_token,
   2173      1.1  mrg 		     (gfc_descriptor_t *)(ds + ref->u.c.offset), src,
   2174      1.1  mrg 		     ds + ref->u.c.offset, sr, dst_kind, src_kind, 0, src_dim,
   2175      1.1  mrg 		     1, size, stat, dst_type);
   2176      1.1  mrg       return;
   2177      1.1  mrg     case CAF_REF_ARRAY:
   2178      1.1  mrg       if (ref->u.a.mode[dst_dim] == CAF_ARR_REF_NONE)
   2179      1.1  mrg 	{
   2180      1.1  mrg 	  send_by_ref (ref->next, i, src_index, single_token,
   2181      1.1  mrg 		       (gfc_descriptor_t *)ds, src, ds, sr, dst_kind, src_kind,
   2182      1.1  mrg 		       0, src_dim, 1, size, stat, dst_type);
   2183      1.1  mrg 	  return;
   2184      1.1  mrg 	}
   2185      1.1  mrg       /* Only when on the left most index switch the data pointer to
   2186      1.1  mrg 	 the array's data pointer.  And only for non-static arrays.  */
   2187      1.1  mrg       if (dst_dim == 0 && ref->type != CAF_REF_STATIC_ARRAY)
   2188      1.1  mrg 	ds = GFC_DESCRIPTOR_DATA (dst);
   2189      1.1  mrg       switch (ref->u.a.mode[dst_dim])
   2190      1.1  mrg 	{
   2191      1.1  mrg 	case CAF_ARR_REF_VECTOR:
   2192      1.1  mrg 	  array_offset_dst = 0;
   2193      1.1  mrg 	  src_index[src_dim] = 0;
   2194      1.1  mrg 	  for (size_t idx = 0; idx < ref->u.a.dim[dst_dim].v.nvec;
   2195      1.1  mrg 	       ++idx)
   2196      1.1  mrg 	    {
   2197      1.1  mrg #define KINDCASE(kind, type) case kind: \
   2198      1.1  mrg 	      array_offset_dst = (((index_type) \
   2199      1.1  mrg 		  ((type *)ref->u.a.dim[dst_dim].v.vector)[idx]) \
   2200      1.1  mrg 		  - GFC_DIMENSION_LBOUND (dst->dim[dst_dim])) \
   2201      1.1  mrg 		  * GFC_DIMENSION_STRIDE (dst->dim[dst_dim]); \
   2202      1.1  mrg 	      break
   2203      1.1  mrg 
   2204      1.1  mrg 	      switch (ref->u.a.dim[dst_dim].v.kind)
   2205      1.1  mrg 		{
   2206      1.1  mrg 		KINDCASE (1, GFC_INTEGER_1);
   2207      1.1  mrg 		KINDCASE (2, GFC_INTEGER_2);
   2208      1.1  mrg 		KINDCASE (4, GFC_INTEGER_4);
   2209      1.1  mrg #ifdef HAVE_GFC_INTEGER_8
   2210      1.1  mrg 		KINDCASE (8, GFC_INTEGER_8);
   2211      1.1  mrg #endif
   2212      1.1  mrg #ifdef HAVE_GFC_INTEGER_16
   2213      1.1  mrg 		KINDCASE (16, GFC_INTEGER_16);
   2214      1.1  mrg #endif
   2215      1.1  mrg 		default:
   2216      1.1  mrg 		  caf_internal_error (vecrefunknownkind, stat, NULL, 0);
   2217      1.1  mrg 		  return;
   2218      1.1  mrg 		}
   2219      1.1  mrg #undef KINDCASE
   2220      1.1  mrg 
   2221      1.1  mrg 	      send_by_ref (ref, i, src_index, single_token, dst, src,
   2222      1.1  mrg 			   ds + array_offset_dst * ref->item_size, sr,
   2223      1.1  mrg 			   dst_kind, src_kind, dst_dim + 1, src_dim + 1,
   2224      1.1  mrg 			   1, size, stat, dst_type);
   2225      1.1  mrg 	      if (src_rank > 0)
   2226      1.1  mrg 		src_index[src_dim]
   2227      1.1  mrg 		    += GFC_DIMENSION_STRIDE (src->dim[src_dim]);
   2228      1.1  mrg 	    }
   2229      1.1  mrg 	  return;
   2230      1.1  mrg 	case CAF_ARR_REF_FULL:
   2231      1.1  mrg 	  COMPUTE_NUM_ITEMS (extent_dst,
   2232      1.1  mrg 			     ref->u.a.dim[dst_dim].s.stride,
   2233      1.1  mrg 			     GFC_DIMENSION_LBOUND (dst->dim[dst_dim]),
   2234      1.1  mrg 			     GFC_DIMENSION_UBOUND (dst->dim[dst_dim]));
   2235      1.1  mrg 	  array_offset_dst = 0;
   2236      1.1  mrg 	  stride_dst = GFC_DIMENSION_STRIDE (dst->dim[dst_dim])
   2237      1.1  mrg 	      * ref->u.a.dim[dst_dim].s.stride;
   2238      1.1  mrg 	  src_index[src_dim] = 0;
   2239      1.1  mrg 	  for (index_type idx = 0; idx < extent_dst;
   2240      1.1  mrg 	       ++idx, array_offset_dst += stride_dst)
   2241      1.1  mrg 	    {
   2242      1.1  mrg 	      send_by_ref (ref, i, src_index, single_token, dst, src,
   2243      1.1  mrg 			   ds + array_offset_dst * ref->item_size, sr,
   2244      1.1  mrg 			   dst_kind, src_kind, dst_dim + 1, src_dim + 1,
   2245      1.1  mrg 			   1, size, stat, dst_type);
   2246      1.1  mrg 	      if (src_rank > 0)
   2247      1.1  mrg 		src_index[src_dim]
   2248      1.1  mrg 		    += GFC_DIMENSION_STRIDE (src->dim[src_dim]);
   2249      1.1  mrg 	    }
   2250      1.1  mrg 	  return;
   2251      1.1  mrg 	case CAF_ARR_REF_RANGE:
   2252      1.1  mrg 	  COMPUTE_NUM_ITEMS (extent_dst,
   2253      1.1  mrg 			     ref->u.a.dim[dst_dim].s.stride,
   2254      1.1  mrg 			     ref->u.a.dim[dst_dim].s.start,
   2255      1.1  mrg 			     ref->u.a.dim[dst_dim].s.end);
   2256      1.1  mrg 	  array_offset_dst = ref->u.a.dim[dst_dim].s.start
   2257      1.1  mrg 	      - GFC_DIMENSION_LBOUND (dst->dim[dst_dim]);
   2258      1.1  mrg 	  stride_dst = GFC_DIMENSION_STRIDE (dst->dim[dst_dim])
   2259      1.1  mrg 	      * ref->u.a.dim[dst_dim].s.stride;
   2260      1.1  mrg 	  src_index[src_dim] = 0;
   2261      1.1  mrg 	  for (index_type idx = 0; idx < extent_dst; ++idx)
   2262      1.1  mrg 	    {
   2263      1.1  mrg 	      send_by_ref (ref, i, src_index, single_token, dst, src,
   2264      1.1  mrg 			   ds + array_offset_dst * ref->item_size, sr,
   2265      1.1  mrg 			   dst_kind, src_kind, dst_dim + 1, src_dim + 1,
   2266      1.1  mrg 			   1, size, stat, dst_type);
   2267      1.1  mrg 	      if (src_rank > 0)
   2268      1.1  mrg 		src_index[src_dim]
   2269      1.1  mrg 		    += GFC_DIMENSION_STRIDE (src->dim[src_dim]);
   2270      1.1  mrg 	      array_offset_dst += stride_dst;
   2271      1.1  mrg 	    }
   2272      1.1  mrg 	  return;
   2273      1.1  mrg 	case CAF_ARR_REF_SINGLE:
   2274      1.1  mrg 	  array_offset_dst = (ref->u.a.dim[dst_dim].s.start
   2275      1.1  mrg 			       - GFC_DIMENSION_LBOUND (dst->dim[dst_dim]))
   2276      1.1  mrg 			     * GFC_DIMENSION_STRIDE (dst->dim[dst_dim]);
   2277      1.1  mrg 	  send_by_ref (ref, i, src_index, single_token, dst, src, ds
   2278      1.1  mrg 		       + array_offset_dst * ref->item_size, sr,
   2279      1.1  mrg 		       dst_kind, src_kind, dst_dim + 1, src_dim, 1,
   2280      1.1  mrg 		       size, stat, dst_type);
   2281      1.1  mrg 	  return;
   2282      1.1  mrg 	case CAF_ARR_REF_OPEN_END:
   2283      1.1  mrg 	  COMPUTE_NUM_ITEMS (extent_dst,
   2284      1.1  mrg 			     ref->u.a.dim[dst_dim].s.stride,
   2285      1.1  mrg 			     ref->u.a.dim[dst_dim].s.start,
   2286      1.1  mrg 			     GFC_DIMENSION_UBOUND (dst->dim[dst_dim]));
   2287      1.1  mrg 	  array_offset_dst = ref->u.a.dim[dst_dim].s.start
   2288      1.1  mrg 	      - GFC_DIMENSION_LBOUND (dst->dim[dst_dim]);
   2289      1.1  mrg 	  stride_dst = GFC_DIMENSION_STRIDE (dst->dim[dst_dim])
   2290      1.1  mrg 	      * ref->u.a.dim[dst_dim].s.stride;
   2291      1.1  mrg 	  src_index[src_dim] = 0;
   2292      1.1  mrg 	  for (index_type idx = 0; idx < extent_dst; ++idx)
   2293      1.1  mrg 	    {
   2294      1.1  mrg 	      send_by_ref (ref, i, src_index, single_token, dst, src,
   2295      1.1  mrg 			   ds + array_offset_dst * ref->item_size, sr,
   2296      1.1  mrg 			   dst_kind, src_kind, dst_dim + 1, src_dim + 1,
   2297      1.1  mrg 			   1, size, stat, dst_type);
   2298      1.1  mrg 	      if (src_rank > 0)
   2299      1.1  mrg 		src_index[src_dim]
   2300      1.1  mrg 		    += GFC_DIMENSION_STRIDE (src->dim[src_dim]);
   2301      1.1  mrg 	      array_offset_dst += stride_dst;
   2302      1.1  mrg 	    }
   2303      1.1  mrg 	  return;
   2304      1.1  mrg 	case CAF_ARR_REF_OPEN_START:
   2305      1.1  mrg 	  COMPUTE_NUM_ITEMS (extent_dst,
   2306      1.1  mrg 			     ref->u.a.dim[dst_dim].s.stride,
   2307      1.1  mrg 			     GFC_DIMENSION_LBOUND (dst->dim[dst_dim]),
   2308      1.1  mrg 			     ref->u.a.dim[dst_dim].s.end);
   2309      1.1  mrg 	  array_offset_dst = 0;
   2310      1.1  mrg 	  stride_dst = GFC_DIMENSION_STRIDE (dst->dim[dst_dim])
   2311      1.1  mrg 	      * ref->u.a.dim[dst_dim].s.stride;
   2312      1.1  mrg 	  src_index[src_dim] = 0;
   2313      1.1  mrg 	  for (index_type idx = 0; idx < extent_dst; ++idx)
   2314      1.1  mrg 	    {
   2315      1.1  mrg 	      send_by_ref (ref, i, src_index, single_token, dst, src,
   2316      1.1  mrg 			   ds + array_offset_dst * ref->item_size, sr,
   2317      1.1  mrg 			   dst_kind, src_kind, dst_dim + 1, src_dim + 1,
   2318      1.1  mrg 			   1, size, stat, dst_type);
   2319      1.1  mrg 	      if (src_rank > 0)
   2320      1.1  mrg 		src_index[src_dim]
   2321      1.1  mrg 		    += GFC_DIMENSION_STRIDE (src->dim[src_dim]);
   2322      1.1  mrg 	      array_offset_dst += stride_dst;
   2323      1.1  mrg 	    }
   2324      1.1  mrg 	  return;
   2325      1.1  mrg 	default:
   2326      1.1  mrg 	  caf_runtime_error (unreachable);
   2327      1.1  mrg 	}
   2328      1.1  mrg       return;
   2329      1.1  mrg     case CAF_REF_STATIC_ARRAY:
   2330      1.1  mrg       if (ref->u.a.mode[dst_dim] == CAF_ARR_REF_NONE)
   2331      1.1  mrg 	{
   2332      1.1  mrg 	  send_by_ref (ref->next, i, src_index, single_token, NULL,
   2333      1.1  mrg 		       src, ds, sr, dst_kind, src_kind,
   2334      1.1  mrg 		       0, src_dim, 1, size, stat, dst_type);
   2335      1.1  mrg 	  return;
   2336      1.1  mrg 	}
   2337      1.1  mrg       switch (ref->u.a.mode[dst_dim])
   2338      1.1  mrg 	{
   2339      1.1  mrg 	case CAF_ARR_REF_VECTOR:
   2340      1.1  mrg 	  array_offset_dst = 0;
   2341      1.1  mrg 	  src_index[src_dim] = 0;
   2342      1.1  mrg 	  for (size_t idx = 0; idx < ref->u.a.dim[dst_dim].v.nvec;
   2343      1.1  mrg 	       ++idx)
   2344      1.1  mrg 	    {
   2345      1.1  mrg #define KINDCASE(kind, type) case kind: \
   2346      1.1  mrg 	     array_offset_dst = ((type *)ref->u.a.dim[dst_dim].v.vector)[idx]; \
   2347      1.1  mrg 	      break
   2348      1.1  mrg 
   2349      1.1  mrg 	      switch (ref->u.a.dim[dst_dim].v.kind)
   2350      1.1  mrg 		{
   2351      1.1  mrg 		KINDCASE (1, GFC_INTEGER_1);
   2352      1.1  mrg 		KINDCASE (2, GFC_INTEGER_2);
   2353      1.1  mrg 		KINDCASE (4, GFC_INTEGER_4);
   2354      1.1  mrg #ifdef HAVE_GFC_INTEGER_8
   2355      1.1  mrg 		KINDCASE (8, GFC_INTEGER_8);
   2356      1.1  mrg #endif
   2357      1.1  mrg #ifdef HAVE_GFC_INTEGER_16
   2358      1.1  mrg 		KINDCASE (16, GFC_INTEGER_16);
   2359      1.1  mrg #endif
   2360      1.1  mrg 		default:
   2361      1.1  mrg 		  caf_runtime_error (unreachable);
   2362      1.1  mrg 		  return;
   2363      1.1  mrg 		}
   2364      1.1  mrg #undef KINDCASE
   2365      1.1  mrg 
   2366      1.1  mrg 	      send_by_ref (ref, i, src_index, single_token, NULL, src,
   2367      1.1  mrg 			   ds + array_offset_dst * ref->item_size, sr,
   2368      1.1  mrg 			   dst_kind, src_kind, dst_dim + 1, src_dim + 1,
   2369      1.1  mrg 			   1, size, stat, dst_type);
   2370      1.1  mrg 	      src_index[src_dim]
   2371      1.1  mrg 		  += GFC_DIMENSION_STRIDE (src->dim[src_dim]);
   2372      1.1  mrg 	    }
   2373      1.1  mrg 	  return;
   2374      1.1  mrg 	case CAF_ARR_REF_FULL:
   2375      1.1  mrg 	  src_index[src_dim] = 0;
   2376      1.1  mrg 	  for (array_offset_dst = 0 ;
   2377      1.1  mrg 	       array_offset_dst <= ref->u.a.dim[dst_dim].s.end;
   2378      1.1  mrg 	       array_offset_dst += ref->u.a.dim[dst_dim].s.stride)
   2379      1.1  mrg 	    {
   2380      1.1  mrg 	      send_by_ref (ref, i, src_index, single_token, NULL, src,
   2381      1.1  mrg 			   ds + array_offset_dst * ref->item_size, sr,
   2382      1.1  mrg 			   dst_kind, src_kind, dst_dim + 1, src_dim + 1,
   2383      1.1  mrg 			   1, size, stat, dst_type);
   2384      1.1  mrg 	      if (src_rank > 0)
   2385      1.1  mrg 		src_index[src_dim]
   2386      1.1  mrg 		    += GFC_DIMENSION_STRIDE (src->dim[src_dim]);
   2387      1.1  mrg 	    }
   2388      1.1  mrg 	  return;
   2389      1.1  mrg 	case CAF_ARR_REF_RANGE:
   2390      1.1  mrg 	  COMPUTE_NUM_ITEMS (extent_dst,
   2391      1.1  mrg 			     ref->u.a.dim[dst_dim].s.stride,
   2392      1.1  mrg 			     ref->u.a.dim[dst_dim].s.start,
   2393      1.1  mrg 			     ref->u.a.dim[dst_dim].s.end);
   2394      1.1  mrg 	  array_offset_dst = ref->u.a.dim[dst_dim].s.start;
   2395      1.1  mrg 	  src_index[src_dim] = 0;
   2396      1.1  mrg 	  for (index_type idx = 0; idx < extent_dst; ++idx)
   2397      1.1  mrg 	    {
   2398      1.1  mrg 	      send_by_ref (ref, i, src_index, single_token, NULL, src,
   2399      1.1  mrg 			   ds + array_offset_dst * ref->item_size, sr,
   2400      1.1  mrg 			   dst_kind, src_kind, dst_dim + 1, src_dim + 1,
   2401      1.1  mrg 			   1, size, stat, dst_type);
   2402      1.1  mrg 	      if (src_rank > 0)
   2403      1.1  mrg 		src_index[src_dim]
   2404      1.1  mrg 		    += GFC_DIMENSION_STRIDE (src->dim[src_dim]);
   2405      1.1  mrg 	      array_offset_dst += ref->u.a.dim[dst_dim].s.stride;
   2406      1.1  mrg 	    }
   2407      1.1  mrg 	  return;
   2408      1.1  mrg 	case CAF_ARR_REF_SINGLE:
   2409      1.1  mrg 	  array_offset_dst = ref->u.a.dim[dst_dim].s.start;
   2410      1.1  mrg 	  send_by_ref (ref, i, src_index, single_token, NULL, src,
   2411      1.1  mrg 		       ds + array_offset_dst * ref->item_size, sr,
   2412      1.1  mrg 		       dst_kind, src_kind, dst_dim + 1, src_dim, 1,
   2413      1.1  mrg 		       size, stat, dst_type);
   2414      1.1  mrg 	  return;
   2415      1.1  mrg 	/* The OPEN_* are mapped to a RANGE and therefore cannot occur.  */
   2416      1.1  mrg 	case CAF_ARR_REF_OPEN_END:
   2417      1.1  mrg 	case CAF_ARR_REF_OPEN_START:
   2418      1.1  mrg 	default:
   2419      1.1  mrg 	  caf_runtime_error (unreachable);
   2420      1.1  mrg 	}
   2421      1.1  mrg       return;
   2422      1.1  mrg     default:
   2423      1.1  mrg       caf_runtime_error (unreachable);
   2424      1.1  mrg     }
   2425      1.1  mrg }
   2426      1.1  mrg 
   2427      1.1  mrg 
   2428      1.1  mrg void
   2429      1.1  mrg _gfortran_caf_send_by_ref (caf_token_t token,
   2430      1.1  mrg 			   int image_index __attribute__ ((unused)),
   2431      1.1  mrg 			   gfc_descriptor_t *src, caf_reference_t *refs,
   2432      1.1  mrg 			   int dst_kind, int src_kind,
   2433      1.1  mrg 			   bool may_require_tmp __attribute__ ((unused)),
   2434      1.1  mrg 			   bool dst_reallocatable, int *stat, int dst_type)
   2435      1.1  mrg {
   2436      1.1  mrg   const char vecrefunknownkind[] = "libcaf_single::caf_get_by_ref(): "
   2437      1.1  mrg 				   "unknown kind in vector-ref.\n";
   2438      1.1  mrg   const char unknownreftype[] = "libcaf_single::caf_send_by_ref(): "
   2439      1.1  mrg 				"unknown reference type.\n";
   2440      1.1  mrg   const char unknownarrreftype[] = "libcaf_single::caf_send_by_ref(): "
   2441      1.1  mrg 				   "unknown array reference type.\n";
   2442      1.1  mrg   const char rankoutofrange[] = "libcaf_single::caf_send_by_ref(): "
   2443      1.1  mrg 				"rank out of range.\n";
   2444      1.1  mrg   const char realloconinnerref[] = "libcaf_single::caf_send_by_ref(): "
   2445      1.1  mrg       "reallocation of array followed by component ref not allowed.\n";
   2446      1.1  mrg   const char cannotallocdst[] = "libcaf_single::caf_send_by_ref(): "
   2447      1.1  mrg 				"cannot allocate memory.\n";
   2448      1.1  mrg   const char nonallocextentmismatch[] = "libcaf_single::caf_send_by_ref(): "
   2449      1.1  mrg       "extent of non-allocatable array mismatch.\n";
   2450      1.1  mrg   const char innercompref[] = "libcaf_single::caf_send_by_ref(): "
   2451      1.1  mrg       "inner unallocated component detected.\n";
   2452      1.1  mrg   size_t size, i;
   2453      1.1  mrg   size_t dst_index[GFC_MAX_DIMENSIONS];
   2454      1.1  mrg   int src_rank = GFC_DESCRIPTOR_RANK (src);
   2455      1.1  mrg   int src_cur_dim = 0;
   2456      1.1  mrg   size_t src_size = 0;
   2457      1.1  mrg   caf_single_token_t single_token = TOKEN (token);
   2458      1.1  mrg   void *memptr = single_token->memptr;
   2459      1.1  mrg   gfc_descriptor_t *dst = single_token->desc;
   2460      1.1  mrg   caf_reference_t *riter = refs;
   2461      1.1  mrg   long delta;
   2462      1.1  mrg   bool extent_mismatch;
   2463      1.1  mrg   /* Note that the component is not allocated yet.  */
   2464      1.1  mrg   index_type new_component_idx = -1;
   2465      1.1  mrg 
   2466      1.1  mrg   if (stat)
   2467      1.1  mrg     *stat = 0;
   2468      1.1  mrg 
   2469      1.1  mrg   /* Compute the size of the result.  In the beginning size just counts the
   2470      1.1  mrg      number of elements.  */
   2471      1.1  mrg   size = 1;
   2472      1.1  mrg   while (riter)
   2473      1.1  mrg     {
   2474      1.1  mrg       switch (riter->type)
   2475      1.1  mrg 	{
   2476      1.1  mrg 	case CAF_REF_COMPONENT:
   2477      1.1  mrg 	  if (unlikely (new_component_idx != -1))
   2478      1.1  mrg 	    {
   2479      1.1  mrg 	      /* Allocating a component in the middle of a component ref is not
   2480      1.1  mrg 		 support.  We don't know the type to allocate.  */
   2481      1.1  mrg 	      caf_internal_error (innercompref, stat, NULL, 0);
   2482      1.1  mrg 	      return;
   2483      1.1  mrg 	    }
   2484      1.1  mrg 	  if (riter->u.c.caf_token_offset > 0)
   2485      1.1  mrg 	    {
   2486      1.1  mrg 	      /* Check whether the allocatable component is zero, then no
   2487      1.1  mrg 		 token is present, too.  The token's pointer is not cleared
   2488      1.1  mrg 		 when the structure is initialized.  */
   2489      1.1  mrg 	      if (*(void**)(memptr + riter->u.c.offset) == NULL)
   2490      1.1  mrg 		{
   2491      1.1  mrg 		  /* This component is not yet allocated.  Check that it is
   2492      1.1  mrg 		     allocatable here.  */
   2493      1.1  mrg 		  if (!dst_reallocatable)
   2494      1.1  mrg 		    {
   2495      1.1  mrg 		      caf_internal_error (cannotallocdst, stat, NULL, 0);
   2496      1.1  mrg 		      return;
   2497      1.1  mrg 		    }
   2498      1.1  mrg 		  single_token = NULL;
   2499      1.1  mrg 		  memptr = NULL;
   2500      1.1  mrg 		  dst = NULL;
   2501      1.1  mrg 		  break;
   2502      1.1  mrg 		}
   2503      1.1  mrg 	      single_token = *(caf_single_token_t*)
   2504      1.1  mrg 					 (memptr + riter->u.c.caf_token_offset);
   2505      1.1  mrg 	      memptr += riter->u.c.offset;
   2506      1.1  mrg 	      dst = single_token->desc;
   2507      1.1  mrg 	    }
   2508      1.1  mrg 	  else
   2509      1.1  mrg 	    {
   2510      1.1  mrg 	      /* Regular component.  */
   2511      1.1  mrg 	      memptr += riter->u.c.offset;
   2512      1.1  mrg 	      dst = (gfc_descriptor_t *)memptr;
   2513      1.1  mrg 	    }
   2514      1.1  mrg 	  break;
   2515      1.1  mrg 	case CAF_REF_ARRAY:
   2516      1.1  mrg 	  if (dst != NULL)
   2517      1.1  mrg 	    memptr = GFC_DESCRIPTOR_DATA (dst);
   2518      1.1  mrg 	  else
   2519      1.1  mrg 	    dst = src;
   2520      1.1  mrg 	  /* When the dst array needs to be allocated, then look at the
   2521      1.1  mrg 	     extent of the source array in the dimension dst_cur_dim.  */
   2522      1.1  mrg 	  for (i = 0; riter->u.a.mode[i] != CAF_ARR_REF_NONE; ++i)
   2523      1.1  mrg 	    {
   2524      1.1  mrg 	      switch (riter->u.a.mode[i])
   2525      1.1  mrg 		{
   2526      1.1  mrg 		case CAF_ARR_REF_VECTOR:
   2527      1.1  mrg 		  delta = riter->u.a.dim[i].v.nvec;
   2528      1.1  mrg #define KINDCASE(kind, type) case kind: \
   2529      1.1  mrg 		    memptr += (((index_type) \
   2530      1.1  mrg 			((type *)riter->u.a.dim[i].v.vector)[0]) \
   2531      1.1  mrg 			- GFC_DIMENSION_LBOUND (dst->dim[i])) \
   2532      1.1  mrg 			* GFC_DIMENSION_STRIDE (dst->dim[i]) \
   2533      1.1  mrg 			* riter->item_size; \
   2534      1.1  mrg 		    break
   2535      1.1  mrg 
   2536      1.1  mrg 		  switch (riter->u.a.dim[i].v.kind)
   2537      1.1  mrg 		    {
   2538      1.1  mrg 		    KINDCASE (1, GFC_INTEGER_1);
   2539      1.1  mrg 		    KINDCASE (2, GFC_INTEGER_2);
   2540      1.1  mrg 		    KINDCASE (4, GFC_INTEGER_4);
   2541      1.1  mrg #ifdef HAVE_GFC_INTEGER_8
   2542      1.1  mrg 		    KINDCASE (8, GFC_INTEGER_8);
   2543      1.1  mrg #endif
   2544      1.1  mrg #ifdef HAVE_GFC_INTEGER_16
   2545      1.1  mrg 		    KINDCASE (16, GFC_INTEGER_16);
   2546      1.1  mrg #endif
   2547      1.1  mrg 		    default:
   2548      1.1  mrg 		      caf_internal_error (vecrefunknownkind, stat, NULL, 0);
   2549      1.1  mrg 		      return;
   2550      1.1  mrg 		    }
   2551      1.1  mrg #undef KINDCASE
   2552      1.1  mrg 		  break;
   2553      1.1  mrg 		case CAF_ARR_REF_FULL:
   2554      1.1  mrg 		  if (dst)
   2555      1.1  mrg 		    COMPUTE_NUM_ITEMS (delta,
   2556      1.1  mrg 				       riter->u.a.dim[i].s.stride,
   2557      1.1  mrg 				       GFC_DIMENSION_LBOUND (dst->dim[i]),
   2558      1.1  mrg 				       GFC_DIMENSION_UBOUND (dst->dim[i]));
   2559      1.1  mrg 		  else
   2560      1.1  mrg 		    COMPUTE_NUM_ITEMS (delta,
   2561      1.1  mrg 				       riter->u.a.dim[i].s.stride,
   2562      1.1  mrg 				   GFC_DIMENSION_LBOUND (src->dim[src_cur_dim]),
   2563      1.1  mrg 				  GFC_DIMENSION_UBOUND (src->dim[src_cur_dim]));
   2564      1.1  mrg 		  break;
   2565      1.1  mrg 		case CAF_ARR_REF_RANGE:
   2566      1.1  mrg 		  COMPUTE_NUM_ITEMS (delta,
   2567      1.1  mrg 				     riter->u.a.dim[i].s.stride,
   2568      1.1  mrg 				     riter->u.a.dim[i].s.start,
   2569      1.1  mrg 				     riter->u.a.dim[i].s.end);
   2570      1.1  mrg 		  memptr += (riter->u.a.dim[i].s.start
   2571      1.1  mrg 			     - dst->dim[i].lower_bound)
   2572      1.1  mrg 		      * GFC_DIMENSION_STRIDE (dst->dim[i])
   2573      1.1  mrg 		      * riter->item_size;
   2574      1.1  mrg 		  break;
   2575      1.1  mrg 		case CAF_ARR_REF_SINGLE:
   2576      1.1  mrg 		  delta = 1;
   2577      1.1  mrg 		  memptr += (riter->u.a.dim[i].s.start
   2578      1.1  mrg 			     - dst->dim[i].lower_bound)
   2579      1.1  mrg 		      * GFC_DIMENSION_STRIDE (dst->dim[i])
   2580      1.1  mrg 		      * riter->item_size;
   2581      1.1  mrg 		  break;
   2582      1.1  mrg 		case CAF_ARR_REF_OPEN_END:
   2583      1.1  mrg 		  if (dst)
   2584      1.1  mrg 		    COMPUTE_NUM_ITEMS (delta,
   2585      1.1  mrg 				       riter->u.a.dim[i].s.stride,
   2586      1.1  mrg 				       riter->u.a.dim[i].s.start,
   2587      1.1  mrg 				       GFC_DIMENSION_UBOUND (dst->dim[i]));
   2588      1.1  mrg 		  else
   2589      1.1  mrg 		    COMPUTE_NUM_ITEMS (delta,
   2590      1.1  mrg 				       riter->u.a.dim[i].s.stride,
   2591      1.1  mrg 				       riter->u.a.dim[i].s.start,
   2592      1.1  mrg 				  GFC_DIMENSION_UBOUND (src->dim[src_cur_dim]));
   2593      1.1  mrg 		  memptr += (riter->u.a.dim[i].s.start
   2594      1.1  mrg 			     - dst->dim[i].lower_bound)
   2595      1.1  mrg 		      * GFC_DIMENSION_STRIDE (dst->dim[i])
   2596      1.1  mrg 		      * riter->item_size;
   2597      1.1  mrg 		  break;
   2598      1.1  mrg 		case CAF_ARR_REF_OPEN_START:
   2599      1.1  mrg 		  if (dst)
   2600      1.1  mrg 		    COMPUTE_NUM_ITEMS (delta,
   2601      1.1  mrg 				       riter->u.a.dim[i].s.stride,
   2602      1.1  mrg 				       GFC_DIMENSION_LBOUND (dst->dim[i]),
   2603      1.1  mrg 				       riter->u.a.dim[i].s.end);
   2604      1.1  mrg 		  else
   2605      1.1  mrg 		    COMPUTE_NUM_ITEMS (delta,
   2606      1.1  mrg 				       riter->u.a.dim[i].s.stride,
   2607      1.1  mrg 				   GFC_DIMENSION_LBOUND (src->dim[src_cur_dim]),
   2608      1.1  mrg 				       riter->u.a.dim[i].s.end);
   2609      1.1  mrg 		  /* The memptr stays unchanged when ref'ing the first element
   2610      1.1  mrg 		     in a dimension.  */
   2611      1.1  mrg 		  break;
   2612      1.1  mrg 		default:
   2613      1.1  mrg 		  caf_internal_error (unknownarrreftype, stat, NULL, 0);
   2614      1.1  mrg 		  return;
   2615      1.1  mrg 		}
   2616      1.1  mrg 
   2617      1.1  mrg 	      if (delta <= 0)
   2618      1.1  mrg 		return;
   2619      1.1  mrg 	      /* Check the various properties of the source array.
   2620      1.1  mrg 		 When src is an array.  */
   2621      1.1  mrg 	      if (delta > 1 && src_rank > 0)
   2622      1.1  mrg 		{
   2623      1.1  mrg 		  /* Check that src_cur_dim is valid for src.  Can be
   2624      1.1  mrg 		     superceeded only by scalar data.  */
   2625      1.1  mrg 		  if (src_cur_dim >= src_rank)
   2626      1.1  mrg 		    {
   2627      1.1  mrg 		      caf_internal_error (rankoutofrange, stat, NULL, 0);
   2628      1.1  mrg 		      return;
   2629      1.1  mrg 		    }
   2630      1.1  mrg 		  /* Do further checks, when the source is not scalar.  */
   2631      1.1  mrg 		  else
   2632      1.1  mrg 		    {
   2633      1.1  mrg 		      /* When the realloc is required, then no extent may have
   2634      1.1  mrg 			 been set.  */
   2635      1.1  mrg 		      extent_mismatch = memptr == NULL
   2636      1.1  mrg 			  || (dst
   2637      1.1  mrg 			      && GFC_DESCRIPTOR_EXTENT (dst, src_cur_dim)
   2638      1.1  mrg 			      != delta);
   2639      1.1  mrg 		      /* When it already known, that a realloc is needed or
   2640      1.1  mrg 			 the extent does not match the needed one.  */
   2641      1.1  mrg 		      if (extent_mismatch)
   2642      1.1  mrg 			{
   2643      1.1  mrg 			  /* Check whether dst is reallocatable.  */
   2644      1.1  mrg 			  if (unlikely (!dst_reallocatable))
   2645      1.1  mrg 			    {
   2646      1.1  mrg 			      caf_internal_error (nonallocextentmismatch, stat,
   2647      1.1  mrg 						  NULL, 0, delta,
   2648      1.1  mrg 						  GFC_DESCRIPTOR_EXTENT (dst,
   2649      1.1  mrg 								  src_cur_dim));
   2650      1.1  mrg 			      return;
   2651      1.1  mrg 			    }
   2652      1.1  mrg 			  /* Report error on allocatable but missing inner
   2653      1.1  mrg 			     ref.  */
   2654      1.1  mrg 			  else if (riter->next != NULL)
   2655      1.1  mrg 			    {
   2656      1.1  mrg 			      caf_internal_error (realloconinnerref, stat, NULL,
   2657      1.1  mrg 						  0);
   2658      1.1  mrg 			      return;
   2659      1.1  mrg 			    }
   2660      1.1  mrg 			}
   2661      1.1  mrg 		      /* Only change the extent when it does not match.  This is
   2662      1.1  mrg 			 to prevent resetting given array bounds.  */
   2663      1.1  mrg 		      if (extent_mismatch)
   2664      1.1  mrg 			GFC_DIMENSION_SET (dst->dim[src_cur_dim], 1, delta,
   2665      1.1  mrg 					   size);
   2666      1.1  mrg 		    }
   2667      1.1  mrg 		  /* Increase the dim-counter of the src only when the extent
   2668      1.1  mrg 		     matches.  */
   2669      1.1  mrg 		  if (src_cur_dim < src_rank
   2670      1.1  mrg 		      && GFC_DESCRIPTOR_EXTENT (src, src_cur_dim) == delta)
   2671      1.1  mrg 		    ++src_cur_dim;
   2672      1.1  mrg 		}
   2673      1.1  mrg 	      size *= (index_type)delta;
   2674      1.1  mrg 	    }
   2675      1.1  mrg 	  break;
   2676      1.1  mrg 	case CAF_REF_STATIC_ARRAY:
   2677      1.1  mrg 	  for (i = 0; riter->u.a.mode[i] != CAF_ARR_REF_NONE; ++i)
   2678      1.1  mrg 	    {
   2679      1.1  mrg 	      switch (riter->u.a.mode[i])
   2680      1.1  mrg 		{
   2681      1.1  mrg 		case CAF_ARR_REF_VECTOR:
   2682      1.1  mrg 		  delta = riter->u.a.dim[i].v.nvec;
   2683      1.1  mrg #define KINDCASE(kind, type) case kind: \
   2684      1.1  mrg 		    memptr += ((type *)riter->u.a.dim[i].v.vector)[0] \
   2685      1.1  mrg 			* riter->item_size; \
   2686      1.1  mrg 		    break
   2687      1.1  mrg 
   2688      1.1  mrg 		  switch (riter->u.a.dim[i].v.kind)
   2689      1.1  mrg 		    {
   2690      1.1  mrg 		    KINDCASE (1, GFC_INTEGER_1);
   2691      1.1  mrg 		    KINDCASE (2, GFC_INTEGER_2);
   2692      1.1  mrg 		    KINDCASE (4, GFC_INTEGER_4);
   2693      1.1  mrg #ifdef HAVE_GFC_INTEGER_8
   2694      1.1  mrg 		    KINDCASE (8, GFC_INTEGER_8);
   2695      1.1  mrg #endif
   2696      1.1  mrg #ifdef HAVE_GFC_INTEGER_16
   2697      1.1  mrg 		    KINDCASE (16, GFC_INTEGER_16);
   2698      1.1  mrg #endif
   2699      1.1  mrg 		    default:
   2700      1.1  mrg 		      caf_internal_error (vecrefunknownkind, stat, NULL, 0);
   2701      1.1  mrg 		      return;
   2702      1.1  mrg 		    }
   2703      1.1  mrg #undef KINDCASE
   2704      1.1  mrg 		  break;
   2705      1.1  mrg 		case CAF_ARR_REF_FULL:
   2706      1.1  mrg 		  delta = riter->u.a.dim[i].s.end / riter->u.a.dim[i].s.stride
   2707      1.1  mrg 		      + 1;
   2708      1.1  mrg 		  /* The memptr stays unchanged when ref'ing the first element
   2709      1.1  mrg 		     in a dimension.  */
   2710      1.1  mrg 		  break;
   2711      1.1  mrg 		case CAF_ARR_REF_RANGE:
   2712      1.1  mrg 		  COMPUTE_NUM_ITEMS (delta,
   2713      1.1  mrg 				     riter->u.a.dim[i].s.stride,
   2714      1.1  mrg 				     riter->u.a.dim[i].s.start,
   2715      1.1  mrg 				     riter->u.a.dim[i].s.end);
   2716      1.1  mrg 		  memptr += riter->u.a.dim[i].s.start
   2717      1.1  mrg 		      * riter->u.a.dim[i].s.stride
   2718      1.1  mrg 		      * riter->item_size;
   2719      1.1  mrg 		  break;
   2720      1.1  mrg 		case CAF_ARR_REF_SINGLE:
   2721      1.1  mrg 		  delta = 1;
   2722      1.1  mrg 		  memptr += riter->u.a.dim[i].s.start
   2723      1.1  mrg 		      * riter->u.a.dim[i].s.stride
   2724      1.1  mrg 		      * riter->item_size;
   2725      1.1  mrg 		  break;
   2726      1.1  mrg 		case CAF_ARR_REF_OPEN_END:
   2727      1.1  mrg 		  /* This and OPEN_START are mapped to a RANGE and therefore
   2728      1.1  mrg 		     cannot occur here.  */
   2729      1.1  mrg 		case CAF_ARR_REF_OPEN_START:
   2730      1.1  mrg 		default:
   2731      1.1  mrg 		  caf_internal_error (unknownarrreftype, stat, NULL, 0);
   2732      1.1  mrg 		  return;
   2733      1.1  mrg 		}
   2734      1.1  mrg 	      if (delta <= 0)
   2735      1.1  mrg 		return;
   2736      1.1  mrg 	      /* Check the various properties of the source array.
   2737      1.1  mrg 		 Only when the source array is not scalar examine its
   2738      1.1  mrg 		 properties.  */
   2739      1.1  mrg 	      if (delta > 1 && src_rank > 0)
   2740      1.1  mrg 		{
   2741      1.1  mrg 		  /* Check that src_cur_dim is valid for src.  Can be
   2742      1.1  mrg 		     superceeded only by scalar data.  */
   2743      1.1  mrg 		  if (src_cur_dim >= src_rank)
   2744      1.1  mrg 		    {
   2745      1.1  mrg 		      caf_internal_error (rankoutofrange, stat, NULL, 0);
   2746      1.1  mrg 		      return;
   2747      1.1  mrg 		    }
   2748      1.1  mrg 		  else
   2749      1.1  mrg 		    {
   2750      1.1  mrg 		      /* We will not be able to realloc the dst, because that's
   2751      1.1  mrg 			 a fixed size array.  */
   2752      1.1  mrg 		      extent_mismatch = GFC_DESCRIPTOR_EXTENT (src, src_cur_dim)
   2753      1.1  mrg 			      != delta;
   2754      1.1  mrg 		      /* When the extent does not match the needed one we can
   2755      1.1  mrg 			 only stop here.  */
   2756      1.1  mrg 		      if (extent_mismatch)
   2757      1.1  mrg 			{
   2758      1.1  mrg 			  caf_internal_error (nonallocextentmismatch, stat,
   2759      1.1  mrg 					      NULL, 0, delta,
   2760      1.1  mrg 					      GFC_DESCRIPTOR_EXTENT (src,
   2761      1.1  mrg 								  src_cur_dim));
   2762      1.1  mrg 			  return;
   2763      1.1  mrg 			}
   2764      1.1  mrg 		    }
   2765      1.1  mrg 		  ++src_cur_dim;
   2766      1.1  mrg 		}
   2767      1.1  mrg 	      size *= (index_type)delta;
   2768      1.1  mrg 	    }
   2769      1.1  mrg 	  break;
   2770      1.1  mrg 	default:
   2771      1.1  mrg 	  caf_internal_error (unknownreftype, stat, NULL, 0);
   2772      1.1  mrg 	  return;
   2773      1.1  mrg 	}
   2774      1.1  mrg       src_size = riter->item_size;
   2775      1.1  mrg       riter = riter->next;
   2776      1.1  mrg     }
   2777      1.1  mrg   if (size == 0 || src_size == 0)
   2778      1.1  mrg     return;
   2779      1.1  mrg   /* Postcondition:
   2780      1.1  mrg      - size contains the number of elements to store in the destination array,
   2781      1.1  mrg      - src_size gives the size in bytes of each item in the destination array.
   2782      1.1  mrg   */
   2783      1.1  mrg 
   2784      1.1  mrg   /* Reset the token.  */
   2785      1.1  mrg   single_token = TOKEN (token);
   2786      1.1  mrg   memptr = single_token->memptr;
   2787      1.1  mrg   dst = single_token->desc;
   2788      1.1  mrg   memset (dst_index, 0, sizeof (dst_index));
   2789      1.1  mrg   i = 0;
   2790      1.1  mrg   send_by_ref (refs, &i, dst_index, single_token, dst, src,
   2791      1.1  mrg 	       memptr, GFC_DESCRIPTOR_DATA (src), dst_kind, src_kind, 0, 0,
   2792      1.1  mrg 	       1, size, stat, dst_type);
   2793      1.1  mrg   assert (i == size);
   2794      1.1  mrg }
   2795      1.1  mrg 
   2796      1.1  mrg 
   2797      1.1  mrg void
   2798      1.1  mrg _gfortran_caf_sendget_by_ref (caf_token_t dst_token, int dst_image_index,
   2799      1.1  mrg 			      caf_reference_t *dst_refs, caf_token_t src_token,
   2800      1.1  mrg 			      int src_image_index,
   2801      1.1  mrg 			      caf_reference_t *src_refs, int dst_kind,
   2802      1.1  mrg 			      int src_kind, bool may_require_tmp, int *dst_stat,
   2803      1.1  mrg 			      int *src_stat, int dst_type, int src_type)
   2804      1.1  mrg {
   2805      1.1  mrg   GFC_FULL_ARRAY_DESCRIPTOR (GFC_MAX_DIMENSIONS, void) temp;
   2806      1.1  mrg   GFC_DESCRIPTOR_DATA (&temp) = NULL;
   2807      1.1  mrg   GFC_DESCRIPTOR_RANK (&temp) = -1;
   2808      1.1  mrg   GFC_DESCRIPTOR_TYPE (&temp) = dst_type;
   2809      1.1  mrg 
   2810      1.1  mrg   _gfortran_caf_get_by_ref (src_token, src_image_index,
   2811      1.1  mrg 			    (gfc_descriptor_t *) &temp, src_refs,
   2812      1.1  mrg 			    dst_kind, src_kind, may_require_tmp, true,
   2813      1.1  mrg 			    src_stat, src_type);
   2814      1.1  mrg 
   2815      1.1  mrg   if (src_stat && *src_stat != 0)
   2816      1.1  mrg     return;
   2817      1.1  mrg 
   2818      1.1  mrg   _gfortran_caf_send_by_ref (dst_token, dst_image_index,
   2819      1.1  mrg 			     (gfc_descriptor_t *) &temp, dst_refs,
   2820      1.1  mrg 			     dst_kind, dst_kind, may_require_tmp, true,
   2821      1.1  mrg 			     dst_stat, dst_type);
   2822      1.1  mrg   if (GFC_DESCRIPTOR_DATA (&temp))
   2823      1.1  mrg     free (GFC_DESCRIPTOR_DATA (&temp));
   2824      1.1  mrg }
   2825      1.1  mrg 
   2826      1.1  mrg 
   2827      1.1  mrg void
   2828      1.1  mrg _gfortran_caf_atomic_define (caf_token_t token, size_t offset,
   2829      1.1  mrg 			     int image_index __attribute__ ((unused)),
   2830      1.1  mrg 			     void *value, int *stat,
   2831      1.1  mrg 			     int type __attribute__ ((unused)), int kind)
   2832      1.1  mrg {
   2833      1.1  mrg   assert(kind == 4);
   2834      1.1  mrg 
   2835      1.1  mrg   uint32_t *atom = (uint32_t *) ((char *) MEMTOK (token) + offset);
   2836      1.1  mrg 
   2837      1.1  mrg   __atomic_store (atom, (uint32_t *) value, __ATOMIC_RELAXED);
   2838      1.1  mrg 
   2839      1.1  mrg   if (stat)
   2840      1.1  mrg     *stat = 0;
   2841      1.1  mrg }
   2842      1.1  mrg 
   2843      1.1  mrg void
   2844      1.1  mrg _gfortran_caf_atomic_ref (caf_token_t token, size_t offset,
   2845      1.1  mrg 			  int image_index __attribute__ ((unused)),
   2846      1.1  mrg 			  void *value, int *stat,
   2847      1.1  mrg 			  int type __attribute__ ((unused)), int kind)
   2848      1.1  mrg {
   2849      1.1  mrg   assert(kind == 4);
   2850      1.1  mrg 
   2851      1.1  mrg   uint32_t *atom = (uint32_t *) ((char *) MEMTOK (token) + offset);
   2852      1.1  mrg 
   2853      1.1  mrg   __atomic_load (atom, (uint32_t *) value, __ATOMIC_RELAXED);
   2854      1.1  mrg 
   2855      1.1  mrg   if (stat)
   2856      1.1  mrg     *stat = 0;
   2857      1.1  mrg }
   2858      1.1  mrg 
   2859      1.1  mrg 
   2860      1.1  mrg void
   2861      1.1  mrg _gfortran_caf_atomic_cas (caf_token_t token, size_t offset,
   2862      1.1  mrg 			  int image_index __attribute__ ((unused)),
   2863      1.1  mrg 			  void *old, void *compare, void *new_val, int *stat,
   2864      1.1  mrg 			  int type __attribute__ ((unused)), int kind)
   2865      1.1  mrg {
   2866      1.1  mrg   assert(kind == 4);
   2867      1.1  mrg 
   2868      1.1  mrg   uint32_t *atom = (uint32_t *) ((char *) MEMTOK (token) + offset);
   2869      1.1  mrg 
   2870      1.1  mrg   *(uint32_t *) old = *(uint32_t *) compare;
   2871      1.1  mrg   (void) __atomic_compare_exchange_n (atom, (uint32_t *) old,
   2872      1.1  mrg 				      *(uint32_t *) new_val, false,
   2873      1.1  mrg 				      __ATOMIC_RELAXED, __ATOMIC_RELAXED);
   2874      1.1  mrg   if (stat)
   2875      1.1  mrg     *stat = 0;
   2876      1.1  mrg }
   2877      1.1  mrg 
   2878      1.1  mrg 
   2879      1.1  mrg void
   2880      1.1  mrg _gfortran_caf_atomic_op (int op, caf_token_t token, size_t offset,
   2881      1.1  mrg 			 int image_index __attribute__ ((unused)),
   2882      1.1  mrg 			 void *value, void *old, int *stat,
   2883      1.1  mrg 			 int type __attribute__ ((unused)), int kind)
   2884      1.1  mrg {
   2885      1.1  mrg   assert(kind == 4);
   2886      1.1  mrg 
   2887      1.1  mrg   uint32_t res;
   2888      1.1  mrg   uint32_t *atom = (uint32_t *) ((char *) MEMTOK (token) + offset);
   2889      1.1  mrg 
   2890      1.1  mrg   switch (op)
   2891      1.1  mrg     {
   2892      1.1  mrg     case GFC_CAF_ATOMIC_ADD:
   2893      1.1  mrg       res = __atomic_fetch_add (atom, *(uint32_t *) value, __ATOMIC_RELAXED);
   2894      1.1  mrg       break;
   2895      1.1  mrg     case GFC_CAF_ATOMIC_AND:
   2896      1.1  mrg       res = __atomic_fetch_and (atom, *(uint32_t *) value, __ATOMIC_RELAXED);
   2897      1.1  mrg       break;
   2898      1.1  mrg     case GFC_CAF_ATOMIC_OR:
   2899      1.1  mrg       res = __atomic_fetch_or (atom, *(uint32_t *) value, __ATOMIC_RELAXED);
   2900      1.1  mrg       break;
   2901      1.1  mrg     case GFC_CAF_ATOMIC_XOR:
   2902      1.1  mrg       res = __atomic_fetch_xor (atom, *(uint32_t *) value, __ATOMIC_RELAXED);
   2903      1.1  mrg       break;
   2904      1.1  mrg     default:
   2905      1.1  mrg       __builtin_unreachable();
   2906      1.1  mrg     }
   2907      1.1  mrg 
   2908      1.1  mrg   if (old)
   2909      1.1  mrg     *(uint32_t *) old = res;
   2910      1.1  mrg 
   2911      1.1  mrg   if (stat)
   2912      1.1  mrg     *stat = 0;
   2913      1.1  mrg }
   2914      1.1  mrg 
   2915      1.1  mrg void
   2916      1.1  mrg _gfortran_caf_event_post (caf_token_t token, size_t index,
   2917      1.1  mrg 			  int image_index __attribute__ ((unused)),
   2918      1.1  mrg 			  int *stat, char *errmsg __attribute__ ((unused)),
   2919      1.1  mrg 			  size_t errmsg_len __attribute__ ((unused)))
   2920      1.1  mrg {
   2921      1.1  mrg   uint32_t value = 1;
   2922      1.1  mrg   uint32_t *event = (uint32_t *) ((char *) MEMTOK (token) + index
   2923      1.1  mrg 				  * sizeof (uint32_t));
   2924      1.1  mrg   __atomic_fetch_add (event, (uint32_t) value, __ATOMIC_RELAXED);
   2925      1.1  mrg 
   2926      1.1  mrg   if(stat)
   2927      1.1  mrg     *stat = 0;
   2928      1.1  mrg }
   2929      1.1  mrg 
   2930      1.1  mrg void
   2931      1.1  mrg _gfortran_caf_event_wait (caf_token_t token, size_t index,
   2932      1.1  mrg 			  int until_count, int *stat,
   2933      1.1  mrg 			  char *errmsg __attribute__ ((unused)),
   2934      1.1  mrg 			  size_t errmsg_len __attribute__ ((unused)))
   2935      1.1  mrg {
   2936      1.1  mrg   uint32_t *event = (uint32_t *) ((char *) MEMTOK (token) + index
   2937      1.1  mrg 				  * sizeof (uint32_t));
   2938      1.1  mrg   uint32_t value = (uint32_t)-until_count;
   2939      1.1  mrg    __atomic_fetch_add (event, (uint32_t) value, __ATOMIC_RELAXED);
   2940      1.1  mrg 
   2941      1.1  mrg    if(stat)
   2942      1.1  mrg     *stat = 0;
   2943      1.1  mrg }
   2944      1.1  mrg 
   2945      1.1  mrg void
   2946      1.1  mrg _gfortran_caf_event_query (caf_token_t token, size_t index,
   2947      1.1  mrg 			   int image_index __attribute__ ((unused)),
   2948      1.1  mrg 			   int *count, int *stat)
   2949      1.1  mrg {
   2950      1.1  mrg   uint32_t *event = (uint32_t *) ((char *) MEMTOK (token) + index
   2951      1.1  mrg 				  * sizeof (uint32_t));
   2952      1.1  mrg   __atomic_load (event, (uint32_t *) count, __ATOMIC_RELAXED);
   2953      1.1  mrg 
   2954      1.1  mrg   if(stat)
   2955      1.1  mrg     *stat = 0;
   2956      1.1  mrg }
   2957      1.1  mrg 
   2958      1.1  mrg void
   2959      1.1  mrg _gfortran_caf_lock (caf_token_t token, size_t index,
   2960      1.1  mrg 		    int image_index __attribute__ ((unused)),
   2961  1.1.1.3  mrg 		    int *acquired_lock, int *stat, char *errmsg,
   2962  1.1.1.3  mrg 		    size_t errmsg_len)
   2963      1.1  mrg {
   2964      1.1  mrg   const char *msg = "Already locked";
   2965      1.1  mrg   bool *lock = &((bool *) MEMTOK (token))[index];
   2966      1.1  mrg 
   2967      1.1  mrg   if (!*lock)
   2968      1.1  mrg     {
   2969      1.1  mrg       *lock = true;
   2970  1.1.1.3  mrg       if (acquired_lock)
   2971  1.1.1.3  mrg 	*acquired_lock = (int) true;
   2972      1.1  mrg       if (stat)
   2973      1.1  mrg 	*stat = 0;
   2974      1.1  mrg       return;
   2975      1.1  mrg     }
   2976      1.1  mrg 
   2977  1.1.1.3  mrg   if (acquired_lock)
   2978      1.1  mrg     {
   2979  1.1.1.3  mrg       *acquired_lock = (int) false;
   2980      1.1  mrg       if (stat)
   2981      1.1  mrg 	*stat = 0;
   2982      1.1  mrg     return;
   2983      1.1  mrg     }
   2984      1.1  mrg 
   2985      1.1  mrg 
   2986      1.1  mrg   if (stat)
   2987      1.1  mrg     {
   2988      1.1  mrg       *stat = 1;
   2989      1.1  mrg       if (errmsg_len > 0)
   2990      1.1  mrg 	{
   2991      1.1  mrg 	  size_t len = (sizeof (msg) > errmsg_len) ? errmsg_len
   2992      1.1  mrg 						      : sizeof (msg);
   2993      1.1  mrg 	  memcpy (errmsg, msg, len);
   2994      1.1  mrg 	  if (errmsg_len > len)
   2995      1.1  mrg 	    memset (&errmsg[len], ' ', errmsg_len-len);
   2996      1.1  mrg 	}
   2997      1.1  mrg       return;
   2998      1.1  mrg     }
   2999      1.1  mrg   _gfortran_caf_error_stop_str (msg, strlen (msg), false);
   3000      1.1  mrg }
   3001      1.1  mrg 
   3002      1.1  mrg 
   3003      1.1  mrg void
   3004      1.1  mrg _gfortran_caf_unlock (caf_token_t token, size_t index,
   3005      1.1  mrg 		      int image_index __attribute__ ((unused)),
   3006      1.1  mrg 		      int *stat, char *errmsg, size_t errmsg_len)
   3007      1.1  mrg {
   3008      1.1  mrg   const char *msg = "Variable is not locked";
   3009      1.1  mrg   bool *lock = &((bool *) MEMTOK (token))[index];
   3010      1.1  mrg 
   3011      1.1  mrg   if (*lock)
   3012      1.1  mrg     {
   3013      1.1  mrg       *lock = false;
   3014      1.1  mrg       if (stat)
   3015      1.1  mrg 	*stat = 0;
   3016      1.1  mrg       return;
   3017      1.1  mrg     }
   3018      1.1  mrg 
   3019      1.1  mrg   if (stat)
   3020      1.1  mrg     {
   3021      1.1  mrg       *stat = 1;
   3022      1.1  mrg       if (errmsg_len > 0)
   3023      1.1  mrg 	{
   3024      1.1  mrg 	  size_t len = (sizeof (msg) > errmsg_len) ? errmsg_len
   3025      1.1  mrg 	    : sizeof (msg);
   3026      1.1  mrg 	  memcpy (errmsg, msg, len);
   3027      1.1  mrg 	  if (errmsg_len > len)
   3028      1.1  mrg 	    memset (&errmsg[len], ' ', errmsg_len-len);
   3029      1.1  mrg 	}
   3030      1.1  mrg       return;
   3031      1.1  mrg     }
   3032      1.1  mrg   _gfortran_caf_error_stop_str (msg, strlen (msg), false);
   3033      1.1  mrg }
   3034      1.1  mrg 
   3035      1.1  mrg int
   3036      1.1  mrg _gfortran_caf_is_present (caf_token_t token,
   3037      1.1  mrg 			  int image_index __attribute__ ((unused)),
   3038      1.1  mrg 			  caf_reference_t *refs)
   3039      1.1  mrg {
   3040      1.1  mrg   const char arraddressingnotallowed[] = "libcaf_single::caf_is_present(): "
   3041      1.1  mrg 				   "only scalar indexes allowed.\n";
   3042      1.1  mrg   const char unknownreftype[] = "libcaf_single::caf_get_by_ref(): "
   3043      1.1  mrg 				"unknown reference type.\n";
   3044      1.1  mrg   const char unknownarrreftype[] = "libcaf_single::caf_get_by_ref(): "
   3045      1.1  mrg 				   "unknown array reference type.\n";
   3046      1.1  mrg   size_t i;
   3047      1.1  mrg   caf_single_token_t single_token = TOKEN (token);
   3048      1.1  mrg   void *memptr = single_token->memptr;
   3049      1.1  mrg   gfc_descriptor_t *src = single_token->desc;
   3050      1.1  mrg   caf_reference_t *riter = refs;
   3051      1.1  mrg 
   3052      1.1  mrg   while (riter)
   3053      1.1  mrg     {
   3054      1.1  mrg       switch (riter->type)
   3055      1.1  mrg 	{
   3056      1.1  mrg 	case CAF_REF_COMPONENT:
   3057      1.1  mrg 	  if (riter->u.c.caf_token_offset)
   3058      1.1  mrg 	    {
   3059      1.1  mrg 	      single_token = *(caf_single_token_t*)
   3060      1.1  mrg 					 (memptr + riter->u.c.caf_token_offset);
   3061      1.1  mrg 	      memptr = single_token->memptr;
   3062      1.1  mrg 	      src = single_token->desc;
   3063      1.1  mrg 	    }
   3064      1.1  mrg 	  else
   3065      1.1  mrg 	    {
   3066      1.1  mrg 	      memptr += riter->u.c.offset;
   3067      1.1  mrg 	      src = (gfc_descriptor_t *)memptr;
   3068      1.1  mrg 	    }
   3069      1.1  mrg 	  break;
   3070      1.1  mrg 	case CAF_REF_ARRAY:
   3071      1.1  mrg 	  for (i = 0; riter->u.a.mode[i] != CAF_ARR_REF_NONE; ++i)
   3072      1.1  mrg 	    {
   3073      1.1  mrg 	      switch (riter->u.a.mode[i])
   3074      1.1  mrg 		{
   3075      1.1  mrg 		case CAF_ARR_REF_SINGLE:
   3076      1.1  mrg 		  memptr += (riter->u.a.dim[i].s.start
   3077      1.1  mrg 			     - GFC_DIMENSION_LBOUND (src->dim[i]))
   3078      1.1  mrg 		      * GFC_DIMENSION_STRIDE (src->dim[i])
   3079      1.1  mrg 		      * riter->item_size;
   3080      1.1  mrg 		  break;
   3081      1.1  mrg 		case CAF_ARR_REF_FULL:
   3082      1.1  mrg 		  /* A full array ref is allowed on the last reference only.  */
   3083      1.1  mrg 		  if (riter->next == NULL)
   3084      1.1  mrg 		    break;
   3085      1.1  mrg 		  /* else fall through reporting an error.  */
   3086      1.1  mrg 		  /* FALLTHROUGH */
   3087      1.1  mrg 		case CAF_ARR_REF_VECTOR:
   3088      1.1  mrg 		case CAF_ARR_REF_RANGE:
   3089      1.1  mrg 		case CAF_ARR_REF_OPEN_END:
   3090      1.1  mrg 		case CAF_ARR_REF_OPEN_START:
   3091      1.1  mrg 		  caf_internal_error (arraddressingnotallowed, 0, NULL, 0);
   3092      1.1  mrg 		  return 0;
   3093      1.1  mrg 		default:
   3094      1.1  mrg 		  caf_internal_error (unknownarrreftype, 0, NULL, 0);
   3095      1.1  mrg 		  return 0;
   3096      1.1  mrg 		}
   3097      1.1  mrg 	    }
   3098      1.1  mrg 	  break;
   3099      1.1  mrg 	case CAF_REF_STATIC_ARRAY:
   3100      1.1  mrg 	  for (i = 0; riter->u.a.mode[i] != CAF_ARR_REF_NONE; ++i)
   3101      1.1  mrg 	    {
   3102      1.1  mrg 	      switch (riter->u.a.mode[i])
   3103      1.1  mrg 		{
   3104      1.1  mrg 		case CAF_ARR_REF_SINGLE:
   3105      1.1  mrg 		  memptr += riter->u.a.dim[i].s.start
   3106      1.1  mrg 		      * riter->u.a.dim[i].s.stride
   3107      1.1  mrg 		      * riter->item_size;
   3108      1.1  mrg 		  break;
   3109      1.1  mrg 		case CAF_ARR_REF_FULL:
   3110      1.1  mrg 		  /* A full array ref is allowed on the last reference only.  */
   3111      1.1  mrg 		  if (riter->next == NULL)
   3112      1.1  mrg 		    break;
   3113      1.1  mrg 		  /* else fall through reporting an error.  */
   3114      1.1  mrg 		  /* FALLTHROUGH */
   3115      1.1  mrg 		case CAF_ARR_REF_VECTOR:
   3116      1.1  mrg 		case CAF_ARR_REF_RANGE:
   3117      1.1  mrg 		case CAF_ARR_REF_OPEN_END:
   3118      1.1  mrg 		case CAF_ARR_REF_OPEN_START:
   3119      1.1  mrg 		  caf_internal_error (arraddressingnotallowed, 0, NULL, 0);
   3120      1.1  mrg 		  return 0;
   3121      1.1  mrg 		default:
   3122      1.1  mrg 		  caf_internal_error (unknownarrreftype, 0, NULL, 0);
   3123      1.1  mrg 		  return 0;
   3124      1.1  mrg 		}
   3125      1.1  mrg 	    }
   3126      1.1  mrg 	  break;
   3127      1.1  mrg 	default:
   3128      1.1  mrg 	  caf_internal_error (unknownreftype, 0, NULL, 0);
   3129      1.1  mrg 	  return 0;
   3130      1.1  mrg 	}
   3131      1.1  mrg       riter = riter->next;
   3132      1.1  mrg     }
   3133      1.1  mrg   return memptr != NULL;
   3134      1.1  mrg }
   3135  1.1.1.3  mrg 
   3136  1.1.1.3  mrg /* Reference the libraries implementation.  */
   3137  1.1.1.3  mrg extern void _gfortran_random_init (int32_t, int32_t, int32_t);
   3138  1.1.1.3  mrg 
   3139  1.1.1.3  mrg void _gfortran_caf_random_init (bool repeatable, bool image_distinct)
   3140  1.1.1.3  mrg {
   3141  1.1.1.3  mrg   /* In a single image implementation always forward to the gfortran
   3142  1.1.1.3  mrg      routine.  */
   3143  1.1.1.3  mrg   _gfortran_random_init (repeatable, image_distinct, 1);
   3144  1.1.1.3  mrg }
   3145