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