]> git.ipfire.org Git - thirdparty/gcc.git/blob - libgfortran/runtime/ISO_Fortran_binding.c
Update copyright years.
[thirdparty/gcc.git] / libgfortran / runtime / ISO_Fortran_binding.c
1 /* Functions to convert descriptors between CFI and gfortran
2 and the CFI function declarations whose prototypes appear
3 in ISO_Fortran_binding.h.
4 Copyright (C) 2018-2022 Free Software Foundation, Inc.
5 Contributed by Daniel Celis Garza <celisdanieljr@gmail.com>
6 and Paul Thomas <pault@gcc.gnu.org>
7
8 This file is part of the GNU Fortran runtime library (libgfortran).
9
10 Libgfortran is free software; you can redistribute it and/or
11 modify it under the terms of the GNU General Public
12 License as published by the Free Software Foundation; either
13 version 3 of the License, or (at your option) any later version.
14
15 Libgfortran is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
19
20 Under Section 7 of GPL version 3, you are granted additional
21 permissions described in the GCC Runtime Library Exception, version
22 3.1, as published by the Free Software Foundation.
23
24 You should have received a copy of the GNU General Public License and
25 a copy of the GCC Runtime Library Exception along with this program;
26 see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
27 <http://www.gnu.org/licenses/>. */
28
29 #include "libgfortran.h"
30 #include "ISO_Fortran_binding.h"
31 #include <string.h>
32 #include <inttypes.h> /* for PRIiPTR */
33
34 extern void cfi_desc_to_gfc_desc (gfc_array_void *, CFI_cdesc_t **);
35 export_proto(cfi_desc_to_gfc_desc);
36
37 /* NOTE: Since GCC 12, the FE generates code to do the conversion
38 directly without calling this function. */
39 void
40 cfi_desc_to_gfc_desc (gfc_array_void *d, CFI_cdesc_t **s_ptr)
41 {
42 signed char type;
43 size_t size;
44 int n;
45 CFI_cdesc_t *s = *s_ptr;
46
47 if (!s)
48 return;
49
50 /* Verify descriptor. */
51 switch (s->attribute)
52 {
53 case CFI_attribute_pointer:
54 case CFI_attribute_allocatable:
55 break;
56 case CFI_attribute_other:
57 if (s->base_addr)
58 break;
59 runtime_error ("Nonallocatable, nonpointer actual argument to BIND(C) "
60 "dummy argument where the effective argument is either "
61 "not allocated or not associated");
62 break;
63 default:
64 runtime_error ("Invalid attribute type %d in CFI_cdesc_t descriptor",
65 (int) s->attribute);
66 break;
67 }
68 GFC_DESCRIPTOR_DATA (d) = s->base_addr;
69
70 /* Correct the unfortunate difference in order with types. */
71 type = (signed char)(s->type & CFI_type_mask);
72 switch (type)
73 {
74 case CFI_type_Character:
75 type = BT_CHARACTER;
76 break;
77 case CFI_type_struct:
78 type = BT_DERIVED;
79 break;
80 case CFI_type_cptr:
81 /* FIXME: PR 100915. GFC descriptors do not distinguish between
82 CFI_type_cptr and CFI_type_cfunptr. */
83 type = BT_VOID;
84 break;
85 default:
86 break;
87 }
88
89 GFC_DESCRIPTOR_TYPE (d) = type;
90 GFC_DESCRIPTOR_SIZE (d) = s->elem_len;
91
92 d->dtype.version = 0;
93
94 if (s->rank < 0 || s->rank > CFI_MAX_RANK)
95 internal_error (NULL, "Invalid rank in descriptor");
96 GFC_DESCRIPTOR_RANK (d) = (signed char)s->rank;
97
98 d->dtype.attribute = (signed short)s->attribute;
99
100 if (s->rank)
101 {
102 if ((size_t)s->dim[0].sm % s->elem_len)
103 d->span = (index_type)s->dim[0].sm;
104 else
105 d->span = (index_type)s->elem_len;
106 }
107
108 d->offset = 0;
109 if (GFC_DESCRIPTOR_DATA (d))
110 for (n = 0; n < GFC_DESCRIPTOR_RANK (d); n++)
111 {
112 CFI_index_t lb = 1;
113
114 if (s->attribute != CFI_attribute_other)
115 lb = s->dim[n].lower_bound;
116
117 GFC_DESCRIPTOR_LBOUND(d, n) = (index_type)lb;
118 GFC_DESCRIPTOR_UBOUND(d, n) = (index_type)(s->dim[n].extent + lb - 1);
119 GFC_DESCRIPTOR_STRIDE(d, n) = (index_type)(s->dim[n].sm / s->elem_len);
120 d->offset -= GFC_DESCRIPTOR_STRIDE(d, n) * GFC_DESCRIPTOR_LBOUND(d, n);
121 }
122 }
123
124 extern void gfc_desc_to_cfi_desc (CFI_cdesc_t **, const gfc_array_void *);
125 export_proto(gfc_desc_to_cfi_desc);
126
127 /* NOTE: Since GCC 12, the FE generates code to do the conversion
128 directly without calling this function. */
129 void
130 gfc_desc_to_cfi_desc (CFI_cdesc_t **d_ptr, const gfc_array_void *s)
131 {
132 int n;
133 CFI_cdesc_t *d;
134 signed char type, kind;
135
136 /* Play it safe with allocation of the flexible array member 'dim'
137 by setting the length to CFI_MAX_RANK. This should not be necessary
138 but valgrind complains accesses after the allocated block. */
139 if (*d_ptr == NULL)
140 d = calloc (1, (sizeof (CFI_cdesc_t)
141 + (CFI_type_t)(CFI_MAX_RANK * sizeof (CFI_dim_t))));
142 else
143 d = *d_ptr;
144
145 /* Verify descriptor. */
146 switch (s->dtype.attribute)
147 {
148 case CFI_attribute_pointer:
149 case CFI_attribute_allocatable:
150 break;
151 case CFI_attribute_other:
152 if (s->base_addr)
153 break;
154 runtime_error ("Nonallocatable, nonpointer actual argument to BIND(C) "
155 "dummy argument where the effective argument is either "
156 "not allocated or not associated");
157 break;
158 default:
159 internal_error (NULL, "Invalid attribute in gfc_array descriptor");
160 break;
161 }
162 d->base_addr = GFC_DESCRIPTOR_DATA (s);
163 d->elem_len = GFC_DESCRIPTOR_SIZE (s);
164 if (d->elem_len <= 0)
165 internal_error (NULL, "Invalid size in descriptor");
166
167 d->version = CFI_VERSION;
168
169 d->rank = (CFI_rank_t)GFC_DESCRIPTOR_RANK (s);
170 if (d->rank < 0 || d->rank > CFI_MAX_RANK)
171 internal_error (NULL, "Invalid rank in descriptor");
172
173 d->attribute = (CFI_attribute_t)s->dtype.attribute;
174
175 type = GFC_DESCRIPTOR_TYPE (s);
176 switch (type)
177 {
178 case BT_CHARACTER:
179 d->type = CFI_type_Character;
180 break;
181 case BT_DERIVED:
182 d->type = CFI_type_struct;
183 break;
184 case BT_VOID:
185 /* FIXME: PR 100915. GFC descriptors do not distinguish between
186 CFI_type_cptr and CFI_type_cfunptr. */
187 d->type = CFI_type_cptr;
188 break;
189 default:
190 d->type = (CFI_type_t)type;
191 break;
192 }
193
194 switch (d->type)
195 {
196 case CFI_type_Integer:
197 case CFI_type_Logical:
198 case CFI_type_Real:
199 kind = (signed char)d->elem_len;
200 break;
201 case CFI_type_Complex:
202 kind = (signed char)(d->elem_len >> 1);
203 break;
204 case CFI_type_Character:
205 /* FIXME: we can't distinguish between kind/len because
206 the GFC descriptor only encodes the elem_len..
207 Until PR92482 is fixed, assume elem_len refers to the
208 character size and not the string length. */
209 kind = (signed char)d->elem_len;
210 break;
211 case CFI_type_struct:
212 case CFI_type_cptr:
213 case CFI_type_other:
214 /* FIXME: PR 100915. GFC descriptors do not distinguish between
215 CFI_type_cptr and CFI_type_cfunptr. */
216 kind = 0;
217 break;
218 default:
219 internal_error (NULL, "Invalid type in descriptor");
220 }
221
222 if (kind < 0)
223 internal_error (NULL, "Invalid kind in descriptor");
224
225 /* FIXME: This is PR100917. Because the GFC descriptor encodes only the
226 elem_len and not the kind, we get into trouble with long double kinds
227 that do not correspond directly to the elem_len, specifically the
228 kind 10 80-bit long double on x86 targets. On x86_64, this has size
229 16 and cannot be differentiated from true _Float128. Prefer the
230 standard long double type over the GNU extension in that case. */
231 if (d->type == CFI_type_Real && kind == sizeof (long double))
232 d->type = CFI_type_long_double;
233 else if (d->type == CFI_type_Complex && kind == sizeof (long double))
234 d->type = CFI_type_long_double_Complex;
235 else
236 d->type = (CFI_type_t)(d->type
237 + ((CFI_type_t)kind << CFI_type_kind_shift));
238
239 if (d->base_addr)
240 /* Full pointer or allocatable arrays retain their lower_bounds. */
241 for (n = 0; n < GFC_DESCRIPTOR_RANK (s); n++)
242 {
243 if (d->attribute != CFI_attribute_other)
244 d->dim[n].lower_bound = (CFI_index_t)GFC_DESCRIPTOR_LBOUND(s, n);
245 else
246 d->dim[n].lower_bound = 0;
247
248 /* Assumed size arrays have gfc ubound == 0 and CFI extent = -1. */
249 if (n == GFC_DESCRIPTOR_RANK (s) - 1
250 && GFC_DESCRIPTOR_LBOUND(s, n) == 1
251 && GFC_DESCRIPTOR_UBOUND(s, n) == 0)
252 d->dim[n].extent = -1;
253 else
254 d->dim[n].extent = (CFI_index_t)GFC_DESCRIPTOR_UBOUND(s, n)
255 - (CFI_index_t)GFC_DESCRIPTOR_LBOUND(s, n) + 1;
256 d->dim[n].sm = (CFI_index_t)(GFC_DESCRIPTOR_STRIDE(s, n) * s->span);
257 }
258
259 if (*d_ptr == NULL)
260 *d_ptr = d;
261 }
262
263 void *CFI_address (const CFI_cdesc_t *dv, const CFI_index_t subscripts[])
264 {
265 int i;
266 char *base_addr = (char *)dv->base_addr;
267
268 if (unlikely (compile_options.bounds_check))
269 {
270 /* C descriptor must not be NULL. */
271 if (dv == NULL)
272 {
273 fprintf (stderr, "CFI_address: C descriptor is NULL.\n");
274 return NULL;
275 }
276
277 /* Base address of C descriptor must not be NULL. */
278 if (dv->base_addr == NULL)
279 {
280 fprintf (stderr, "CFI_address: base address of C descriptor "
281 "must not be NULL.\n");
282 return NULL;
283 }
284 }
285
286 /* Return base address if C descriptor is a scalar. */
287 if (dv->rank == 0)
288 return dv->base_addr;
289
290 /* Calculate the appropriate base address if dv is not a scalar. */
291 else
292 {
293 /* Base address is the C address of the element of the object
294 specified by subscripts. */
295 for (i = 0; i < dv->rank; i++)
296 {
297 CFI_index_t idx = subscripts[i] - dv->dim[i].lower_bound;
298 if (unlikely (compile_options.bounds_check)
299 && ((dv->dim[i].extent != -1 && idx >= dv->dim[i].extent)
300 || idx < 0))
301 {
302 fprintf (stderr, "CFI_address: subscripts[%d] is out of "
303 "bounds. For dimension = %d, subscripts = %d, "
304 "lower_bound = %" PRIiPTR ", upper bound = %" PRIiPTR
305 ", extent = %" PRIiPTR "\n",
306 i, i, (int)subscripts[i],
307 (ptrdiff_t)dv->dim[i].lower_bound,
308 (ptrdiff_t)(dv->dim[i].extent - dv->dim[i].lower_bound),
309 (ptrdiff_t)dv->dim[i].extent);
310 return NULL;
311 }
312
313 base_addr = base_addr + (CFI_index_t)(idx * dv->dim[i].sm);
314 }
315 }
316
317 return (void *)base_addr;
318 }
319
320
321 int
322 CFI_allocate (CFI_cdesc_t *dv, const CFI_index_t lower_bounds[],
323 const CFI_index_t upper_bounds[], size_t elem_len)
324 {
325 if (unlikely (compile_options.bounds_check))
326 {
327 /* C descriptor must not be NULL. */
328 if (dv == NULL)
329 {
330 fprintf (stderr, "CFI_allocate: C descriptor is NULL.\n");
331 return CFI_INVALID_DESCRIPTOR;
332 }
333
334 /* The C descriptor must be for an allocatable or pointer object. */
335 if (dv->attribute == CFI_attribute_other)
336 {
337 fprintf (stderr, "CFI_allocate: The object of the C descriptor "
338 "must be a pointer or allocatable variable.\n");
339 return CFI_INVALID_ATTRIBUTE;
340 }
341
342 /* Base address of C descriptor must be NULL. */
343 if (dv->base_addr != NULL)
344 {
345 fprintf (stderr, "CFI_allocate: Base address of C descriptor "
346 "must be NULL.\n");
347 return CFI_ERROR_BASE_ADDR_NOT_NULL;
348 }
349 }
350
351 /* If the type is a Fortran character type, the descriptor's element
352 length is replaced by the elem_len argument. */
353 if (dv->type == CFI_type_char || dv->type == CFI_type_ucs4_char)
354 dv->elem_len = elem_len;
355
356 /* Dimension information and calculating the array length. */
357 size_t arr_len = 1;
358
359 /* If rank is greater than 0, lower_bounds and upper_bounds are used. They're
360 ignored otherwise. */
361 if (dv->rank > 0)
362 {
363 if (unlikely (compile_options.bounds_check)
364 && (lower_bounds == NULL || upper_bounds == NULL))
365 {
366 fprintf (stderr, "CFI_allocate: The lower_bounds and "
367 "upper_bounds arguments must be non-NULL when "
368 "rank is greater than zero.\n");
369 return CFI_INVALID_EXTENT;
370 }
371
372 for (int i = 0; i < dv->rank; i++)
373 {
374 dv->dim[i].lower_bound = lower_bounds[i];
375 dv->dim[i].extent = upper_bounds[i] - dv->dim[i].lower_bound + 1;
376 dv->dim[i].sm = dv->elem_len * arr_len;
377 arr_len *= dv->dim[i].extent;
378 }
379 }
380
381 dv->base_addr = calloc (arr_len, dv->elem_len);
382 if (dv->base_addr == NULL)
383 {
384 fprintf (stderr, "CFI_allocate: Failure in memory allocation.\n");
385 return CFI_ERROR_MEM_ALLOCATION;
386 }
387
388 return CFI_SUCCESS;
389 }
390
391
392 int
393 CFI_deallocate (CFI_cdesc_t *dv)
394 {
395 if (unlikely (compile_options.bounds_check))
396 {
397 /* C descriptor must not be NULL */
398 if (dv == NULL)
399 {
400 fprintf (stderr, "CFI_deallocate: C descriptor is NULL.\n");
401 return CFI_INVALID_DESCRIPTOR;
402 }
403
404 /* Base address must not be NULL. */
405 if (dv->base_addr == NULL)
406 {
407 fprintf (stderr, "CFI_deallocate: Base address is already NULL.\n");
408 return CFI_ERROR_BASE_ADDR_NULL;
409 }
410
411 /* C descriptor must be for an allocatable or pointer variable. */
412 if (dv->attribute == CFI_attribute_other)
413 {
414 fprintf (stderr, "CFI_deallocate: C descriptor must describe a "
415 "pointer or allocatable object.\n");
416 return CFI_INVALID_ATTRIBUTE;
417 }
418 }
419
420 /* Free and nullify memory. */
421 free (dv->base_addr);
422 dv->base_addr = NULL;
423
424 return CFI_SUCCESS;
425 }
426
427
428 int CFI_establish (CFI_cdesc_t *dv, void *base_addr, CFI_attribute_t attribute,
429 CFI_type_t type, size_t elem_len, CFI_rank_t rank,
430 const CFI_index_t extents[])
431 {
432 if (unlikely (compile_options.bounds_check))
433 {
434 /* C descriptor must not be NULL. */
435 if (dv == NULL)
436 {
437 fprintf (stderr, "CFI_establish: C descriptor is NULL.\n");
438 return CFI_INVALID_DESCRIPTOR;
439 }
440
441 /* Rank must be between 0 and CFI_MAX_RANK. */
442 if (rank < 0 || rank > CFI_MAX_RANK)
443 {
444 fprintf (stderr, "CFI_establish: Rank must be between 0 and %d, "
445 "0 < rank (0 !< %d).\n", CFI_MAX_RANK, (int)rank);
446 return CFI_INVALID_RANK;
447 }
448
449 /* If base address is not NULL, the established C descriptor is for a
450 nonallocatable entity. */
451 if (attribute == CFI_attribute_allocatable && base_addr != NULL)
452 {
453 fprintf (stderr, "CFI_establish: If base address is not NULL, "
454 "the established C descriptor must be "
455 "for a nonallocatable entity.\n");
456 return CFI_INVALID_ATTRIBUTE;
457 }
458 }
459
460 dv->base_addr = base_addr;
461
462 if (type == CFI_type_char || type == CFI_type_ucs4_char
463 || type == CFI_type_struct || type == CFI_type_other)
464 {
465 /* Note that elem_len has type size_t, which is unsigned. */
466 if (unlikely (compile_options.bounds_check) && elem_len == 0)
467 {
468 fprintf (stderr, "CFI_establish: The supplied elem_len must "
469 "be greater than zero.\n");
470 return CFI_INVALID_ELEM_LEN;
471 }
472 dv->elem_len = elem_len;
473 }
474 else if (type == CFI_type_cptr)
475 dv->elem_len = sizeof (void *);
476 else if (type == CFI_type_cfunptr)
477 dv->elem_len = sizeof (void (*)(void));
478 else if (unlikely (compile_options.bounds_check) && type < 0)
479 {
480 fprintf (stderr, "CFI_establish: Invalid type (type = %d).\n",
481 (int)type);
482 return CFI_INVALID_TYPE;
483 }
484 else
485 {
486 /* base_type describes the intrinsic type with kind parameter. */
487 size_t base_type = type & CFI_type_mask;
488 /* base_type_size is the size in bytes of the variable as given by its
489 * kind parameter. */
490 size_t base_type_size = (type - base_type) >> CFI_type_kind_shift;
491 /* Kind type 10 maps onto the 80-bit long double encoding on x86.
492 Note that this has different storage size for -m32 than -m64. */
493 if (base_type_size == 10)
494 base_type_size = sizeof (long double);
495 /* Complex numbers are twice the size of their real counterparts. */
496 if (base_type == CFI_type_Complex)
497 base_type_size *= 2;
498 dv->elem_len = base_type_size;
499 }
500
501 dv->version = CFI_VERSION;
502 dv->rank = rank;
503 dv->attribute = attribute;
504 dv->type = type;
505
506 /* Extents must not be NULL if rank is greater than zero and base_addr is not
507 NULL */
508 if (rank > 0 && base_addr != NULL)
509 {
510 if (unlikely (compile_options.bounds_check) && extents == NULL)
511 {
512 fprintf (stderr, "CFI_establish: Extents must not be NULL "
513 "if rank is greater than zero and base address is "
514 "not NULL.\n");
515 return CFI_INVALID_EXTENT;
516 }
517
518 for (int i = 0; i < rank; i++)
519 {
520 /* The standard requires all dimensions to be nonnegative.
521 Apparently you can have an extent-zero dimension but can't
522 construct an assumed-size array with -1 as the extent
523 of the last dimension. */
524 if (unlikely (compile_options.bounds_check) && extents[i] < 0)
525 {
526 fprintf (stderr, "CFI_establish: Extents must be nonnegative "
527 "(extents[%d] = %" PRIiPTR ").\n",
528 i, (ptrdiff_t)extents[i]);
529 return CFI_INVALID_EXTENT;
530 }
531 dv->dim[i].lower_bound = 0;
532 dv->dim[i].extent = extents[i];
533 if (i == 0)
534 dv->dim[i].sm = dv->elem_len;
535 else
536 {
537 CFI_index_t extents_product = 1;
538 for (int j = 0; j < i; j++)
539 extents_product *= extents[j];
540 dv->dim[i].sm = (CFI_index_t)(dv->elem_len * extents_product);
541 }
542 }
543 }
544
545 return CFI_SUCCESS;
546 }
547
548
549 int CFI_is_contiguous (const CFI_cdesc_t *dv)
550 {
551 if (unlikely (compile_options.bounds_check))
552 {
553 /* C descriptor must not be NULL. */
554 if (dv == NULL)
555 {
556 fprintf (stderr, "CFI_is_contiguous: C descriptor is NULL.\n");
557 return 0;
558 }
559
560 /* Base address must not be NULL. */
561 if (dv->base_addr == NULL)
562 {
563 fprintf (stderr, "CFI_is_contiguous: Base address of C descriptor "
564 "is already NULL.\n");
565 return 0;
566 }
567
568 /* Must be an array. */
569 if (dv->rank <= 0)
570 {
571 fprintf (stderr, "CFI_is_contiguous: C descriptor must describe "
572 "an array.\n");
573 return 0;
574 }
575 }
576
577 /* Assumed size arrays are always contiguous. */
578 if (dv->rank > 0 && dv->dim[dv->rank - 1].extent == -1)
579 return 1;
580
581 /* If an array is not contiguous the memory stride is different to
582 the element length. */
583 for (int i = 0; i < dv->rank; i++)
584 {
585 if (i == 0 && dv->dim[i].sm == (CFI_index_t)dv->elem_len)
586 continue;
587 else if (i > 0
588 && dv->dim[i].sm == (CFI_index_t)(dv->dim[i - 1].sm
589 * dv->dim[i - 1].extent))
590 continue;
591
592 return 0;
593 }
594
595 /* Array sections are guaranteed to be contiguous by the previous test. */
596 return 1;
597 }
598
599
600 int CFI_section (CFI_cdesc_t *result, const CFI_cdesc_t *source,
601 const CFI_index_t lower_bounds[],
602 const CFI_index_t upper_bounds[], const CFI_index_t strides[])
603 {
604 /* Dimension information. */
605 CFI_index_t lower[CFI_MAX_RANK];
606 CFI_index_t upper[CFI_MAX_RANK];
607 CFI_index_t stride[CFI_MAX_RANK];
608 int zero_count = 0;
609
610 if (unlikely (compile_options.bounds_check))
611 {
612 /* C descriptors must not be NULL. */
613 if (source == NULL)
614 {
615 fprintf (stderr, "CFI_section: Source must not be NULL.\n");
616 return CFI_INVALID_DESCRIPTOR;
617 }
618
619 if (result == NULL)
620 {
621 fprintf (stderr, "CFI_section: Result must not be NULL.\n");
622 return CFI_INVALID_DESCRIPTOR;
623 }
624
625 /* Base address of source must not be NULL. */
626 if (source->base_addr == NULL)
627 {
628 fprintf (stderr, "CFI_section: Base address of source must "
629 "not be NULL.\n");
630 return CFI_ERROR_BASE_ADDR_NULL;
631 }
632
633 /* Result must not be an allocatable array. */
634 if (result->attribute == CFI_attribute_allocatable)
635 {
636 fprintf (stderr, "CFI_section: Result must not describe an "
637 "allocatable array.\n");
638 return CFI_INVALID_ATTRIBUTE;
639 }
640
641 /* Source must be some form of array (nonallocatable nonpointer array,
642 allocated allocatable array or an associated pointer array). */
643 if (source->rank <= 0)
644 {
645 fprintf (stderr, "CFI_section: Source must describe an array.\n");
646 return CFI_INVALID_RANK;
647 }
648
649 /* Element lengths of source and result must be equal. */
650 if (result->elem_len != source->elem_len)
651 {
652 fprintf (stderr, "CFI_section: The element lengths of "
653 "source (source->elem_len = %" PRIiPTR ") and result "
654 "(result->elem_len = %" PRIiPTR ") must be equal.\n",
655 (ptrdiff_t)source->elem_len, (ptrdiff_t)result->elem_len);
656 return CFI_INVALID_ELEM_LEN;
657 }
658
659 /* Types must be equal. */
660 if (result->type != source->type)
661 {
662 fprintf (stderr, "CFI_section: Types of source "
663 "(source->type = %d) and result (result->type = %d) "
664 "must be equal.\n", source->type, result->type);
665 return CFI_INVALID_TYPE;
666 }
667 }
668
669 /* Stride of zero in the i'th dimension means rank reduction in that
670 dimension. */
671 for (int i = 0; i < source->rank; i++)
672 {
673 if (strides[i] == 0)
674 zero_count++;
675 }
676
677 /* Rank of result must be equal the the rank of source minus the number of
678 * zeros in strides. */
679 if (unlikely (compile_options.bounds_check)
680 && result->rank != source->rank - zero_count)
681 {
682 fprintf (stderr, "CFI_section: Rank of result must be equal to the "
683 "rank of source minus the number of zeros in strides "
684 "(result->rank = source->rank - zero_count, %d != %d "
685 "- %d).\n", result->rank, source->rank, zero_count);
686 return CFI_INVALID_RANK;
687 }
688
689 /* Lower bounds. */
690 if (lower_bounds == NULL)
691 {
692 for (int i = 0; i < source->rank; i++)
693 lower[i] = source->dim[i].lower_bound;
694 }
695 else
696 {
697 for (int i = 0; i < source->rank; i++)
698 lower[i] = lower_bounds[i];
699 }
700
701 /* Upper bounds. */
702 if (upper_bounds == NULL)
703 {
704 if (unlikely (compile_options.bounds_check)
705 && source->dim[source->rank - 1].extent == -1)
706 {
707 fprintf (stderr, "CFI_section: Source must not be an assumed-size "
708 "array if upper_bounds is NULL.\n");
709 return CFI_INVALID_EXTENT;
710 }
711
712 for (int i = 0; i < source->rank; i++)
713 upper[i] = source->dim[i].lower_bound + source->dim[i].extent - 1;
714 }
715 else
716 {
717 for (int i = 0; i < source->rank; i++)
718 upper[i] = upper_bounds[i];
719 }
720
721 /* Stride */
722 if (strides == NULL)
723 {
724 for (int i = 0; i < source->rank; i++)
725 stride[i] = 1;
726 }
727 else
728 {
729 for (int i = 0; i < source->rank; i++)
730 {
731 stride[i] = strides[i];
732 /* If stride[i] == 0 then lower[i] and upper[i] must be equal. */
733 if (unlikely (compile_options.bounds_check)
734 && stride[i] == 0 && lower[i] != upper[i])
735 {
736 fprintf (stderr, "CFI_section: If strides[%d] = 0, then "
737 "lower_bounds[%d] = %" PRIiPTR " and "
738 "upper_bounds[%d] = %" PRIiPTR " must be equal.\n",
739 i, i, (ptrdiff_t)lower_bounds[i], i,
740 (ptrdiff_t)upper_bounds[i]);
741 return CFI_ERROR_OUT_OF_BOUNDS;
742 }
743 }
744 }
745
746 /* Check that section upper and lower bounds are within the array bounds. */
747 if (unlikely (compile_options.bounds_check))
748 for (int i = 0; i < source->rank; i++)
749 {
750 bool assumed_size
751 = (i == source->rank - 1 && source->dim[i].extent == -1);
752 CFI_index_t ub
753 = source->dim[i].lower_bound + source->dim[i].extent - 1;
754 if (lower_bounds != NULL
755 && (lower[i] < source->dim[i].lower_bound
756 || (!assumed_size && lower[i] > ub)))
757 {
758 fprintf (stderr, "CFI_section: Lower bounds must be within "
759 "the bounds of the Fortran array "
760 "(source->dim[%d].lower_bound "
761 "<= lower_bounds[%d] <= source->dim[%d].lower_bound "
762 "+ source->dim[%d].extent - 1, "
763 "%" PRIiPTR " <= %" PRIiPTR " <= %" PRIiPTR ").\n",
764 i, i, i, i,
765 (ptrdiff_t)source->dim[i].lower_bound,
766 (ptrdiff_t)lower[i],
767 (ptrdiff_t)ub);
768 return CFI_ERROR_OUT_OF_BOUNDS;
769 }
770
771 if (upper_bounds != NULL
772 && (upper[i] < source->dim[i].lower_bound
773 || (!assumed_size && upper[i] > ub)))
774 {
775 fprintf (stderr, "CFI_section: Upper bounds must be within "
776 "the bounds of the Fortran array "
777 "(source->dim[%d].lower_bound "
778 "<= upper_bounds[%d] <= source->dim[%d].lower_bound "
779 "+ source->dim[%d].extent - 1, "
780 "%" PRIiPTR " !<= %" PRIiPTR " !<= %" PRIiPTR ").\n",
781 i, i, i, i,
782 (ptrdiff_t)source->dim[i].lower_bound,
783 (ptrdiff_t)upper[i],
784 (ptrdiff_t)ub);
785 return CFI_ERROR_OUT_OF_BOUNDS;
786 }
787
788 if (upper[i] < lower[i] && stride[i] >= 0)
789 {
790 fprintf (stderr, "CFI_section: If the upper bound is smaller than "
791 "the lower bound for a given dimension (upper[%d] < "
792 "lower[%d], %" PRIiPTR " < %" PRIiPTR "), then the "
793 "stride for said dimension must be negative "
794 "(stride[%d] < 0, %" PRIiPTR " < 0).\n",
795 i, i, (ptrdiff_t)upper[i], (ptrdiff_t)lower[i],
796 i, (ptrdiff_t)stride[i]);
797 return CFI_INVALID_STRIDE;
798 }
799 }
800
801 /* Set the base address. We have to compute this first in the case
802 where source == result, before we overwrite the dimension data. */
803 result->base_addr = CFI_address (source, lower);
804
805 /* Set the appropriate dimension information that gives us access to the
806 * data. */
807 for (int i = 0, o = 0; i < source->rank; i++)
808 {
809 if (stride[i] == 0)
810 continue;
811 result->dim[o].lower_bound = 0;
812 result->dim[o].extent = 1 + (upper[i] - lower[i])/stride[i];
813 result->dim[o].sm = stride[i] * source->dim[i].sm;
814 o++;
815 }
816
817 return CFI_SUCCESS;
818 }
819
820
821 int CFI_select_part (CFI_cdesc_t *result, const CFI_cdesc_t *source,
822 size_t displacement, size_t elem_len)
823 {
824 if (unlikely (compile_options.bounds_check))
825 {
826 /* C descriptors must not be NULL. */
827 if (source == NULL)
828 {
829 fprintf (stderr, "CFI_select_part: Source must not be NULL.\n");
830 return CFI_INVALID_DESCRIPTOR;
831 }
832
833 if (result == NULL)
834 {
835 fprintf (stderr, "CFI_select_part: Result must not be NULL.\n");
836 return CFI_INVALID_DESCRIPTOR;
837 }
838
839 /* Attribute of result will be CFI_attribute_other or
840 CFI_attribute_pointer. */
841 if (result->attribute == CFI_attribute_allocatable)
842 {
843 fprintf (stderr, "CFI_select_part: Result must not describe an "
844 "allocatable object (result->attribute != %d).\n",
845 CFI_attribute_allocatable);
846 return CFI_INVALID_ATTRIBUTE;
847 }
848
849 /* Base address of source must not be NULL. */
850 if (source->base_addr == NULL)
851 {
852 fprintf (stderr, "CFI_select_part: Base address of source must "
853 "not be NULL.\n");
854 return CFI_ERROR_BASE_ADDR_NULL;
855 }
856
857 /* Source and result must have the same rank. */
858 if (source->rank != result->rank)
859 {
860 fprintf (stderr, "CFI_select_part: Source and result must have "
861 "the same rank (source->rank = %d, result->rank = %d).\n",
862 (int)source->rank, (int)result->rank);
863 return CFI_INVALID_RANK;
864 }
865
866 /* Nonallocatable nonpointer must not be an assumed size array. */
867 if (source->rank > 0 && source->dim[source->rank - 1].extent == -1)
868 {
869 fprintf (stderr, "CFI_select_part: Source must not describe an "
870 "assumed size array (source->dim[%d].extent != -1).\n",
871 source->rank - 1);
872 return CFI_INVALID_DESCRIPTOR;
873 }
874 }
875
876 /* Element length is ignored unless result->type specifies a Fortran
877 character type. */
878 if (result->type == CFI_type_char || result->type == CFI_type_ucs4_char)
879 result->elem_len = elem_len;
880
881 if (unlikely (compile_options.bounds_check))
882 {
883 /* Ensure displacement is within the bounds of the element length
884 of source.*/
885 if (displacement > source->elem_len - 1)
886 {
887 fprintf (stderr, "CFI_select_part: Displacement must be within the "
888 "bounds of source (0 <= displacement <= source->elem_len "
889 "- 1, 0 <= %" PRIiPTR " <= %" PRIiPTR ").\n",
890 (ptrdiff_t)displacement,
891 (ptrdiff_t)(source->elem_len - 1));
892 return CFI_ERROR_OUT_OF_BOUNDS;
893 }
894
895 /* Ensure displacement and element length of result are less than or
896 equal to the element length of source. */
897 if (displacement + result->elem_len > source->elem_len)
898 {
899 fprintf (stderr, "CFI_select_part: Displacement plus the element "
900 "length of result must be less than or equal to the "
901 "element length of source (displacement + result->elem_len "
902 "<= source->elem_len, "
903 "%" PRIiPTR " + %" PRIiPTR " = %" PRIiPTR " <= %" PRIiPTR
904 ").\n",
905 (ptrdiff_t)displacement, (ptrdiff_t)result->elem_len,
906 (ptrdiff_t)(displacement + result->elem_len),
907 (ptrdiff_t)source->elem_len);
908 return CFI_ERROR_OUT_OF_BOUNDS;
909 }
910 }
911
912 if (result->rank > 0)
913 {
914 for (int i = 0; i < result->rank; i++)
915 {
916 result->dim[i].lower_bound = source->dim[i].lower_bound;
917 result->dim[i].extent = source->dim[i].extent;
918 result->dim[i].sm = source->dim[i].sm;
919 }
920 }
921
922 result->base_addr = (char *) source->base_addr + displacement;
923 return CFI_SUCCESS;
924 }
925
926
927 int CFI_setpointer (CFI_cdesc_t *result, CFI_cdesc_t *source,
928 const CFI_index_t lower_bounds[])
929 {
930 /* Result must not be NULL and must be a Fortran pointer. */
931 if (unlikely (compile_options.bounds_check))
932 {
933 if (result == NULL)
934 {
935 fprintf (stderr, "CFI_setpointer: Result is NULL.\n");
936 return CFI_INVALID_DESCRIPTOR;
937 }
938
939 if (result->attribute != CFI_attribute_pointer)
940 {
941 fprintf (stderr, "CFI_setpointer: Result shall be the address of a "
942 "C descriptor for a Fortran pointer.\n");
943 return CFI_INVALID_ATTRIBUTE;
944 }
945 }
946
947 /* If source is NULL, the result is a C descriptor that describes a
948 * disassociated pointer. */
949 if (source == NULL)
950 {
951 result->base_addr = NULL;
952 result->version = CFI_VERSION;
953 }
954 else
955 {
956 /* Check that the source is valid and that element lengths, ranks
957 and types of source and result are the same. */
958 if (unlikely (compile_options.bounds_check))
959 {
960 if (source->base_addr == NULL
961 && source->attribute == CFI_attribute_allocatable)
962 {
963 fprintf (stderr, "CFI_setpointer: The source is an "
964 "allocatable object but is not allocated.\n");
965 return CFI_ERROR_BASE_ADDR_NULL;
966 }
967 if (source->rank > 0
968 && source->dim[source->rank - 1].extent == -1)
969 {
970 fprintf (stderr, "CFI_setpointer: The source is an "
971 "assumed-size array.\n");
972 return CFI_INVALID_EXTENT;
973 }
974 if (result->elem_len != source->elem_len)
975 {
976 fprintf (stderr, "CFI_setpointer: Element lengths of result "
977 "(result->elem_len = %" PRIiPTR ") and source "
978 "(source->elem_len = %" PRIiPTR ") "
979 " must be the same.\n",
980 (ptrdiff_t)result->elem_len,
981 (ptrdiff_t)source->elem_len);
982 return CFI_INVALID_ELEM_LEN;
983 }
984
985 if (result->rank != source->rank)
986 {
987 fprintf (stderr, "CFI_setpointer: Ranks of result "
988 "(result->rank = %d) and source (source->rank = %d) "
989 "must be the same.\n", result->rank, source->rank);
990 return CFI_INVALID_RANK;
991 }
992
993 if (result->type != source->type)
994 {
995 fprintf (stderr, "CFI_setpointer: Types of result "
996 "(result->type = %d) and source (source->type = %d) "
997 "must be the same.\n", result->type, source->type);
998 return CFI_INVALID_TYPE;
999 }
1000 }
1001
1002 /* If the source is a disassociated pointer, the result must also
1003 describe a disassociated pointer. */
1004 if (source->base_addr == NULL
1005 && source->attribute == CFI_attribute_pointer)
1006 result->base_addr = NULL;
1007 else
1008 result->base_addr = source->base_addr;
1009
1010 /* Assign components to result. */
1011 result->version = source->version;
1012
1013 /* Dimension information. */
1014 for (int i = 0; i < source->rank; i++)
1015 {
1016 if (lower_bounds != NULL)
1017 result->dim[i].lower_bound = lower_bounds[i];
1018 else
1019 result->dim[i].lower_bound = source->dim[i].lower_bound;
1020
1021 result->dim[i].extent = source->dim[i].extent;
1022 result->dim[i].sm = source->dim[i].sm;
1023 }
1024 }
1025
1026 return CFI_SUCCESS;
1027 }