single.c revision 1.1.1.3 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