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