1 1.1 mrg /* Generic implementation of the SPREAD intrinsic 2 1.1.1.4 mrg Copyright (C) 2002-2024 Free Software Foundation, Inc. 3 1.1 mrg Contributed by Paul Brook <paul (at) nowt.org> 4 1.1 mrg 5 1.1 mrg This file is part of the GNU Fortran runtime library (libgfortran). 6 1.1 mrg 7 1.1 mrg Libgfortran is free software; you can redistribute it and/or 8 1.1 mrg modify it under the terms of the GNU General Public 9 1.1 mrg License as published by the Free Software Foundation; either 10 1.1 mrg version 3 of the License, or (at your option) any later version. 11 1.1 mrg 12 1.1 mrg Ligbfortran is distributed in the hope that it will be useful, 13 1.1 mrg but WITHOUT ANY WARRANTY; without even the implied warranty of 14 1.1 mrg MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 1.1 mrg GNU General Public License for more details. 16 1.1 mrg 17 1.1 mrg Under Section 7 of GPL version 3, you are granted additional 18 1.1 mrg permissions described in the GCC Runtime Library Exception, version 19 1.1 mrg 3.1, as published by the Free Software Foundation. 20 1.1 mrg 21 1.1 mrg You should have received a copy of the GNU General Public License and 22 1.1 mrg a copy of the GCC Runtime Library Exception along with this program; 23 1.1 mrg see the files COPYING3 and COPYING.RUNTIME respectively. If not, see 24 1.1 mrg <http://www.gnu.org/licenses/>. */ 25 1.1 mrg 26 1.1 mrg #include "libgfortran.h" 27 1.1 mrg #include <string.h> 28 1.1 mrg 29 1.1 mrg static void 30 1.1 mrg spread_internal (gfc_array_char *ret, const gfc_array_char *source, 31 1.1 mrg const index_type *along, const index_type *pncopies) 32 1.1 mrg { 33 1.1 mrg /* r.* indicates the return array. */ 34 1.1 mrg index_type rstride[GFC_MAX_DIMENSIONS]; 35 1.1 mrg index_type rstride0; 36 1.1 mrg index_type rdelta = 0; 37 1.1 mrg index_type rrank; 38 1.1 mrg index_type rs; 39 1.1 mrg char *rptr; 40 1.1 mrg char *dest; 41 1.1 mrg /* s.* indicates the source array. */ 42 1.1 mrg index_type sstride[GFC_MAX_DIMENSIONS]; 43 1.1 mrg index_type sstride0; 44 1.1 mrg index_type srank; 45 1.1 mrg const char *sptr; 46 1.1 mrg 47 1.1 mrg index_type count[GFC_MAX_DIMENSIONS]; 48 1.1 mrg index_type extent[GFC_MAX_DIMENSIONS]; 49 1.1 mrg index_type n; 50 1.1 mrg index_type dim; 51 1.1 mrg index_type ncopies; 52 1.1 mrg index_type size; 53 1.1 mrg 54 1.1 mrg size = GFC_DESCRIPTOR_SIZE(source); 55 1.1 mrg 56 1.1 mrg srank = GFC_DESCRIPTOR_RANK(source); 57 1.1 mrg 58 1.1.1.4 mrg sstride[0] = 0; /* Avoid warnings if not initialized. */ 59 1.1.1.4 mrg 60 1.1 mrg rrank = srank + 1; 61 1.1 mrg if (rrank > GFC_MAX_DIMENSIONS) 62 1.1 mrg runtime_error ("return rank too large in spread()"); 63 1.1 mrg 64 1.1 mrg if (*along > rrank) 65 1.1 mrg runtime_error ("dim outside of rank in spread()"); 66 1.1 mrg 67 1.1 mrg ncopies = *pncopies; 68 1.1 mrg 69 1.1 mrg if (ret->base_addr == NULL) 70 1.1 mrg { 71 1.1 mrg /* The front end has signalled that we need to populate the 72 1.1 mrg return array descriptor. */ 73 1.1 mrg 74 1.1 mrg size_t ub, stride; 75 1.1 mrg 76 1.1 mrg ret->dtype.rank = rrank; 77 1.1 mrg 78 1.1 mrg dim = 0; 79 1.1 mrg rs = 1; 80 1.1 mrg for (n = 0; n < rrank; n++) 81 1.1 mrg { 82 1.1 mrg stride = rs; 83 1.1 mrg if (n == *along - 1) 84 1.1 mrg { 85 1.1 mrg ub = ncopies - 1; 86 1.1 mrg rdelta = rs * size; 87 1.1 mrg rs *= ncopies; 88 1.1 mrg } 89 1.1 mrg else 90 1.1 mrg { 91 1.1 mrg count[dim] = 0; 92 1.1 mrg extent[dim] = GFC_DESCRIPTOR_EXTENT(source,dim); 93 1.1 mrg sstride[dim] = GFC_DESCRIPTOR_STRIDE_BYTES(source,dim); 94 1.1 mrg rstride[dim] = rs * size; 95 1.1 mrg 96 1.1 mrg ub = extent[dim]-1; 97 1.1 mrg rs *= extent[dim]; 98 1.1 mrg dim++; 99 1.1 mrg } 100 1.1 mrg 101 1.1 mrg GFC_DIMENSION_SET(ret->dim[n], 0, ub, stride); 102 1.1 mrg } 103 1.1 mrg ret->offset = 0; 104 1.1 mrg ret->base_addr = xmallocarray (rs, size); 105 1.1 mrg 106 1.1 mrg if (rs <= 0) 107 1.1 mrg return; 108 1.1 mrg } 109 1.1 mrg else 110 1.1 mrg { 111 1.1 mrg int zero_sized; 112 1.1 mrg 113 1.1 mrg zero_sized = 0; 114 1.1 mrg 115 1.1 mrg dim = 0; 116 1.1 mrg if (GFC_DESCRIPTOR_RANK(ret) != rrank) 117 1.1 mrg runtime_error ("rank mismatch in spread()"); 118 1.1 mrg 119 1.1 mrg if (compile_options.bounds_check) 120 1.1 mrg { 121 1.1 mrg for (n = 0; n < rrank; n++) 122 1.1 mrg { 123 1.1 mrg index_type ret_extent; 124 1.1 mrg 125 1.1 mrg ret_extent = GFC_DESCRIPTOR_EXTENT(ret,n); 126 1.1 mrg if (n == *along - 1) 127 1.1 mrg { 128 1.1 mrg rdelta = GFC_DESCRIPTOR_STRIDE_BYTES(ret,n); 129 1.1 mrg 130 1.1 mrg if (ret_extent != ncopies) 131 1.1 mrg runtime_error("Incorrect extent in return value of SPREAD" 132 1.1 mrg " intrinsic in dimension %ld: is %ld," 133 1.1 mrg " should be %ld", (long int) n+1, 134 1.1 mrg (long int) ret_extent, (long int) ncopies); 135 1.1 mrg } 136 1.1 mrg else 137 1.1 mrg { 138 1.1 mrg count[dim] = 0; 139 1.1 mrg extent[dim] = GFC_DESCRIPTOR_EXTENT(source,dim); 140 1.1 mrg if (ret_extent != extent[dim]) 141 1.1 mrg runtime_error("Incorrect extent in return value of SPREAD" 142 1.1 mrg " intrinsic in dimension %ld: is %ld," 143 1.1 mrg " should be %ld", (long int) n+1, 144 1.1 mrg (long int) ret_extent, 145 1.1 mrg (long int) extent[dim]); 146 1.1 mrg 147 1.1 mrg if (extent[dim] <= 0) 148 1.1 mrg zero_sized = 1; 149 1.1 mrg sstride[dim] = GFC_DESCRIPTOR_STRIDE_BYTES(source,dim); 150 1.1 mrg rstride[dim] = GFC_DESCRIPTOR_STRIDE_BYTES(ret,n); 151 1.1 mrg dim++; 152 1.1 mrg } 153 1.1 mrg } 154 1.1 mrg } 155 1.1 mrg else 156 1.1 mrg { 157 1.1 mrg for (n = 0; n < rrank; n++) 158 1.1 mrg { 159 1.1 mrg if (n == *along - 1) 160 1.1 mrg { 161 1.1 mrg rdelta = GFC_DESCRIPTOR_STRIDE_BYTES(ret,n); 162 1.1 mrg } 163 1.1 mrg else 164 1.1 mrg { 165 1.1 mrg count[dim] = 0; 166 1.1 mrg extent[dim] = GFC_DESCRIPTOR_EXTENT(source,dim); 167 1.1 mrg if (extent[dim] <= 0) 168 1.1 mrg zero_sized = 1; 169 1.1 mrg sstride[dim] = GFC_DESCRIPTOR_STRIDE_BYTES(source,dim); 170 1.1 mrg rstride[dim] = GFC_DESCRIPTOR_STRIDE_BYTES(ret,n); 171 1.1 mrg dim++; 172 1.1 mrg } 173 1.1 mrg } 174 1.1 mrg } 175 1.1 mrg 176 1.1 mrg if (zero_sized) 177 1.1 mrg return; 178 1.1 mrg 179 1.1 mrg if (sstride[0] == 0) 180 1.1 mrg sstride[0] = size; 181 1.1 mrg } 182 1.1 mrg sstride0 = sstride[0]; 183 1.1 mrg rstride0 = rstride[0]; 184 1.1 mrg rptr = ret->base_addr; 185 1.1 mrg sptr = source->base_addr; 186 1.1 mrg 187 1.1 mrg while (sptr) 188 1.1 mrg { 189 1.1 mrg /* Spread this element. */ 190 1.1 mrg dest = rptr; 191 1.1 mrg for (n = 0; n < ncopies; n++) 192 1.1 mrg { 193 1.1 mrg memcpy (dest, sptr, size); 194 1.1 mrg dest += rdelta; 195 1.1 mrg } 196 1.1 mrg /* Advance to the next element. */ 197 1.1 mrg sptr += sstride0; 198 1.1 mrg rptr += rstride0; 199 1.1 mrg count[0]++; 200 1.1 mrg n = 0; 201 1.1 mrg while (count[n] == extent[n]) 202 1.1 mrg { 203 1.1 mrg /* When we get to the end of a dimension, reset it and increment 204 1.1 mrg the next dimension. */ 205 1.1 mrg count[n] = 0; 206 1.1 mrg /* We could precalculate these products, but this is a less 207 1.1 mrg frequently used path so probably not worth it. */ 208 1.1 mrg sptr -= sstride[n] * extent[n]; 209 1.1 mrg rptr -= rstride[n] * extent[n]; 210 1.1 mrg n++; 211 1.1 mrg if (n >= srank) 212 1.1 mrg { 213 1.1 mrg /* Break out of the loop. */ 214 1.1 mrg sptr = NULL; 215 1.1 mrg break; 216 1.1 mrg } 217 1.1 mrg else 218 1.1 mrg { 219 1.1 mrg count[n]++; 220 1.1 mrg sptr += sstride[n]; 221 1.1 mrg rptr += rstride[n]; 222 1.1 mrg } 223 1.1 mrg } 224 1.1 mrg } 225 1.1 mrg } 226 1.1 mrg 227 1.1 mrg /* This version of spread_internal treats the special case of a scalar 228 1.1 mrg source. This is much simpler than the more general case above. */ 229 1.1 mrg 230 1.1 mrg static void 231 1.1 mrg spread_internal_scalar (gfc_array_char *ret, const char *source, 232 1.1 mrg const index_type *along, const index_type *pncopies) 233 1.1 mrg { 234 1.1 mrg int n; 235 1.1 mrg int ncopies = *pncopies; 236 1.1 mrg char * dest; 237 1.1 mrg size_t size; 238 1.1 mrg 239 1.1 mrg size = GFC_DESCRIPTOR_SIZE(ret); 240 1.1 mrg 241 1.1 mrg if (GFC_DESCRIPTOR_RANK (ret) != 1) 242 1.1 mrg runtime_error ("incorrect destination rank in spread()"); 243 1.1 mrg 244 1.1 mrg if (*along > 1) 245 1.1 mrg runtime_error ("dim outside of rank in spread()"); 246 1.1 mrg 247 1.1 mrg if (ret->base_addr == NULL) 248 1.1 mrg { 249 1.1 mrg ret->base_addr = xmallocarray (ncopies, size); 250 1.1 mrg ret->offset = 0; 251 1.1 mrg GFC_DIMENSION_SET(ret->dim[0], 0, ncopies - 1, 1); 252 1.1 mrg } 253 1.1 mrg else 254 1.1 mrg { 255 1.1 mrg if (ncopies - 1 > (GFC_DESCRIPTOR_EXTENT(ret,0) - 1) 256 1.1 mrg / GFC_DESCRIPTOR_STRIDE(ret,0)) 257 1.1 mrg runtime_error ("dim too large in spread()"); 258 1.1 mrg } 259 1.1 mrg 260 1.1 mrg for (n = 0; n < ncopies; n++) 261 1.1 mrg { 262 1.1 mrg dest = (char*)(ret->base_addr + n * GFC_DESCRIPTOR_STRIDE_BYTES(ret,0)); 263 1.1 mrg memcpy (dest , source, size); 264 1.1 mrg } 265 1.1 mrg } 266 1.1 mrg 267 1.1 mrg extern void spread (gfc_array_char *, const gfc_array_char *, 268 1.1 mrg const index_type *, const index_type *); 269 1.1 mrg export_proto(spread); 270 1.1 mrg 271 1.1 mrg void 272 1.1 mrg spread (gfc_array_char *ret, const gfc_array_char *source, 273 1.1 mrg const index_type *along, const index_type *pncopies) 274 1.1 mrg { 275 1.1 mrg index_type type_size; 276 1.1 mrg 277 1.1 mrg type_size = GFC_DTYPE_TYPE_SIZE(ret); 278 1.1 mrg switch(type_size) 279 1.1 mrg { 280 1.1 mrg case GFC_DTYPE_LOGICAL_1: 281 1.1 mrg case GFC_DTYPE_INTEGER_1: 282 1.1 mrg spread_i1 ((gfc_array_i1 *) ret, (gfc_array_i1 *) source, 283 1.1 mrg *along, *pncopies); 284 1.1 mrg return; 285 1.1 mrg 286 1.1 mrg case GFC_DTYPE_LOGICAL_2: 287 1.1 mrg case GFC_DTYPE_INTEGER_2: 288 1.1 mrg spread_i2 ((gfc_array_i2 *) ret, (gfc_array_i2 *) source, 289 1.1 mrg *along, *pncopies); 290 1.1 mrg return; 291 1.1 mrg 292 1.1 mrg case GFC_DTYPE_LOGICAL_4: 293 1.1 mrg case GFC_DTYPE_INTEGER_4: 294 1.1 mrg spread_i4 ((gfc_array_i4 *) ret, (gfc_array_i4 *) source, 295 1.1 mrg *along, *pncopies); 296 1.1 mrg return; 297 1.1 mrg 298 1.1 mrg case GFC_DTYPE_LOGICAL_8: 299 1.1 mrg case GFC_DTYPE_INTEGER_8: 300 1.1 mrg spread_i8 ((gfc_array_i8 *) ret, (gfc_array_i8 *) source, 301 1.1 mrg *along, *pncopies); 302 1.1 mrg return; 303 1.1 mrg 304 1.1 mrg #ifdef HAVE_GFC_INTEGER_16 305 1.1 mrg case GFC_DTYPE_LOGICAL_16: 306 1.1 mrg case GFC_DTYPE_INTEGER_16: 307 1.1 mrg spread_i16 ((gfc_array_i16 *) ret, (gfc_array_i16 *) source, 308 1.1 mrg *along, *pncopies); 309 1.1 mrg return; 310 1.1 mrg #endif 311 1.1 mrg 312 1.1 mrg case GFC_DTYPE_REAL_4: 313 1.1 mrg spread_r4 ((gfc_array_r4 *) ret, (gfc_array_r4 *) source, 314 1.1 mrg *along, *pncopies); 315 1.1 mrg return; 316 1.1 mrg 317 1.1 mrg case GFC_DTYPE_REAL_8: 318 1.1 mrg spread_r8 ((gfc_array_r8 *) ret, (gfc_array_r8 *) source, 319 1.1 mrg *along, *pncopies); 320 1.1 mrg return; 321 1.1 mrg 322 1.1 mrg /* FIXME: This here is a hack, which will have to be removed when 323 1.1 mrg the array descriptor is reworked. Currently, we don't store the 324 1.1 mrg kind value for the type, but only the size. Because on targets with 325 1.1.1.4 mrg _Float128, we have sizeof(long double) == sizeof(_Float128), 326 1.1 mrg we cannot discriminate here and have to fall back to the generic 327 1.1 mrg handling (which is suboptimal). */ 328 1.1 mrg #if !defined(GFC_REAL_16_IS_FLOAT128) 329 1.1 mrg # ifdef GFC_HAVE_REAL_10 330 1.1 mrg case GFC_DTYPE_REAL_10: 331 1.1 mrg spread_r10 ((gfc_array_r10 *) ret, (gfc_array_r10 *) source, 332 1.1 mrg *along, *pncopies); 333 1.1 mrg return; 334 1.1 mrg # endif 335 1.1 mrg 336 1.1 mrg # ifdef GFC_HAVE_REAL_16 337 1.1 mrg case GFC_DTYPE_REAL_16: 338 1.1 mrg spread_r16 ((gfc_array_r16 *) ret, (gfc_array_r16 *) source, 339 1.1 mrg *along, *pncopies); 340 1.1 mrg return; 341 1.1 mrg # endif 342 1.1 mrg #endif 343 1.1 mrg 344 1.1 mrg case GFC_DTYPE_COMPLEX_4: 345 1.1 mrg spread_c4 ((gfc_array_c4 *) ret, (gfc_array_c4 *) source, 346 1.1 mrg *along, *pncopies); 347 1.1 mrg return; 348 1.1 mrg 349 1.1 mrg case GFC_DTYPE_COMPLEX_8: 350 1.1 mrg spread_c8 ((gfc_array_c8 *) ret, (gfc_array_c8 *) source, 351 1.1 mrg *along, *pncopies); 352 1.1 mrg return; 353 1.1 mrg 354 1.1 mrg /* FIXME: This here is a hack, which will have to be removed when 355 1.1 mrg the array descriptor is reworked. Currently, we don't store the 356 1.1 mrg kind value for the type, but only the size. Because on targets with 357 1.1.1.4 mrg _Float128, we have sizeof(long double) == sizeof(_Float128), 358 1.1 mrg we cannot discriminate here and have to fall back to the generic 359 1.1 mrg handling (which is suboptimal). */ 360 1.1 mrg #if !defined(GFC_REAL_16_IS_FLOAT128) 361 1.1 mrg # ifdef GFC_HAVE_COMPLEX_10 362 1.1 mrg case GFC_DTYPE_COMPLEX_10: 363 1.1 mrg spread_c10 ((gfc_array_c10 *) ret, (gfc_array_c10 *) source, 364 1.1 mrg *along, *pncopies); 365 1.1 mrg return; 366 1.1 mrg # endif 367 1.1 mrg 368 1.1 mrg # ifdef GFC_HAVE_COMPLEX_16 369 1.1 mrg case GFC_DTYPE_COMPLEX_16: 370 1.1 mrg spread_c16 ((gfc_array_c16 *) ret, (gfc_array_c16 *) source, 371 1.1 mrg *along, *pncopies); 372 1.1 mrg return; 373 1.1 mrg # endif 374 1.1 mrg #endif 375 1.1 mrg 376 1.1 mrg } 377 1.1 mrg 378 1.1 mrg switch (GFC_DESCRIPTOR_SIZE (ret)) 379 1.1 mrg { 380 1.1 mrg case 1: 381 1.1 mrg spread_i1 ((gfc_array_i1 *) ret, (gfc_array_i1 *) source, 382 1.1 mrg *along, *pncopies); 383 1.1 mrg return; 384 1.1 mrg 385 1.1 mrg case 2: 386 1.1 mrg if (GFC_UNALIGNED_2(ret->base_addr) || GFC_UNALIGNED_2(source->base_addr)) 387 1.1 mrg break; 388 1.1 mrg else 389 1.1 mrg { 390 1.1 mrg spread_i2 ((gfc_array_i2 *) ret, (gfc_array_i2 *) source, 391 1.1 mrg *along, *pncopies); 392 1.1 mrg return; 393 1.1 mrg } 394 1.1 mrg 395 1.1 mrg case 4: 396 1.1 mrg if (GFC_UNALIGNED_4(ret->base_addr) || GFC_UNALIGNED_4(source->base_addr)) 397 1.1 mrg break; 398 1.1 mrg else 399 1.1 mrg { 400 1.1 mrg spread_i4 ((gfc_array_i4 *) ret, (gfc_array_i4 *) source, 401 1.1 mrg *along, *pncopies); 402 1.1 mrg return; 403 1.1 mrg } 404 1.1 mrg 405 1.1 mrg case 8: 406 1.1 mrg if (GFC_UNALIGNED_8(ret->base_addr) || GFC_UNALIGNED_8(source->base_addr)) 407 1.1 mrg break; 408 1.1 mrg else 409 1.1 mrg { 410 1.1 mrg spread_i8 ((gfc_array_i8 *) ret, (gfc_array_i8 *) source, 411 1.1 mrg *along, *pncopies); 412 1.1 mrg return; 413 1.1 mrg } 414 1.1 mrg #ifdef HAVE_GFC_INTEGER_16 415 1.1 mrg case 16: 416 1.1 mrg if (GFC_UNALIGNED_16(ret->base_addr) 417 1.1 mrg || GFC_UNALIGNED_16(source->base_addr)) 418 1.1 mrg break; 419 1.1 mrg else 420 1.1 mrg { 421 1.1 mrg spread_i16 ((gfc_array_i16 *) ret, (gfc_array_i16 *) source, 422 1.1 mrg *along, *pncopies); 423 1.1 mrg return; 424 1.1 mrg } 425 1.1 mrg #endif 426 1.1 mrg 427 1.1 mrg } 428 1.1 mrg 429 1.1 mrg spread_internal (ret, source, along, pncopies); 430 1.1 mrg } 431 1.1 mrg 432 1.1 mrg 433 1.1 mrg extern void spread_char (gfc_array_char *, GFC_INTEGER_4, 434 1.1 mrg const gfc_array_char *, const index_type *, 435 1.1 mrg const index_type *, GFC_INTEGER_4); 436 1.1 mrg export_proto(spread_char); 437 1.1 mrg 438 1.1 mrg void 439 1.1 mrg spread_char (gfc_array_char *ret, 440 1.1 mrg GFC_INTEGER_4 ret_length __attribute__((unused)), 441 1.1 mrg const gfc_array_char *source, const index_type *along, 442 1.1 mrg const index_type *pncopies, 443 1.1 mrg GFC_INTEGER_4 source_length __attribute__((unused))) 444 1.1 mrg { 445 1.1 mrg spread_internal (ret, source, along, pncopies); 446 1.1 mrg } 447 1.1 mrg 448 1.1 mrg 449 1.1 mrg extern void spread_char4 (gfc_array_char *, GFC_INTEGER_4, 450 1.1 mrg const gfc_array_char *, const index_type *, 451 1.1 mrg const index_type *, GFC_INTEGER_4); 452 1.1 mrg export_proto(spread_char4); 453 1.1 mrg 454 1.1 mrg void 455 1.1 mrg spread_char4 (gfc_array_char *ret, 456 1.1 mrg GFC_INTEGER_4 ret_length __attribute__((unused)), 457 1.1 mrg const gfc_array_char *source, const index_type *along, 458 1.1 mrg const index_type *pncopies, 459 1.1 mrg GFC_INTEGER_4 source_length __attribute__((unused))) 460 1.1 mrg { 461 1.1 mrg spread_internal (ret, source, along, pncopies); 462 1.1 mrg } 463 1.1 mrg 464 1.1 mrg 465 1.1 mrg /* The following are the prototypes for the versions of spread with a 466 1.1 mrg scalar source. */ 467 1.1 mrg 468 1.1 mrg extern void spread_scalar (gfc_array_char *, const char *, 469 1.1 mrg const index_type *, const index_type *); 470 1.1 mrg export_proto(spread_scalar); 471 1.1 mrg 472 1.1 mrg void 473 1.1 mrg spread_scalar (gfc_array_char *ret, const char *source, 474 1.1 mrg const index_type *along, const index_type *pncopies) 475 1.1 mrg { 476 1.1 mrg index_type type_size; 477 1.1 mrg 478 1.1 mrg if (GFC_DTYPE_IS_UNSET(ret)) 479 1.1 mrg runtime_error ("return array missing descriptor in spread()"); 480 1.1 mrg 481 1.1 mrg type_size = GFC_DTYPE_TYPE_SIZE(ret); 482 1.1 mrg switch(type_size) 483 1.1 mrg { 484 1.1 mrg case GFC_DTYPE_LOGICAL_1: 485 1.1 mrg case GFC_DTYPE_INTEGER_1: 486 1.1 mrg spread_scalar_i1 ((gfc_array_i1 *) ret, (GFC_INTEGER_1 *) source, 487 1.1 mrg *along, *pncopies); 488 1.1 mrg return; 489 1.1 mrg 490 1.1 mrg case GFC_DTYPE_LOGICAL_2: 491 1.1 mrg case GFC_DTYPE_INTEGER_2: 492 1.1 mrg spread_scalar_i2 ((gfc_array_i2 *) ret, (GFC_INTEGER_2 *) source, 493 1.1 mrg *along, *pncopies); 494 1.1 mrg return; 495 1.1 mrg 496 1.1 mrg case GFC_DTYPE_LOGICAL_4: 497 1.1 mrg case GFC_DTYPE_INTEGER_4: 498 1.1 mrg spread_scalar_i4 ((gfc_array_i4 *) ret, (GFC_INTEGER_4 *) source, 499 1.1 mrg *along, *pncopies); 500 1.1 mrg return; 501 1.1 mrg 502 1.1 mrg case GFC_DTYPE_LOGICAL_8: 503 1.1 mrg case GFC_DTYPE_INTEGER_8: 504 1.1 mrg spread_scalar_i8 ((gfc_array_i8 *) ret, (GFC_INTEGER_8 *) source, 505 1.1 mrg *along, *pncopies); 506 1.1 mrg return; 507 1.1 mrg 508 1.1 mrg #ifdef HAVE_GFC_INTEGER_16 509 1.1 mrg case GFC_DTYPE_LOGICAL_16: 510 1.1 mrg case GFC_DTYPE_INTEGER_16: 511 1.1 mrg spread_scalar_i16 ((gfc_array_i16 *) ret, (GFC_INTEGER_16 *) source, 512 1.1 mrg *along, *pncopies); 513 1.1 mrg return; 514 1.1 mrg #endif 515 1.1 mrg 516 1.1 mrg case GFC_DTYPE_REAL_4: 517 1.1 mrg spread_scalar_r4 ((gfc_array_r4 *) ret, (GFC_REAL_4 *) source, 518 1.1 mrg *along, *pncopies); 519 1.1 mrg return; 520 1.1 mrg 521 1.1 mrg case GFC_DTYPE_REAL_8: 522 1.1 mrg spread_scalar_r8 ((gfc_array_r8 *) ret, (GFC_REAL_8 *) source, 523 1.1 mrg *along, *pncopies); 524 1.1 mrg return; 525 1.1 mrg 526 1.1 mrg /* FIXME: This here is a hack, which will have to be removed when 527 1.1 mrg the array descriptor is reworked. Currently, we don't store the 528 1.1 mrg kind value for the type, but only the size. Because on targets with 529 1.1.1.4 mrg _Float128, we have sizeof(long double) == sizeof(_Float128), 530 1.1 mrg we cannot discriminate here and have to fall back to the generic 531 1.1 mrg handling (which is suboptimal). */ 532 1.1 mrg #if !defined(GFC_REAL_16_IS_FLOAT128) 533 1.1 mrg # ifdef HAVE_GFC_REAL_10 534 1.1 mrg case GFC_DTYPE_REAL_10: 535 1.1 mrg spread_scalar_r10 ((gfc_array_r10 *) ret, (GFC_REAL_10 *) source, 536 1.1 mrg *along, *pncopies); 537 1.1 mrg return; 538 1.1 mrg # endif 539 1.1 mrg 540 1.1 mrg # ifdef HAVE_GFC_REAL_16 541 1.1 mrg case GFC_DTYPE_REAL_16: 542 1.1 mrg spread_scalar_r16 ((gfc_array_r16 *) ret, (GFC_REAL_16 *) source, 543 1.1 mrg *along, *pncopies); 544 1.1 mrg return; 545 1.1 mrg # endif 546 1.1 mrg #endif 547 1.1 mrg 548 1.1 mrg case GFC_DTYPE_COMPLEX_4: 549 1.1 mrg spread_scalar_c4 ((gfc_array_c4 *) ret, (GFC_COMPLEX_4 *) source, 550 1.1 mrg *along, *pncopies); 551 1.1 mrg return; 552 1.1 mrg 553 1.1 mrg case GFC_DTYPE_COMPLEX_8: 554 1.1 mrg spread_scalar_c8 ((gfc_array_c8 *) ret, (GFC_COMPLEX_8 *) source, 555 1.1 mrg *along, *pncopies); 556 1.1 mrg return; 557 1.1 mrg 558 1.1 mrg /* FIXME: This here is a hack, which will have to be removed when 559 1.1 mrg the array descriptor is reworked. Currently, we don't store the 560 1.1 mrg kind value for the type, but only the size. Because on targets with 561 1.1.1.4 mrg _Float128, we have sizeof(long double) == sizeof(_Float128), 562 1.1 mrg we cannot discriminate here and have to fall back to the generic 563 1.1 mrg handling (which is suboptimal). */ 564 1.1 mrg #if !defined(GFC_REAL_16_IS_FLOAT128) 565 1.1 mrg # ifdef HAVE_GFC_COMPLEX_10 566 1.1 mrg case GFC_DTYPE_COMPLEX_10: 567 1.1 mrg spread_scalar_c10 ((gfc_array_c10 *) ret, (GFC_COMPLEX_10 *) source, 568 1.1 mrg *along, *pncopies); 569 1.1 mrg return; 570 1.1 mrg # endif 571 1.1 mrg 572 1.1 mrg # ifdef HAVE_GFC_COMPLEX_16 573 1.1 mrg case GFC_DTYPE_COMPLEX_16: 574 1.1 mrg spread_scalar_c16 ((gfc_array_c16 *) ret, (GFC_COMPLEX_16 *) source, 575 1.1 mrg *along, *pncopies); 576 1.1 mrg return; 577 1.1 mrg # endif 578 1.1 mrg #endif 579 1.1 mrg 580 1.1 mrg } 581 1.1 mrg 582 1.1 mrg switch (GFC_DESCRIPTOR_SIZE(ret)) 583 1.1 mrg { 584 1.1 mrg case 1: 585 1.1 mrg spread_scalar_i1 ((gfc_array_i1 *) ret, (GFC_INTEGER_1 *) source, 586 1.1 mrg *along, *pncopies); 587 1.1 mrg return; 588 1.1 mrg 589 1.1 mrg case 2: 590 1.1 mrg if (GFC_UNALIGNED_2(ret->base_addr) || GFC_UNALIGNED_2(source)) 591 1.1 mrg break; 592 1.1 mrg else 593 1.1 mrg { 594 1.1 mrg spread_scalar_i2 ((gfc_array_i2 *) ret, (GFC_INTEGER_2 *) source, 595 1.1 mrg *along, *pncopies); 596 1.1 mrg return; 597 1.1 mrg } 598 1.1 mrg 599 1.1 mrg case 4: 600 1.1 mrg if (GFC_UNALIGNED_4(ret->base_addr) || GFC_UNALIGNED_4(source)) 601 1.1 mrg break; 602 1.1 mrg else 603 1.1 mrg { 604 1.1 mrg spread_scalar_i4 ((gfc_array_i4 *) ret, (GFC_INTEGER_4 *) source, 605 1.1 mrg *along, *pncopies); 606 1.1 mrg return; 607 1.1 mrg } 608 1.1 mrg 609 1.1 mrg case 8: 610 1.1 mrg if (GFC_UNALIGNED_8(ret->base_addr) || GFC_UNALIGNED_8(source)) 611 1.1 mrg break; 612 1.1 mrg else 613 1.1 mrg { 614 1.1 mrg spread_scalar_i8 ((gfc_array_i8 *) ret, (GFC_INTEGER_8 *) source, 615 1.1 mrg *along, *pncopies); 616 1.1 mrg return; 617 1.1 mrg } 618 1.1 mrg #ifdef HAVE_GFC_INTEGER_16 619 1.1 mrg case 16: 620 1.1 mrg if (GFC_UNALIGNED_16(ret->base_addr) || GFC_UNALIGNED_16(source)) 621 1.1 mrg break; 622 1.1 mrg else 623 1.1 mrg { 624 1.1 mrg spread_scalar_i16 ((gfc_array_i16 *) ret, (GFC_INTEGER_16 *) source, 625 1.1 mrg *along, *pncopies); 626 1.1 mrg return; 627 1.1 mrg } 628 1.1 mrg #endif 629 1.1 mrg default: 630 1.1 mrg break; 631 1.1 mrg } 632 1.1 mrg 633 1.1 mrg spread_internal_scalar (ret, source, along, pncopies); 634 1.1 mrg } 635 1.1 mrg 636 1.1 mrg 637 1.1 mrg extern void spread_char_scalar (gfc_array_char *, GFC_INTEGER_4, 638 1.1 mrg const char *, const index_type *, 639 1.1 mrg const index_type *, GFC_INTEGER_4); 640 1.1 mrg export_proto(spread_char_scalar); 641 1.1 mrg 642 1.1 mrg void 643 1.1 mrg spread_char_scalar (gfc_array_char *ret, 644 1.1 mrg GFC_INTEGER_4 ret_length __attribute__((unused)), 645 1.1 mrg const char *source, const index_type *along, 646 1.1 mrg const index_type *pncopies, 647 1.1 mrg GFC_INTEGER_4 source_length __attribute__((unused))) 648 1.1 mrg { 649 1.1 mrg if (GFC_DTYPE_IS_UNSET(ret)) 650 1.1 mrg runtime_error ("return array missing descriptor in spread()"); 651 1.1 mrg spread_internal_scalar (ret, source, along, pncopies); 652 1.1 mrg } 653 1.1 mrg 654 1.1 mrg 655 1.1 mrg extern void spread_char4_scalar (gfc_array_char *, GFC_INTEGER_4, 656 1.1 mrg const char *, const index_type *, 657 1.1 mrg const index_type *, GFC_INTEGER_4); 658 1.1 mrg export_proto(spread_char4_scalar); 659 1.1 mrg 660 1.1 mrg void 661 1.1 mrg spread_char4_scalar (gfc_array_char *ret, 662 1.1 mrg GFC_INTEGER_4 ret_length __attribute__((unused)), 663 1.1 mrg const char *source, const index_type *along, 664 1.1 mrg const index_type *pncopies, 665 1.1 mrg GFC_INTEGER_4 source_length __attribute__((unused))) 666 1.1 mrg { 667 1.1 mrg if (GFC_DTYPE_IS_UNSET(ret)) 668 1.1 mrg runtime_error ("return array missing descriptor in spread()"); 669 1.1 mrg spread_internal_scalar (ret, source, along, pncopies); 670 1.1 mrg 671 1.1 mrg } 672 1.1 mrg 673