annotate libgfortran/caf/single.c @ 111:04ced10e8804

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