1 /* 2 * Copyright 1995-2021 Bruno Haible <bruno@clisp.org> 3 * 4 * This program is free software: you can redistribute it and/or modify 5 * it under the terms of the GNU General Public License as published by 6 * the Free Software Foundation; either version 2 of the License, or 7 * (at your option) any later version. 8 * 9 * This program is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 * GNU General Public License for more details. 13 * 14 * You should have received a copy of the GNU General Public License 15 * along with this program. If not, see <https://www.gnu.org/licenses/>. 16 */ 17 18 #ifndef _VACALL_INTERNAL_H 19 #define _VACALL_INTERNAL_H 20 21 /* Get intptr_t, uintptr_t. */ 22 #include "ffcall-stdint.h" 23 24 /* Include the public definitions, */ 25 #ifndef REENTRANT 26 #include "vacall.h" 27 #else 28 #include "vacall_r.h" 29 #endif 30 31 32 /* The platform indicator symbols (__i386__, etc.) come from 33 - "config.h" when compiling vacall-libapi.c, 34 - the GCC command line options when compiling vacall-$(CPU).c. 35 */ 36 37 /* These two variants of powerpc ABIs are quite different. */ 38 #if defined(__powerpc__) && !defined(__powerpc64__) 39 #if defined(_AIX) || (defined(__MACH__) && defined(__APPLE__)) 40 #define __powerpc_aix__ 1 41 #else 42 #define __powerpc_sysv4__ 1 43 #endif 44 #endif 45 46 /* The Unix and Windows variants of x86_64 ABIs are quite different. */ 47 #if defined(__x86_64__) 48 #if defined(_WIN32) || defined(__CYGWIN__) 49 #define __x86_64_ms__ 1 50 #else 51 #define __x86_64_sysv__ 1 52 #endif 53 #endif 54 55 56 /* Max # words in temporary structure storage. 57 */ 58 #ifndef __VA_ALIST_WORDS 59 #define __VA_ALIST_WORDS 256 60 #endif 61 62 /* 63 * Definition of the ‘__va_alist’ type. 64 */ 65 /* Note: This struct must not contain members of type 'long' or 'unsigned long', 66 because in the mingw port we use precompiled code that assumes 'long' is 67 64-bit whereas avcall-libapi.c is then compiled by a compiler that has a 68 32-bit 'long' type. */ 69 typedef struct vacall_alist 70 { 71 /* some va_... macros need these flags */ 72 int flags; 73 /* temporary storage for return value */ 74 #if defined(__i386__) || defined(__arm__) || defined(__armhf__) || (defined(__powerpc__) && !defined(__powerpc64__) && defined(__MACH__) && defined(__APPLE__)) 75 /* Filler word, needed if the numbers of words up to now in this structure */ 76 /* is odd. */ 77 /* - On MSVC, alignof(double) = 8, but normally on i386 it is = 4. */ 78 /* - On ARM, GCC 3.1 produces code for an ABI where alignof(double) = 4 */ 79 /* and alignof(long long) = 4. But in the newer AAPCS ABI, these */ 80 /* alignments are 8. */ 81 /* - On Mac OS X, the Apple compiler has alignof(double) = 8 whereas the */ 82 /* standard GCC has alignof(double) = 4. */ 83 __vaword filler1; 84 #endif 85 union { 86 char _char; 87 signed char _schar; 88 unsigned char _uchar; 89 short _short; 90 unsigned short _ushort; 91 int _int; 92 unsigned int _uint; 93 long _long; 94 unsigned long _ulong; 95 #if !(defined(__mips64__) || defined(__sparc64__) || defined(__alpha__) || defined(__hppa64__) || defined(__arm64__) || defined(__powerpc64__) || defined(__ia64__) || defined(__riscv64__)) 96 long long _longlong; 97 unsigned long long _ulonglong; 98 #endif 99 float _float; 100 double _double; 101 void* _ptr; 102 __vaword _words[2]; 103 } tmp; 104 /* current pointer into the argument array */ 105 uintptr_t aptr; 106 /* structure return pointer, return type, return type size */ 107 void* raddr; 108 enum __VAtype rtype; 109 uintptr_t rsize; 110 #if defined(__i386__) || defined(__m68k__) || (defined(__sparc__) && !defined(__sparc64__)) || defined(__hppa__) || defined(__hppa64__) || defined(__arm64__) || defined(__ia64__) 111 void* structraddr; 112 #endif 113 #if (defined(__mips__) && !defined(__mipsn32__) && !defined(__mips64__)) || defined(__alpha__) || defined(__hppa__) || defined(__hppa64__) 114 uintptr_t memargptr; 115 #endif 116 #if defined(__alpha__) 117 long farg_offset; 118 double farg[6]; 119 #endif 120 #if defined(__hppa__) && !defined(__hppa64__) 121 long farg_offset; 122 long darg_offset; 123 float farg[4]; 124 double darg[2]; 125 #endif 126 #if defined(__mips__) && !defined(__mipsn32__) && !defined(__mips64__) 127 unsigned int anum; 128 #define __VA_FARG_NUM 2 129 unsigned int fanum; 130 float farg[__VA_FARG_NUM]; 131 double darg[__VA_FARG_NUM]; 132 #endif 133 #if defined(__mipsn32__) || defined(__mips64__) 134 int anum; 135 #define __VA_FARG_NUM 8 136 float farg[__VA_FARG_NUM]; 137 double darg[__VA_FARG_NUM]; 138 #endif 139 #if defined(__sparc64__) 140 int anum; 141 float farg[16]; 142 double darg[16]; 143 #endif 144 #if defined(__hppa64__) 145 #define __VA_FARG_NUM 8 146 float farg[__VA_FARG_NUM]; 147 double darg[__VA_FARG_NUM]; 148 #endif 149 #if defined(__armhf__) 150 #define __VA_IARG_NUM 4 151 /* The first __AV_IARG_NUM integer arguments are passed in registers, even if 152 some floating-point arguments have already been allocated on the stack. */ 153 __vaword* iarg; 154 unsigned int ianum; 155 unsigned int fanum; 156 float farg[16]; 157 double darg[8]; 158 #endif 159 #if defined(__arm64__) 160 #define __VA_IARG_NUM 8 161 unsigned int ianum; 162 __varword iarg[__VA_IARG_NUM]; 163 #define __VA_FARG_NUM 8 164 unsigned int fanum; 165 float farg[__VA_FARG_NUM]; 166 double darg[__VA_FARG_NUM]; 167 #endif 168 #if defined(__powerpc__) || defined(__powerpc64__) 169 #if defined(__powerpc_sysv4__) 170 #define __VA_IARG_NUM 8 171 unsigned int ianum; 172 __varword iarg[__VA_IARG_NUM]; 173 #define __VA_FARG_NUM 8 174 #else 175 #define __VA_FARG_NUM 13 176 #endif 177 unsigned int fanum; 178 double farg[__VA_FARG_NUM]; 179 #endif 180 #if defined(__ia64__) 181 __vaword* saptr; 182 #define __VA_FARG_NUM 8 183 unsigned int fanum; 184 double farg[__VA_FARG_NUM]; 185 #endif 186 #if defined(__x86_64_sysv__) 187 #define __VA_FARG_NUM 8 188 unsigned int fanum; 189 double farg[__VA_FARG_NUM]; 190 #define __VA_IARG_NUM 6 191 unsigned int ianum; 192 __varword iarg[__VA_IARG_NUM]; 193 #endif 194 #if defined(__x86_64_ms__) 195 int anum; 196 #define __VA_FARG_NUM 4 197 float farg[__VA_FARG_NUM]; 198 double darg[__VA_FARG_NUM]; 199 #endif 200 #if defined(__s390__) && !defined(__s390x__) 201 #define __VA_IARG_NUM 5 202 unsigned int ianum; 203 __varword iarg[5]; 204 #define __VA_FARG_NUM 2 205 unsigned int fanum; 206 float farg[__VA_FARG_NUM]; 207 double darg[__VA_FARG_NUM]; 208 #endif 209 #if defined(__s390x__) 210 #define __VA_IARG_NUM 5 211 unsigned int ianum; 212 __varword iarg[__VA_IARG_NUM]; 213 #define __VA_FARG_NUM 4 214 unsigned int fanum; 215 float farg[__VA_FARG_NUM]; 216 double darg[__VA_FARG_NUM]; 217 #endif 218 #if defined(__riscv32__) || defined(__riscv64__) 219 #define __VA_IARG_NUM 8 220 unsigned int ianum; 221 __varword iarg[__VA_IARG_NUM]; 222 /* Note: iarg[7] == ((__vaword *) (initial aptr))[-1]. */ 223 #define __VA_FARG_NUM 8 224 unsigned int fanum; 225 float farg[__VA_FARG_NUM]; 226 double darg[__VA_FARG_NUM]; 227 #endif 228 } __va_alist; 229 230 231 /* Avoid macro redefinition warnings on DragonFly BSD. */ 232 #undef __va_start 233 #undef __va_arg 234 235 236 /* 237 * Definition of the va_start_xxx macros. 238 */ 239 240 #define __va_start(LIST,RETTYPE,FLAGS) \ 241 ((LIST)->flags = (FLAGS), \ 242 (LIST)->rtype = (RETTYPE) \ 243 ) 244 245 /* 246 * va_start_struct: Preparing structure return. 247 */ 248 #define __va_start_struct(LIST,TYPE_SIZE,TYPE_ALIGN,TYPE_SPLITTABLE,FLAGS) \ 249 (__va_start(LIST,__VAstruct,FLAGS), \ 250 (LIST)->rsize = (TYPE_SIZE), \ 251 ((LIST)->flags & __VA_SUNPROCC_STRUCT_RETURN \ 252 ? __va_start_struct2(LIST) \ 253 : ((LIST)->flags & __VA_SUNCC_STRUCT_RETURN \ 254 ? ((TYPE_SIZE) <= sizeof(vacall_struct_buffer) || (vacall_error_struct_too_large(TYPE_SIZE), 0), \ 255 (LIST)->raddr = &vacall_struct_buffer, \ 256 0 \ 257 ) \ 258 : (((LIST)->flags & __VA_SMALL_STRUCT_RETURN) \ 259 && __va_reg_struct_return(LIST,TYPE_SIZE,TYPE_SPLITTABLE) \ 260 ? ((LIST)->raddr = &(LIST)->tmp, \ 261 __va_start_struct1(LIST,TYPE_SIZE,TYPE_ALIGN,TYPE_SPLITTABLE) \ 262 ) \ 263 : __va_start_struct2(LIST) \ 264 )) ) ) 265 /* Determines whether a structure is returned in registers, 266 * depending on its size and its word-splittable flag. 267 */ 268 #if (defined(__i386__) && defined(_WIN32)) 269 #define __va_reg_struct_return(LIST,TYPE_SIZE,TYPE_SPLITTABLE) \ 270 ((TYPE_SIZE) == 1 || (TYPE_SIZE) == 2 || (TYPE_SIZE) == 4 \ 271 || ((TYPE_SIZE) == 8 \ 272 && (((LIST)->flags & __VA_MSVC_STRUCT_RETURN) \ 273 || ((TYPE_SPLITTABLE) \ 274 && ((LIST)->flags & __VA_GCC_STRUCT_RETURN) \ 275 ) ) ) ) 276 /* Turn on __VA_REGISTER_STRUCT_RETURN if __VA_SMALL_STRUCT_RETURN was set 277 * and the struct will actually be returned in registers. 278 */ 279 #define __va_start_struct1(LIST,TYPE_SIZE,TYPE_ALIGN,TYPE_SPLITTABLE) \ 280 ((LIST)->flags |= __VA_REGISTER_STRUCT_RETURN, 0) 281 #endif 282 #if (defined(__i386__) && !defined(_WIN32)) || defined(__m68k__) || (defined(__powerpc__) && !defined(__powerpc64__)) || (defined(__s390__) && !defined(__s390x__)) 283 #define __va_reg_struct_return(LIST,TYPE_SIZE,TYPE_SPLITTABLE) \ 284 ((TYPE_SIZE) == 1 || (TYPE_SIZE) == 2 || (TYPE_SIZE) == 4 \ 285 || ((TYPE_SIZE) == 8 && (TYPE_SPLITTABLE) \ 286 && ((LIST)->flags & __VA_GCC_STRUCT_RETURN) \ 287 ) ) 288 /* Turn on __VA_REGISTER_STRUCT_RETURN if __VA_SMALL_STRUCT_RETURN was set 289 * and the struct will actually be returned in registers. 290 */ 291 #define __va_start_struct1(LIST,TYPE_SIZE,TYPE_ALIGN,TYPE_SPLITTABLE) \ 292 ((LIST)->flags |= __VA_REGISTER_STRUCT_RETURN, 0) 293 #endif 294 #if defined(__arm__) || defined(__armhf__) 295 /* structs of size 3 also will be returned in register */ 296 #define __va_reg_struct_return(LIST,TYPE_SIZE,TYPE_SPLITTABLE) \ 297 ((TYPE_SIZE) <= 4) 298 /* Turn on __VA_REGISTER_STRUCT_RETURN if __VA_SMALL_STRUCT_RETURN was set 299 * and the struct will actually be returned in registers. 300 */ 301 #define __va_start_struct1(LIST,TYPE_SIZE,TYPE_ALIGN,TYPE_SPLITTABLE) \ 302 ((LIST)->flags |= __VA_REGISTER_STRUCT_RETURN, 0) 303 #endif 304 #if defined(__alpha__) 305 #define __va_reg_struct_return(LIST,TYPE_SIZE,TYPE_SPLITTABLE) \ 306 ((TYPE_SIZE) == 1 || (TYPE_SIZE) == 2 || (TYPE_SIZE) == 4 || (TYPE_SIZE) == 8 \ 307 || ((TYPE_SIZE) == 16 && (TYPE_SPLITTABLE) \ 308 && ((LIST)->flags & __VA_GCC_STRUCT_RETURN) \ 309 ) ) 310 /* Turn on __VA_REGISTER_STRUCT_RETURN if __VA_SMALL_STRUCT_RETURN was set 311 * and the struct will actually be returned in registers. 312 */ 313 #define __va_start_struct1(LIST,TYPE_SIZE,TYPE_ALIGN,TYPE_SPLITTABLE) \ 314 ((LIST)->flags |= __VA_REGISTER_STRUCT_RETURN, 0) 315 #endif 316 #if (defined(__hppa__) && !defined(__hppa64__)) || defined(__riscv32__) 317 #define __va_reg_struct_return(LIST,TYPE_SIZE,TYPE_SPLITTABLE) \ 318 ((TYPE_SIZE) <= 8) 319 /* Test __VA_SMALL_STRUCT_RETURN at run time. */ 320 #define __va_start_struct1(LIST,TYPE_SIZE,TYPE_ALIGN,TYPE_SPLITTABLE) \ 321 0 322 #endif 323 #if defined(__mips__) && !defined(__mipsn32__) && !defined(__mips64__) || (defined(__sparc__) && !defined(__sparc64__)) 324 #define __va_reg_struct_return(LIST,TYPE_SIZE,TYPE_SPLITTABLE) \ 325 ((TYPE_SIZE) == 1 || (TYPE_SIZE) == 2 || (TYPE_SIZE) == 4) 326 /* Test __VA_SMALL_STRUCT_RETURN instead of __VA_REGISTER_STRUCT_RETURN. */ 327 #if defined(__mips__) && !defined(__mipsn32__) && !defined(__mips64__) 328 #define __va_start_struct1(LIST,TYPE_SIZE,TYPE_ALIGN,TYPE_SPLITTABLE) \ 329 ((LIST)->anum++, \ 330 0 \ 331 ) 332 #else 333 #define __va_start_struct1(LIST,TYPE_SIZE,TYPE_ALIGN,TYPE_SPLITTABLE) \ 334 0 335 #endif 336 #endif 337 #if defined(__mipsn32__) || defined(__mips64__) 338 #define __va_reg_struct_return(LIST,TYPE_SIZE,TYPE_SPLITTABLE) \ 339 ((LIST)->flags & __VA_GCC_STRUCT_RETURN \ 340 ? ((TYPE_SIZE) == 1 || (TYPE_SIZE) == 2 || (TYPE_SIZE) == 4 || (TYPE_SIZE) == 8) \ 341 : ((TYPE_SIZE) <= 16) \ 342 ) 343 /* Turn on __VA_REGISTER_STRUCT_RETURN if __VA_SMALL_STRUCT_RETURN was set 344 * and the struct will actually be returned in registers. Also turn on 345 * __VA_REGISTER_FLOATSTRUCT_RETURN or __VA_REGISTER_DOUBLESTRUCT_RETURN if 346 * the struct will be returned in floating-point registers. 347 */ 348 #define __va_start_struct1(LIST,TYPE_SIZE,TYPE_ALIGN,TYPE_SPLITTABLE) \ 349 ((LIST)->flags |= __VA_REGISTER_STRUCT_RETURN, \ 350 (TYPE_ALIGN) == sizeof(float) && (TYPE_SPLITTABLE) \ 351 && ((TYPE_SIZE) == sizeof(float) || (TYPE_SIZE) == 2*sizeof(float)) \ 352 && ((LIST)->flags |= __VA_REGISTER_FLOATSTRUCT_RETURN), \ 353 (TYPE_ALIGN) == sizeof(double) && (TYPE_SPLITTABLE) \ 354 && ((TYPE_SIZE) == sizeof(double) || (TYPE_SIZE) == 2*sizeof(double)) \ 355 && ((LIST)->flags |= __VA_REGISTER_DOUBLESTRUCT_RETURN), \ 356 0) 357 #endif 358 #if (defined(__powerpc64__) && !defined(__powerpc64_elfv2__)) || defined(__s390x__) 359 #define __va_reg_struct_return(LIST,TYPE_SIZE,TYPE_SPLITTABLE) \ 360 0 361 #define __va_start_struct1(LIST,TYPE_SIZE,TYPE_ALIGN,TYPE_SPLITTABLE) \ 362 0 363 #endif 364 #if defined(__sparc64__) || defined(__ia64__) 365 #define __va_reg_struct_return(LIST,TYPE_SIZE,TYPE_SPLITTABLE) \ 366 ((TYPE_SIZE) <= 32) 367 /* Turn on __VA_REGISTER_STRUCT_RETURN if __VA_SMALL_STRUCT_RETURN was set 368 * and the struct will actually be returned in registers. 369 */ 370 #define __va_start_struct1(LIST,TYPE_SIZE,TYPE_ALIGN,TYPE_SPLITTABLE) \ 371 ((LIST)->flags |= __VA_REGISTER_STRUCT_RETURN, \ 372 0) 373 #endif 374 #if defined(__hppa64__) || defined(__arm64__) || (defined(__powerpc64__) && defined(__powerpc64_elfv2__)) || defined(__x86_64_sysv__) || defined(__riscv64__) 375 #define __va_reg_struct_return(LIST,TYPE_SIZE,TYPE_SPLITTABLE) \ 376 ((TYPE_SIZE) <= 16) 377 /* Turn on __VA_REGISTER_STRUCT_RETURN if __VA_SMALL_STRUCT_RETURN was set 378 * and the struct will actually be returned in registers. 379 */ 380 #define __va_start_struct1(LIST,TYPE_SIZE,TYPE_ALIGN,TYPE_SPLITTABLE) \ 381 ((LIST)->flags |= __VA_REGISTER_STRUCT_RETURN, \ 382 0) 383 #endif 384 #if defined(__x86_64_ms__) 385 #define __va_reg_struct_return(LIST,TYPE_SIZE,TYPE_SPLITTABLE) \ 386 ((TYPE_SIZE) == 1 || (TYPE_SIZE) == 2 || (TYPE_SIZE) == 4 || (TYPE_SIZE) == 8) 387 /* Turn on __VA_REGISTER_STRUCT_RETURN if __VA_SMALL_STRUCT_RETURN was set 388 * and the struct will actually be returned in registers. 389 */ 390 #define __va_start_struct1(LIST,TYPE_SIZE,TYPE_ALIGN,TYPE_SPLITTABLE) \ 391 ((LIST)->flags |= __VA_REGISTER_STRUCT_RETURN, \ 392 0) 393 #endif 394 /* 395 * Preparing structure return in memory. 396 */ 397 #if defined(__i386__) || defined(__alpha__) || (defined(__arm__) && !defined(__armhf__)) || defined(__powerpc_aix__) || defined(__powerpc64__) 398 /* Return structure pointer is passed as first arg. */ 399 #define __va_start_struct2(LIST) \ 400 ((LIST)->raddr = *(void* *)((LIST)->aptr), \ 401 (LIST)->aptr += sizeof(void*), \ 402 0 \ 403 ) 404 #endif 405 #if defined(__mips__) || defined(__mipsn32__) || defined(__mips64__) || defined(__sparc64__) || defined(__x86_64_ms__) 406 /* Return structure pointer is passed as first arg. */ 407 #define __va_start_struct2(LIST) \ 408 ((LIST)->raddr = *(void* *)((LIST)->aptr), \ 409 (LIST)->aptr += sizeof(void*), \ 410 (LIST)->anum++, \ 411 0 \ 412 ) 413 #endif 414 #if defined(__armhf__) 415 /* Return structure pointer is passed as first arg. */ 416 #define __va_start_struct2(LIST) \ 417 ((LIST)->raddr = (void*)(LIST)->iarg[(LIST)->ianum], \ 418 (LIST)->ianum++, \ 419 0 \ 420 ) 421 #endif 422 #if defined(__powerpc_sysv4__) || defined(__x86_64_sysv__) || defined(__s390__) || defined(__s390x__) || defined(__riscv32__) || defined(__riscv64__) 423 /* Return structure pointer is passed as first arg. */ 424 #define __va_start_struct2(LIST) \ 425 ((LIST)->raddr = (void*)((LIST)->iarg[(LIST)->ianum++]), \ 426 0 \ 427 ) 428 #endif 429 #if defined(__m68k__) || (defined(__sparc__) && !defined(__sparc64__)) || defined(__hppa__) || defined(__hppa64__) || defined(__arm64__) || defined(__ia64__) 430 /* Return structure pointer is passed in a special register. */ 431 #define __va_start_struct2(LIST) \ 432 ((LIST)->raddr = (LIST)->structraddr, 0) 433 #endif 434 435 436 /* 437 * Definition of the va_arg_xxx macros. 438 */ 439 440 /* Padding of non-struct arguments. */ 441 #define __va_argsize(TYPE_SIZE) \ 442 (((TYPE_SIZE) + sizeof(__vaword)-1) & -(intptr_t)sizeof(__vaword)) 443 #if defined(__i386__) || defined(__m68k__) || (defined(__mips__) && !defined(__mipsn32__) && !defined(__mips64__)) || (defined(__sparc__) && !defined(__sparc64__)) || defined(__alpha__) || (defined(__arm__) && !defined(__armhf__)) || defined(__arm64__) || defined(__powerpc_aix__) || defined(__powerpc64__) || defined(__ia64__) || defined(__x86_64_sysv__) || defined(__s390__) || defined(__s390x__) || defined(__riscv32__) || defined(__riscv64__) 444 /* args grow up */ 445 /* small structures < 1 word are adjusted depending on compiler */ 446 #define __va_arg_leftadjusted(LIST,TYPE_SIZE,TYPE_ALIGN) \ 447 ((LIST)->aptr += __va_argsize(TYPE_SIZE), \ 448 (LIST)->aptr - __va_argsize(TYPE_SIZE) \ 449 ) 450 #define __va_arg_rightadjusted(LIST,TYPE_SIZE,TYPE_ALIGN) \ 451 ((LIST)->aptr += __va_argsize(TYPE_SIZE), \ 452 (LIST)->aptr - ((TYPE_SIZE) < sizeof(__vaword) \ 453 ? (TYPE_SIZE) \ 454 : __va_argsize(TYPE_SIZE) \ 455 ) \ 456 ) 457 #endif 458 #if defined(__armhf__) 459 /* args grow up */ 460 /* small structures < 1 word are adjusted depending on compiler */ 461 /* the first __VA_IARG_NUM argument words are passed in registers */ 462 #define __va_arg_leftadjusted(LIST,TYPE_SIZE,TYPE_ALIGN) \ 463 (((LIST)->ianum + ((TYPE_SIZE) + sizeof(__vaword)-1) / sizeof(__vaword) <= __VA_IARG_NUM \ 464 ? ((LIST)->ianum += __va_argsize(TYPE_SIZE) / sizeof(__vaword), \ 465 (char*)&(LIST)->iarg[(LIST)->ianum] \ 466 ) \ 467 : (((LIST)->aptr == (uintptr_t)&(LIST)->iarg[__VA_IARG_NUM] \ 468 ? /* split case */ \ 469 ((LIST)->aptr = (uintptr_t)&(LIST)->iarg[(LIST)->ianum] + __va_argsize(TYPE_SIZE), \ 470 0) \ 471 : ((LIST)->aptr += __va_argsize(TYPE_SIZE), \ 472 0)), \ 473 (LIST)->ianum = __VA_IARG_NUM, \ 474 (char*)(LIST)->aptr \ 475 ) ) \ 476 - __va_argsize(TYPE_SIZE) \ 477 ) 478 #define __va_arg_rightadjusted(LIST,TYPE_SIZE,TYPE_ALIGN) \ 479 (((LIST)->ianum + ((TYPE_SIZE) + sizeof(__vaword)-1) / sizeof(__vaword) <= __VA_IARG_NUM \ 480 ? ((LIST)->ianum += __va_argsize(TYPE_SIZE) / sizeof(__vaword), \ 481 (char*)&(LIST)->iarg[(LIST)->ianum] \ 482 ) \ 483 : (((LIST)->aptr == (uintptr_t)&(LIST)->iarg[__VA_IARG_NUM] \ 484 ? /* split case */ \ 485 ((LIST)->aptr = (uintptr_t)&(LIST)->iarg[(LIST)->ianum] + __va_argsize(TYPE_SIZE), \ 486 0) \ 487 : ((LIST)->aptr += __va_argsize(TYPE_SIZE), \ 488 0)), \ 489 (LIST)->ianum = __VA_IARG_NUM, \ 490 (char*)(LIST)->aptr \ 491 ) ) \ 492 - ((TYPE_SIZE) < sizeof(__vaword) \ 493 ? (TYPE_SIZE) \ 494 : __va_argsize(TYPE_SIZE) \ 495 ) \ 496 ) 497 #endif 498 #if defined(__powerpc_sysv4__) 499 /* args grow up */ 500 /* small structures < 1 word are adjusted depending on compiler */ 501 /* the first __VA_IARG_NUM argument words are passed in registers */ 502 #define __va_arg_leftadjusted(LIST,TYPE_SIZE,TYPE_ALIGN) \ 503 (((LIST)->ianum + ((TYPE_SIZE) + sizeof(__varword)-1) / sizeof(__varword) <= __VA_IARG_NUM \ 504 ? ((LIST)->ianum += __va_argsize(TYPE_SIZE) / sizeof(__varword), \ 505 (char*)&(LIST)->iarg[(LIST)->ianum] \ 506 ) \ 507 : ((LIST)->aptr += __va_argsize(TYPE_SIZE), \ 508 (char*)(LIST)->aptr \ 509 ) ) \ 510 - __va_argsize(TYPE_SIZE) \ 511 ) 512 #define __va_arg_rightadjusted(LIST,TYPE_SIZE,TYPE_ALIGN) \ 513 (((LIST)->ianum + ((TYPE_SIZE) + sizeof(__varword)-1) / sizeof(__varword) <= __VA_IARG_NUM \ 514 ? ((LIST)->ianum += __va_argsize(TYPE_SIZE) / sizeof(__varword), \ 515 (char*)&(LIST)->iarg[(LIST)->ianum] \ 516 ) \ 517 : ((LIST)->aptr += __va_argsize(TYPE_SIZE), \ 518 (char*)(LIST)->aptr \ 519 ) ) \ 520 - ((TYPE_SIZE) < sizeof(__vaword) \ 521 ? (TYPE_SIZE) \ 522 : __va_argsize(TYPE_SIZE) \ 523 ) \ 524 ) 525 #endif 526 #if defined(__mipsn32__) || defined(__mips64__) || defined(__sparc64__) || defined(__x86_64_ms__) 527 /* args grow up */ 528 /* small structures < 1 word are adjusted depending on compiler */ 529 #define __va_arg_leftadjusted(LIST,TYPE_SIZE,TYPE_ALIGN) \ 530 ((LIST)->anum += __va_argsize(TYPE_SIZE)/sizeof(__vaword), \ 531 (LIST)->aptr += __va_argsize(TYPE_SIZE), \ 532 (LIST)->aptr - __va_argsize(TYPE_SIZE) \ 533 ) 534 #define __va_arg_rightadjusted(LIST,TYPE_SIZE,TYPE_ALIGN) \ 535 ((LIST)->anum += __va_argsize(TYPE_SIZE)/sizeof(__vaword), \ 536 (LIST)->aptr += __va_argsize(TYPE_SIZE), \ 537 (LIST)->aptr - ((TYPE_SIZE) < sizeof(__vaword) \ 538 ? (TYPE_SIZE) \ 539 : __va_argsize(TYPE_SIZE) \ 540 ) \ 541 ) 542 #endif 543 #if defined(__hppa__) && !defined(__hppa64__) 544 /* args grow down */ 545 #define __va_arg_leftadjusted(LIST,TYPE_SIZE,TYPE_ALIGN) \ 546 ((LIST)->aptr = (LIST)->aptr - __va_argsize(TYPE_SIZE), \ 547 ((TYPE_SIZE) > 4 && ((LIST)->aptr &= -8)), \ 548 (LIST)->aptr \ 549 ) 550 #define __va_arg_rightadjusted(LIST,TYPE_SIZE,TYPE_ALIGN) \ 551 ((LIST)->aptr = (LIST)->aptr - __va_argsize(TYPE_SIZE), \ 552 ((TYPE_SIZE) > 4 && ((LIST)->aptr &= -8)), \ 553 (LIST)->aptr + ((-(TYPE_SIZE)) & 3) \ 554 ) 555 #endif 556 #if defined(__hppa64__) 557 /* args grow up */ 558 #define __va_arg_leftadjusted(LIST,TYPE_SIZE,TYPE_ALIGN) \ 559 (((TYPE_SIZE) > 8 && ((LIST)->aptr = (((LIST)->aptr +15) & -16))), \ 560 (LIST)->aptr += __va_argsize(TYPE_SIZE), \ 561 (LIST)->aptr - __va_argsize(TYPE_SIZE) \ 562 ) 563 #define __va_arg_rightadjusted(LIST,TYPE_SIZE,TYPE_ALIGN) \ 564 (((TYPE_SIZE) > 8 && ((LIST)->aptr = (((LIST)->aptr +15) & -16))), \ 565 (LIST)->aptr += __va_argsize(TYPE_SIZE), \ 566 (LIST)->aptr - ((TYPE_SIZE) < sizeof(__vaword) \ 567 ? (TYPE_SIZE) \ 568 : __va_argsize(TYPE_SIZE) \ 569 ) \ 570 ) 571 #endif 572 #if defined(__i386__) || ((defined(__mipsn32__) || defined(__mips64__)) && defined(_MIPSEL)) || defined(__alpha__) || ((defined(__arm__) || defined(__armhf__)) && defined(__ARMEL__)) || defined(__ia64__) || (defined(__powerpc64__) && defined(_LITTLE_ENDIAN)) || defined(__x86_64_ms__) 573 /* little endian -> small args < 1 word are adjusted to the left */ 574 #define __va_arg_adjusted(LIST,TYPE_SIZE,TYPE_ALIGN) \ 575 (void*)__va_arg_leftadjusted(LIST,TYPE_SIZE,TYPE_ALIGN) 576 #endif 577 #if defined(__m68k__) || ((defined(__mipsn32__) || defined(__mips64__)) && defined(_MIPSEB)) || defined(__sparc__) || defined(__sparc64__) || defined(__hppa__) || defined(__hppa64__) || ((defined(__arm__) || defined(__armhf__)) && !defined(__ARMEL__)) || (defined(__powerpc__) && !defined(__powerpc64__)) || (defined(__powerpc64__) && defined(_BIG_ENDIAN)) 578 /* big endian -> small args < 1 word are adjusted to the right */ 579 #define __va_arg_adjusted(LIST,TYPE_SIZE,TYPE_ALIGN) \ 580 (void*)__va_arg_rightadjusted(LIST,TYPE_SIZE,TYPE_ALIGN) 581 #endif 582 #if defined(__mips__) && !defined(__mipsn32__) && !defined(__mips64__) 583 #ifdef _MIPSEB 584 /* big endian -> small args < 1 word are adjusted to the right */ 585 #define __va_arg_adjusted(LIST,TYPE_SIZE,TYPE_ALIGN) \ 586 ((LIST)->anum++, \ 587 (void*)__va_arg_rightadjusted(LIST,TYPE_SIZE,TYPE_ALIGN)) 588 #else /* _MIPSEL */ 589 /* little endian -> small args < 1 word are adjusted to the left */ 590 #define __va_arg_adjusted(LIST,TYPE_SIZE,TYPE_ALIGN) \ 591 ((LIST)->anum++, \ 592 (void*)__va_arg_leftadjusted(LIST,TYPE_SIZE,TYPE_ALIGN)) 593 #endif 594 #endif 595 #if defined(__arm64__) 596 /* the first __VA_IARG_NUM argument words are passed in registers */ 597 #define __va_arg_adjusted(LIST,TYPE_SIZE,TYPE_ALIGN) \ 598 ((LIST)->ianum + ((TYPE_SIZE) + sizeof(__varword)-1) / sizeof(__varword) <= __VA_IARG_NUM \ 599 ? ((LIST)->ianum += ((TYPE_SIZE) + sizeof(__varword)-1) / sizeof(__varword), \ 600 &(LIST)->iarg[(LIST)->ianum - ((TYPE_SIZE) + sizeof(__varword)-1) / sizeof(__varword)] \ 601 ) \ 602 : ((LIST)->ianum = __VA_IARG_NUM, \ 603 (void*)__va_arg_leftadjusted(LIST,TYPE_SIZE,TYPE_ALIGN) \ 604 ) ) 605 #endif 606 #if defined(__x86_64_sysv__) 607 /* the first __VA_IARG_NUM argument words are passed in registers */ 608 #define __va_arg_adjusted(LIST,TYPE_SIZE,TYPE_ALIGN) \ 609 (((TYPE_SIZE) <= 2*sizeof(__varword) \ 610 && (LIST)->ianum + ((TYPE_SIZE) + sizeof(__varword)-1) / sizeof(__varword) <= __VA_IARG_NUM) \ 611 ? ((LIST)->ianum += ((TYPE_SIZE) + sizeof(__varword)-1) / sizeof(__varword), \ 612 &(LIST)->iarg[(LIST)->ianum - ((TYPE_SIZE) + sizeof(__varword)-1) / sizeof(__varword)] \ 613 ) \ 614 : (void*)__va_arg_leftadjusted(LIST,TYPE_SIZE,TYPE_ALIGN) \ 615 ) 616 #endif 617 #if defined(__s390__) || defined(__s390x__) 618 /* the first __VA_IARG_NUM argument words are passed in registers */ 619 #define __va_arg_adjusted(LIST,TYPE_SIZE,TYPE_ALIGN) \ 620 ((LIST)->ianum + ((TYPE_SIZE) + sizeof(__varword)-1) / sizeof(__varword) <= __VA_IARG_NUM \ 621 ? ((LIST)->ianum += ((TYPE_SIZE) + sizeof(__varword)-1) / sizeof(__varword), \ 622 (void*)((uintptr_t)&(LIST)->iarg[(LIST)->ianum] - (TYPE_SIZE)) \ 623 ) \ 624 : ((LIST)->ianum = __VA_IARG_NUM, \ 625 (void*)__va_arg_rightadjusted(LIST,TYPE_SIZE,TYPE_ALIGN) \ 626 ) ) 627 #endif 628 #if defined(__riscv32__) || defined(__riscv64__) 629 /* the first __VA_IARG_NUM argument words are passed in registers */ 630 #define __va_arg_adjusted(LIST,TYPE_SIZE,TYPE_ALIGN) \ 631 ((LIST)->ianum + ((TYPE_SIZE) + sizeof(__varword)-1) / sizeof(__varword) <= __VA_IARG_NUM \ 632 ? ((LIST)->ianum += ((TYPE_SIZE) + sizeof(__varword)-1) / sizeof(__varword), \ 633 &(LIST)->iarg[(LIST)->ianum - ((TYPE_SIZE) + sizeof(__varword)-1) / sizeof(__varword)] \ 634 ) \ 635 : (((LIST)->ianum < __VA_IARG_NUM \ 636 ? ((LIST)->aptr -= (__VA_IARG_NUM - (LIST)->ianum) * sizeof(__vaword), \ 637 (LIST)->ianum = __VA_IARG_NUM, \ 638 0) \ 639 : 0), \ 640 (void*)__va_arg_leftadjusted(LIST,TYPE_SIZE,TYPE_ALIGN) \ 641 ) ) 642 #endif 643 #define __va_arg(LIST,TYPE) \ 644 *(TYPE*)__va_arg_adjusted(LIST,sizeof(TYPE),__VA_alignof(TYPE)) 645 646 /* Integer arguments. */ 647 648 #define _va_arg_char(LIST) __va_arg(LIST,char) 649 #define _va_arg_schar(LIST) __va_arg(LIST,signed char) 650 #define _va_arg_uchar(LIST) __va_arg(LIST,unsigned char) 651 #define _va_arg_short(LIST) __va_arg(LIST,short) 652 #define _va_arg_ushort(LIST) __va_arg(LIST,unsigned short) 653 #define _va_arg_int(LIST) __va_arg(LIST,int) 654 #define _va_arg_uint(LIST) __va_arg(LIST,unsigned int) 655 #define _va_arg_long(LIST) __va_arg(LIST,long) 656 #define _va_arg_ulong(LIST) __va_arg(LIST,unsigned long) 657 658 #if defined(__mips64__) || defined(__sparc64__) || defined(__alpha__) || defined(__hppa64__) || defined(__arm64__) || defined(__powerpc64__) || defined(__ia64__) || (defined(__x86_64__) && !defined(__x86_64_x32__) && !defined(__VA_LLP64)) || defined(__s390x__) || defined(__riscv64__) 659 /* ‘long long’ and ‘long’ are identical. */ 660 #define _va_arg_longlong _va_arg_long 661 #define _va_arg_ulonglong _va_arg_ulong 662 #elif defined(__mipsn32__) || defined(__x86_64_x32__) || (defined(__x86_64__) && defined(__VA_LLP64)) 663 /* ‘long long’ fits in __vaword. */ 664 #define _va_arg_longlong(LIST) __va_arg(LIST,long long) 665 #define _va_arg_ulonglong(LIST) __va_arg(LIST,unsigned long long) 666 #elif defined(__i386__) || defined(__m68k__) || defined(__mips__) || (defined(__sparc__) && !defined(__sparc64__)) || (defined(__hppa__) && !defined(__hppa64__)) || defined(__arm__) || defined(__armhf__) || defined(__powerpc__) || (defined(__s390__) && !defined(__s390x__)) || defined(__riscv32__) 667 /* ‘long long’s are passed embedded on the arg stack. */ 668 #define _va_arg_longlong(LIST) __va_arg_longlong(LIST,long long) 669 #define _va_arg_ulonglong(LIST) __va_arg_longlong(LIST,unsigned long long) 670 #if defined(__i386__) || defined(__m68k__) || defined(__powerpc_aix__) 671 /* ‘long long’s are (at most) word-aligned. */ 672 #define __va_arg_longlong(LIST,TYPE) __va_arg(LIST,TYPE) 673 #endif 674 #if defined(__mips__) || defined(__arm__) 675 /* ‘long long’s have alignment 8. */ 676 #define __va_arg_longlong(LIST,TYPE) \ 677 ((LIST)->aptr = (((LIST)->aptr+__VA_alignof(TYPE)-1) & -(intptr_t)__VA_alignof(TYPE)), \ 678 __va_arg(LIST,TYPE)) 679 #endif 680 #if defined(__armhf__) 681 /* ‘long long’s have alignment 8. */ 682 #define __va_arg_longlong(LIST,TYPE) \ 683 (((LIST)->ianum < __VA_IARG_NUM \ 684 ? ((LIST)->ianum = (((LIST)->ianum+__VA_alignof(TYPE)/sizeof(__vaword)-1) & -(intptr_t)(__VA_alignof(TYPE)/sizeof(__vaword))), 0) \ 685 : ((LIST)->aptr = (((LIST)->aptr+__VA_alignof(TYPE)-1) & -(intptr_t)__VA_alignof(TYPE)), 0) \ 686 ), \ 687 __va_arg(LIST,TYPE)) 688 #endif 689 #if defined(__powerpc_sysv4__) 690 /* ‘long long’s have alignment 8. */ 691 #define __va_arg_longlong(LIST,TYPE) \ 692 (((LIST)->ianum < __VA_IARG_NUM \ 693 ? ((LIST)->ianum = (((LIST)->ianum+__VA_alignof(TYPE)/sizeof(__varword)-1) & -(intptr_t)(__VA_alignof(TYPE)/sizeof(__varword))), 0) \ 694 : ((LIST)->aptr = (((LIST)->aptr+__VA_alignof(TYPE)-1) & -(intptr_t)__VA_alignof(TYPE)), 0) \ 695 ), \ 696 __va_arg(LIST,TYPE)) 697 #endif 698 #if (defined(__s390__) && !defined(__s390x__)) || defined(__riscv32__) 699 /* Within the arg stack, the alignment is only 4, not 8. */ 700 #define __va_arg_longlong(LIST,TYPE) __va_arg(LIST,TYPE) 701 #endif 702 #if (defined(__sparc__) && !defined(__sparc64__)) 703 /* Within the arg stack, the alignment is only 4, not 8. */ 704 /* Beware against unaligned accesses! */ 705 #define __va_arg_longlong(LIST,TYPE) \ 706 ((LIST)->tmp._words[0] = ((__vaword*)((LIST)->aptr))[0], \ 707 (LIST)->tmp._words[1] = ((__vaword*)((LIST)->aptr))[1], \ 708 (LIST)->aptr += sizeof(TYPE), \ 709 (TYPE)((LIST)->tmp._longlong) \ 710 ) 711 #endif 712 #if defined(__hppa__) && !defined(__hppa64__) 713 /* ‘long long’s have alignment 8. */ 714 #define __va_arg_longlong(LIST,TYPE) \ 715 ((LIST)->aptr = ((LIST)->aptr & -(intptr_t)__VA_alignof(TYPE)), \ 716 __va_arg(LIST,TYPE)) 717 #endif 718 #endif 719 720 /* Floating point arguments. */ 721 722 #if defined(__i386__) || defined(__m68k__) || defined(__mipsn32__) || defined(__mips64__) || defined(__sparc__) || defined(__sparc64__) || defined(__alpha__) || defined(__hppa64__) || defined(__arm64__) || defined(__powerpc__) || defined(__powerpc64__) || defined(__ia64__) || defined(__x86_64__) || defined(__s390__) || defined(__s390x__) || defined(__riscv32__) || defined(__riscv64__) 723 #define __va_align_double(LIST) 724 #endif 725 #if defined(__mips__) && !defined(__mipsn32__) && !defined(__mips64__) || defined(__arm__) || defined(__armhf__) 726 /* __VA_alignof(double) > sizeof(__vaword) */ 727 #define __va_align_double(LIST) \ 728 (LIST)->aptr = ((LIST)->aptr + sizeof(double)-1) & -(intptr_t)sizeof(double), 729 #endif 730 #if defined(__hppa__) && !defined(__hppa64__) 731 #define __va_align_double(LIST) \ 732 (LIST)->aptr = (LIST)->aptr & -(intptr_t)sizeof(double), 733 #endif 734 735 #if defined(__sparc__) && !defined(__sparc64__) 736 /* Beware against unaligned ‘double’ accesses! */ 737 #define _va_arg_double(LIST) \ 738 (__va_align_double(LIST) \ 739 (LIST)->tmp._words[0] = ((__vaword*)((LIST)->aptr))[0], \ 740 (LIST)->tmp._words[1] = ((__vaword*)((LIST)->aptr))[1], \ 741 (LIST)->aptr += sizeof(double), \ 742 (LIST)->tmp._double \ 743 ) 744 #endif 745 #if defined(__alpha__) 746 /* The first 6 floating point registers have been stored in another place. */ 747 #define _va_arg_double(LIST) \ 748 (((LIST)->aptr += sizeof(double)) <= (LIST)->memargptr \ 749 ? *(double*)((LIST)->aptr - sizeof(double) + (LIST)->farg_offset) \ 750 : *(double*)((LIST)->aptr - sizeof(double)) \ 751 ) 752 #define _va_arg_float(LIST) \ 753 (((LIST)->aptr += sizeof(double)) <= (LIST)->memargptr \ 754 ? /* The first 6 args have been put into memory by "stt" instructions */\ 755 /* (see vacall-alpha.s!). Therefore load them as doubles. */ \ 756 /* When viewed as floats, the value will be the correct one. */ \ 757 (float)*(double*)((LIST)->aptr - sizeof(double) + (LIST)->farg_offset) \ 758 : /* These args have been put into memory by "sts" instructions, */ \ 759 /* therefore load them as floats. */ \ 760 *(float*)((LIST)->aptr - sizeof(double)) \ 761 ) 762 #endif 763 #if defined(__hppa__) && !defined(__hppa64__) 764 /* The floats and doubles among the first 4 argument words are passed 765 * - in both general registers and floating-point registers when the 766 * function call is a variadic one, which means: 767 * - for HP cc: the call is done through a function pointer or 768 * directly to a function declared with a varargs prototype, 769 * - for GCC: the function's type is a varargs function. 770 * - in floating-point registers otherwise. 771 * Since the code in tests.c uses a function pointer, casted to a non-varargs 772 * function type, we are in the first case for HP cc, but in the second case 773 * for GCC. 774 * Therefore we need to take the values from the floating-point registers. 775 */ 776 #define _va_arg_float(LIST) \ 777 (((LIST)->aptr -= sizeof(float)) >= (LIST)->memargptr \ 778 ? /* The first 4 float args are stored separately. */ \ 779 *(float*)((LIST)->aptr + (LIST)->farg_offset) \ 780 : *(float*)((LIST)->aptr) \ 781 ) 782 #define _va_arg_double(LIST) \ 783 (__va_align_double(LIST) \ 784 (((LIST)->aptr -= sizeof(double)) >= (LIST)->memargptr \ 785 ? /* The first 2 double args are stored separately. */ \ 786 *(double*)((LIST)->aptr + (LIST)->darg_offset) \ 787 : *(double*)((LIST)->aptr) \ 788 )) 789 #endif 790 #if defined(__mips__) && !defined(__mipsn32__) && !defined(__mips64__) 791 /* The first 0,1,2 registers are stored elsewhere if they are floating-point 792 * parameters. 793 */ 794 #define _va_arg_float(LIST) \ 795 ((LIST)->aptr += sizeof(float), \ 796 (LIST)->anum++, \ 797 (LIST)->fanum++, \ 798 ((LIST)->anum == (LIST)->fanum && (LIST)->fanum <= __VA_FARG_NUM \ 799 ? /* only floating-point arguments so far */ \ 800 (LIST)->farg[(LIST)->fanum - 1] \ 801 : *(float*)((LIST)->aptr - sizeof(float)) \ 802 )) 803 #define _va_arg_double(LIST) \ 804 (__va_align_double(LIST) \ 805 (LIST)->aptr += sizeof(double), \ 806 (LIST)->anum++, \ 807 (LIST)->fanum++, \ 808 ((LIST)->anum == (LIST)->fanum && (LIST)->fanum <= __VA_FARG_NUM \ 809 ? /* only floating-point arguments so far */ \ 810 (LIST)->darg[(LIST)->fanum - 1] \ 811 : *(double*)((LIST)->aptr - sizeof(double)) \ 812 )) 813 #endif 814 #if defined(__mipsn32__) || defined(__mips64__) || defined(__x86_64_ms__) 815 /* The first 0,..,8 registers are stored elsewhere if they are floating-point 816 * parameters. 817 */ 818 #define _va_arg_float(LIST) \ 819 (__va_align_double(LIST) \ 820 (LIST)->aptr += sizeof(double), \ 821 (++(LIST)->anum <= __VA_FARG_NUM \ 822 ? (LIST)->farg[(LIST)->anum - 1] \ 823 : *(float*)((LIST)->aptr - sizeof(double)) \ 824 )) 825 #define _va_arg_double(LIST) \ 826 (__va_align_double(LIST) \ 827 (LIST)->aptr += sizeof(double), \ 828 (++(LIST)->anum <= __VA_FARG_NUM \ 829 ? (LIST)->darg[(LIST)->anum - 1] \ 830 : *(double*)((LIST)->aptr - sizeof(double)) \ 831 )) 832 #endif 833 #if defined(__sparc64__) 834 /* The first 0,..,16 registers are stored elsewhere if they are floating-point 835 * parameters. 836 */ 837 #define _va_arg_float(LIST) \ 838 (__va_align_double(LIST) \ 839 (LIST)->aptr += sizeof(double), \ 840 (++(LIST)->anum <= 16 \ 841 ? (LIST)->farg[(LIST)->anum - 1] \ 842 : *(float*)((LIST)->aptr - sizeof(float)) \ 843 )) 844 #define _va_arg_double(LIST) \ 845 (__va_align_double(LIST) \ 846 (LIST)->aptr += sizeof(double), \ 847 (++(LIST)->anum <= 16 \ 848 ? (LIST)->darg[(LIST)->anum - 1] \ 849 : *(double*)((LIST)->aptr - sizeof(double)) \ 850 )) 851 #endif 852 #if defined(__hppa64__) 853 /* The floating-point arguments among the first 8 argument words have been 854 stored elsewhere. */ 855 #define _va_arg_float(LIST) \ 856 ((LIST)->aptr += sizeof(double), \ 857 ((LIST)->aptr <= (LIST)->memargptr \ 858 ? (LIST)->farg[__VA_FARG_NUM-1-((LIST)->memargptr - (LIST)->aptr)/sizeof(__vaword)] \ 859 : ((float*)(LIST)->aptr)[-1] \ 860 )) 861 #define _va_arg_double(LIST) \ 862 ((LIST)->aptr += sizeof(double), \ 863 ((LIST)->aptr <= (LIST)->memargptr \ 864 ? (LIST)->darg[__VA_FARG_NUM-1-((LIST)->memargptr - (LIST)->aptr)/sizeof(__vaword)] \ 865 : ((double*)(LIST)->aptr)[-1] \ 866 )) 867 #endif 868 #if defined(__armhf__) 869 #define _va_arg_float(LIST) \ 870 ((LIST)->fanum <= 15 \ 871 ? (LIST)->farg[(LIST)->fanum++] \ 872 : ((LIST)->aptr += sizeof(float), \ 873 *(float*)((LIST)->aptr - sizeof(float)) \ 874 ) ) 875 #define _va_arg_double(LIST) \ 876 (((LIST)->fanum % 2 ? (LIST)->fanum++ : 0), \ 877 ((LIST)->fanum <= 14 \ 878 ? ((LIST)->fanum += 2, (LIST)->darg[(LIST)->fanum / 2 - 1]) \ 879 : ((LIST)->aptr += sizeof(double), \ 880 *(double*)((LIST)->aptr - sizeof(double)) \ 881 )) ) 882 #endif 883 #if defined(__arm64__) 884 /* The first __VA_FARG_NUM floating-point args have been stored elsewhere. */ 885 #define _va_arg_float(LIST) \ 886 ((LIST)->fanum < __VA_FARG_NUM \ 887 ? (LIST)->farg[(LIST)->fanum++] \ 888 : ((LIST)->aptr += sizeof(__vaword), \ 889 *(float*)((LIST)->aptr - sizeof(__vaword)) \ 890 ) ) 891 #define _va_arg_double(LIST) \ 892 ((LIST)->fanum < __VA_FARG_NUM \ 893 ? (LIST)->darg[(LIST)->fanum++] \ 894 : ((LIST)->aptr += sizeof(double), \ 895 *(double*)((LIST)->aptr - sizeof(double)) \ 896 ) ) 897 #endif 898 #if defined(__powerpc_aix__) 899 /* The first __VA_FARG_NUM floating-point args have been stored elsewhere. */ 900 #define _va_arg_float(LIST) \ 901 ((LIST)->aptr += sizeof(float), \ 902 ((LIST)->fanum < __VA_FARG_NUM \ 903 ? (float) (LIST)->farg[(LIST)->fanum++] \ 904 : *(float*)((LIST)->aptr - sizeof(float)) \ 905 )) 906 #define _va_arg_double(LIST) \ 907 (__va_align_double(LIST) \ 908 (LIST)->aptr += sizeof(double), \ 909 ((LIST)->fanum < __VA_FARG_NUM \ 910 ? (LIST)->farg[(LIST)->fanum++] \ 911 : *(double*)((LIST)->aptr - sizeof(double)) \ 912 )) 913 #endif 914 #if defined(__powerpc_sysv4__) 915 /* The first __VA_FARG_NUM floating-point args have been stored elsewhere. */ 916 #define _va_arg_float(LIST) \ 917 ((LIST)->fanum < __VA_FARG_NUM \ 918 ? (float) (LIST)->farg[(LIST)->fanum++] \ 919 : ((LIST)->aptr += sizeof(float), \ 920 *(float*)((LIST)->aptr - sizeof(float)) \ 921 ) ) 922 #define _va_arg_double(LIST) \ 923 ((LIST)->fanum < __VA_FARG_NUM \ 924 ? (LIST)->farg[(LIST)->fanum++] \ 925 : (__va_align_double(LIST) \ 926 (LIST)->aptr += sizeof(double), \ 927 *(double*)((LIST)->aptr - sizeof(double)) \ 928 ) ) 929 #endif 930 #if defined(__powerpc64__) 931 /* The first __VA_FARG_NUM floating-point args have been stored elsewhere. */ 932 #if defined(_AIX) 933 #define _va_arg_float(LIST) \ 934 ((LIST)->aptr += sizeof(__vaword), \ 935 ((LIST)->fanum < __VA_FARG_NUM \ 936 ? (float) (LIST)->farg[(LIST)->fanum++] \ 937 : ((float*)(LIST)->aptr)[(LIST)->flags & __VA_AIXCC_FLOAT_ARGS ? -2 : -1] \ 938 )) 939 #elif defined(_LITTLE_ENDIAN) 940 #define _va_arg_float(LIST) \ 941 ((LIST)->aptr += sizeof(__vaword), \ 942 ((LIST)->fanum < __VA_FARG_NUM \ 943 ? (float) (LIST)->farg[(LIST)->fanum++] \ 944 : ((float*)(LIST)->aptr)[-2] \ 945 )) 946 #else /* _BIG_ENDIAN */ 947 #define _va_arg_float(LIST) \ 948 ((LIST)->aptr += sizeof(__vaword), \ 949 ((LIST)->fanum < __VA_FARG_NUM \ 950 ? (float) (LIST)->farg[(LIST)->fanum++] \ 951 : ((float*)(LIST)->aptr)[-1] \ 952 )) 953 #endif 954 #define _va_arg_double(LIST) \ 955 (__va_align_double(LIST) \ 956 (LIST)->aptr += sizeof(double), \ 957 ((LIST)->fanum < __VA_FARG_NUM \ 958 ? (LIST)->farg[(LIST)->fanum++] \ 959 : *(double*)((LIST)->aptr - sizeof(double)) \ 960 )) 961 #endif 962 #if defined(__ia64__) 963 /* The first 8 floating-point args have been stored elsewhere. */ 964 #define _va_arg_float(LIST) \ 965 ((LIST)->aptr += sizeof(__vaword), \ 966 ((LIST)->fanum < __VA_FARG_NUM \ 967 ? (float) (LIST)->farg[(LIST)->fanum++] \ 968 : *(float*)((LIST)->aptr - sizeof(__vaword)) \ 969 )) 970 #define _va_arg_double(LIST) \ 971 (__va_align_double(LIST) \ 972 (LIST)->aptr += sizeof(double), \ 973 ((LIST)->fanum < __VA_FARG_NUM \ 974 ? (LIST)->farg[(LIST)->fanum++] \ 975 : *(double*)((LIST)->aptr - sizeof(double)) \ 976 )) 977 #endif 978 #if defined(__x86_64_sysv__) 979 /* The first 8 floating-point args have been stored elsewhere. */ 980 #define _va_arg_float(LIST) \ 981 ((LIST)->fanum < __VA_FARG_NUM \ 982 ? *(float*)&(LIST)->farg[(LIST)->fanum++] \ 983 : ((LIST)->aptr += sizeof(__vaword), \ 984 *(float*)((LIST)->aptr - sizeof(__vaword)) \ 985 ) ) 986 #define _va_arg_double(LIST) \ 987 ((LIST)->fanum < __VA_FARG_NUM \ 988 ? (LIST)->farg[(LIST)->fanum++] \ 989 : ((LIST)->aptr += sizeof(__vaword), \ 990 *(double*)((LIST)->aptr - sizeof(__vaword)) \ 991 ) ) 992 #endif 993 #if defined(__s390__) || defined(__s390x__) 994 /* The first __VA_FARG_NUM floating-point args have been stored elsewhere. */ 995 #define _va_arg_float(LIST) \ 996 ((LIST)->fanum < __VA_FARG_NUM \ 997 ? (LIST)->farg[(LIST)->fanum++] \ 998 : ((LIST)->aptr += sizeof(__vaword), \ 999 ((float*)(LIST)->aptr)[-1] \ 1000 ) ) 1001 #define _va_arg_double(LIST) \ 1002 ((LIST)->fanum < __VA_FARG_NUM \ 1003 ? (LIST)->darg[(LIST)->fanum++] \ 1004 : ((LIST)->aptr += sizeof(double), \ 1005 *(double*)((LIST)->aptr - sizeof(double)) \ 1006 ) ) 1007 #endif 1008 #if defined(__riscv32__) || defined(__riscv64__) 1009 /* The first __VA_FARG_NUM floating-point args have been stored elsewhere. */ 1010 #define _va_arg_float(LIST) \ 1011 ((LIST)->fanum < __VA_FARG_NUM \ 1012 ? (LIST)->farg[(LIST)->fanum++] \ 1013 : __va_arg((LIST),float) \ 1014 ) 1015 #define _va_arg_double(LIST) \ 1016 ((LIST)->fanum < __VA_FARG_NUM \ 1017 ? (LIST)->darg[(LIST)->fanum++] \ 1018 : __va_arg((LIST),double) \ 1019 ) 1020 #endif 1021 #ifndef _va_arg_float 1022 #define _va_arg_float(LIST) __va_arg(LIST,float) 1023 #endif 1024 #ifndef _va_arg_double 1025 #define _va_arg_double(LIST) \ 1026 (__va_align_double(LIST) __va_arg(LIST,double)) 1027 #endif 1028 1029 /* Pointer arguments. */ 1030 #define _va_arg_ptr(LIST) __va_arg(LIST,void*) 1031 1032 /* Structure arguments. */ 1033 /* Structure argument alignment. */ 1034 #if defined(__i386__) && defined(_MSC_VER) 1035 /* In MSVC, doubles inside structures have alignment 8, i.e. 1036 * __VA_alignof(double) = 8, but doubles (and also structures containing 1037 * doubles) are passed on the stack with alignment 4. Looks really weird. 1038 */ 1039 #define __va_struct_alignment(TYPE_ALIGN) \ 1040 ((TYPE_ALIGN) <= 4 ? (TYPE_ALIGN) : 4) 1041 #else 1042 #define __va_struct_alignment(TYPE_ALIGN) \ 1043 (TYPE_ALIGN) 1044 #endif 1045 #define __va_align_struct(LIST,TYPE_SIZE,TYPE_ALIGN) \ 1046 (LIST)->aptr = ((LIST)->aptr + __va_struct_alignment(TYPE_ALIGN)-1) & -(intptr_t)__va_struct_alignment(TYPE_ALIGN), 1047 #if defined(__i386__) || defined(__m68k__) || defined(__alpha__) || defined(__arm__) || defined(__armhf__) || (defined(__powerpc64__) && !defined(_AIX)) || defined(__x86_64_sysv__) 1048 #define __va_arg_struct(LIST,TYPE_SIZE,TYPE_ALIGN) \ 1049 (__va_align_struct(LIST,TYPE_SIZE,TYPE_ALIGN) \ 1050 __va_arg_adjusted(LIST,TYPE_SIZE,TYPE_ALIGN) \ 1051 ) 1052 #endif 1053 #if defined(__mips__) && !defined(__mipsn32__) && !defined(__mips64__) 1054 /* small structures < 1 word are adjusted depending on compiler */ 1055 #define __va_arg_struct(LIST,TYPE_SIZE,TYPE_ALIGN) \ 1056 (__va_align_struct(LIST,TYPE_SIZE,TYPE_ALIGN) \ 1057 ((LIST)->flags & __VA_SGICC_STRUCT_ARGS \ 1058 ? /* SGI MIPS cc passes small structures left-adjusted, although big-endian! */\ 1059 (void*)__va_arg_leftadjusted(LIST,TYPE_SIZE,TYPE_ALIGN) \ 1060 : /* SGI MIPS gcc passes small structures within the first four words left- \ 1061 * adjusted, for compatibility with cc. But structures in memory are passed \ 1062 * right-adjusted!! See gcc-2.6.3/config/mips/mips.c:function_arg(). \ 1063 */ \ 1064 ((LIST)->aptr < (LIST)->memargptr \ 1065 ? (void*)__va_arg_leftadjusted(LIST,TYPE_SIZE,TYPE_ALIGN) \ 1066 : (void*)__va_arg_rightadjusted(LIST,TYPE_SIZE,TYPE_ALIGN) \ 1067 )) ) 1068 #endif 1069 #if defined(__mipsn32__) || defined(__mips64__) 1070 /* small structures < 1 word are adjusted depending on compiler */ 1071 #define __va_arg_struct(LIST,TYPE_SIZE,TYPE_ALIGN) \ 1072 (__va_align_struct(LIST,TYPE_SIZE,TYPE_ALIGN) \ 1073 ((LIST)->flags & __VA_SGICC_STRUCT_ARGS \ 1074 ? /* SGI MIPS cc and gcc >= 3.4 passes small structures left-adjusted, although big-endian! */\ 1075 (void*)__va_arg_leftadjusted(LIST,TYPE_SIZE,TYPE_ALIGN) \ 1076 : /* SGI MIPS gcc < 3.4 passes small structures right-adjusted. */ \ 1077 (void*)__va_arg_rightadjusted(LIST,TYPE_SIZE,TYPE_ALIGN) \ 1078 )) 1079 #endif 1080 #if defined(__powerpc_aix__) || (defined(__powerpc64__) && defined(_AIX)) 1081 /* small structures < 1 word are adjusted depending on compiler */ 1082 #define __va_arg_struct(LIST,TYPE_SIZE,TYPE_ALIGN) \ 1083 (__va_align_struct(LIST,TYPE_SIZE,TYPE_ALIGN) \ 1084 ((LIST)->flags & __VA_AIXCC_STRUCT_ARGS \ 1085 ? /* AIX cc and xlc pass small structures left-adjusted, although big-endian! */\ 1086 (void*)__va_arg_leftadjusted(LIST,TYPE_SIZE,TYPE_ALIGN) \ 1087 : /* gcc passes small structures right-adjusted. */ \ 1088 (void*)__va_arg_rightadjusted(LIST,TYPE_SIZE,TYPE_ALIGN) \ 1089 )) 1090 #endif 1091 #if defined(__powerpc_sysv4__) 1092 /* Structures are passed as pointers to caller-made local copies. */ 1093 #define __va_arg_struct(LIST,TYPE_SIZE,TYPE_ALIGN) \ 1094 va_arg_ptr(LIST,void*) 1095 #endif 1096 #if defined(__sparc__) && !defined(__sparc64__) 1097 /* Structures are passed as pointers to caller-made local copies. */ 1098 #define __va_arg_struct(LIST,TYPE_SIZE,TYPE_ALIGN) \ 1099 va_arg_ptr(LIST,void*) 1100 #endif 1101 #if defined(__sparc64__) 1102 /* Small structures are passed left-adjusted, although big-endian! */ 1103 /* Big structures are passed as pointers to caller-made local copies. */ 1104 #define __va_arg_struct(LIST,TYPE_SIZE,TYPE_ALIGN) \ 1105 ((TYPE_SIZE) <= 16 \ 1106 ? (__va_align_struct(LIST,TYPE_SIZE,TYPE_ALIGN) \ 1107 (void*)__va_arg_leftadjusted(LIST,TYPE_SIZE,TYPE_ALIGN)) \ 1108 : va_arg_ptr(LIST,void*) \ 1109 ) 1110 #endif 1111 #if defined(__hppa64__) 1112 /* Structures are passed left-adjusted (although big-endian!). */ 1113 #define __va_arg_struct(LIST,TYPE_SIZE,TYPE_ALIGN) \ 1114 (__va_align_struct(LIST,TYPE_SIZE,TYPE_ALIGN) \ 1115 (void*)__va_arg_leftadjusted(LIST,TYPE_SIZE,TYPE_ALIGN) \ 1116 ) 1117 #endif 1118 #if defined(__arm64__) || defined(__riscv32__) || defined(__riscv64__) 1119 /* Small structures are passed in registers or on the stack. */ 1120 /* Big structures are passed as pointers to caller-made local copies. */ 1121 #define __va_arg_struct(LIST,TYPE_SIZE,TYPE_ALIGN) \ 1122 ((TYPE_SIZE) <= 2*sizeof(__varword) \ 1123 ? (void*)__va_arg_adjusted(LIST,TYPE_SIZE,TYPE_ALIGN) \ 1124 : va_arg_ptr(LIST,void*) \ 1125 ) 1126 #endif 1127 #if defined(__x86_64_ms__) || defined(__s390__) || defined(__s390x__) 1128 /* Structures of 1, 2, 4, 8 bytes are passed as embedded copies on the arg stack. 1129 * Big structures are passed as pointers to caller-made local copies. 1130 */ 1131 #define __va_arg_struct(LIST,TYPE_SIZE,TYPE_ALIGN) \ 1132 ((TYPE_SIZE) == 1 || (TYPE_SIZE) == 2 || (TYPE_SIZE) == 4 || (TYPE_SIZE) == 8 \ 1133 ? (void*)__va_arg_adjusted(LIST,TYPE_SIZE,TYPE_ALIGN) \ 1134 : va_arg_ptr(LIST,void*) \ 1135 ) 1136 #endif 1137 #if defined(__hppa__) && !defined(__hppa64__) 1138 /* Structures <= 8 bytes are passed as embedded copies on the arg stack. 1139 * Big structures are passed as pointers (to caller-made local copies 1140 * with GCC >= 8, without copy otherwise). 1141 */ 1142 #define __va_arg_struct(LIST,TYPE_SIZE,TYPE_ALIGN) \ 1143 ((TYPE_SIZE) > 8 \ 1144 ? va_arg_ptr(LIST,void*) \ 1145 : /* FIXME: gcc-2.6.3 passes structures <= 4 bytes in memory left-adjusted! ?? */\ 1146 (void*)__va_arg_rightadjusted(LIST,TYPE_SIZE,TYPE_ALIGN) \ 1147 ) 1148 #endif 1149 #if defined(__ia64__) 1150 /* With GCC < 3, types larger than a word have 2-word alignment. */ 1151 #define __va_arg_struct(LIST,TYPE_SIZE,TYPE_ALIGN) \ 1152 (__va_align_struct(LIST,TYPE_SIZE,TYPE_ALIGN) \ 1153 (((LIST)->flags & __VA_OLDGCC_STRUCT_ARGS) && (TYPE_SIZE) > sizeof(__vaword) && (((__vaword*)(LIST)->aptr - (LIST)->saptr) & 1) ? (LIST)->aptr += sizeof(__vaword) : 0), \ 1154 __va_arg_adjusted(LIST,TYPE_SIZE,TYPE_ALIGN) \ 1155 ) 1156 #endif 1157 1158 1159 /* 1160 * Definition of the va_return_xxx macros. 1161 */ 1162 #define __va_return(LIST,RETTYPE) \ 1163 (((LIST)->rtype == (RETTYPE)) || (vacall_error_type_mismatch((LIST)->rtype,RETTYPE), 0)) 1164 #define _va_return_void(LIST) \ 1165 __va_return(LIST,__VAvoid) 1166 #define _va_return_char(LIST,VAL) \ 1167 (__va_return(LIST,__VAchar), (LIST)->tmp._char = (VAL)) 1168 #define _va_return_schar(LIST,VAL) \ 1169 (__va_return(LIST,__VAschar), (LIST)->tmp._schar = (VAL)) 1170 #define _va_return_uchar(LIST,VAL) \ 1171 (__va_return(LIST,__VAuchar), (LIST)->tmp._uchar = (VAL)) 1172 #define _va_return_short(LIST,VAL) \ 1173 (__va_return(LIST,__VAshort), (LIST)->tmp._short = (VAL)) 1174 #define _va_return_ushort(LIST,VAL) \ 1175 (__va_return(LIST,__VAushort), (LIST)->tmp._ushort = (VAL)) 1176 #define _va_return_int(LIST,VAL) \ 1177 (__va_return(LIST,__VAint), (LIST)->tmp._int = (VAL)) 1178 #define _va_return_uint(LIST,VAL) \ 1179 (__va_return(LIST,__VAuint), (LIST)->tmp._uint = (VAL)) 1180 #define _va_return_long(LIST,VAL) \ 1181 (__va_return(LIST,__VAlong), (LIST)->tmp._long = (VAL)) 1182 #define _va_return_ulong(LIST,VAL) \ 1183 (__va_return(LIST,__VAulong), (LIST)->tmp._ulong = (VAL)) 1184 #if defined(__mips64__) || defined(__sparc64__) || defined(__alpha__) || defined(__hppa64__) || defined(__arm64__) || defined(__powerpc64__) || defined(__ia64__) || (defined(__x86_64__) && !defined(__x86_64_x32__) && !defined(__VA_LLP64)) || defined(__riscv64__) 1185 #define _va_return_longlong(LIST,VAL) \ 1186 (__va_return(LIST,__VAlonglong), (LIST)->tmp._long = (VAL)) 1187 #define _va_return_ulonglong(LIST,VAL) \ 1188 (__va_return(LIST,__VAulonglong), (LIST)->tmp._ulong = (VAL)) 1189 #else 1190 #define _va_return_longlong(LIST,VAL) \ 1191 (__va_return(LIST,__VAlonglong), (LIST)->tmp._longlong = (VAL)) 1192 #define _va_return_ulonglong(LIST,VAL) \ 1193 (__va_return(LIST,__VAulonglong), (LIST)->tmp._ulonglong = (VAL)) 1194 #endif 1195 #define _va_return_float(LIST,VAL) \ 1196 (__va_return(LIST,__VAfloat), (LIST)->tmp._float = (VAL)) 1197 #define _va_return_double(LIST,VAL) \ 1198 (__va_return(LIST,__VAdouble), (LIST)->tmp._double = (VAL)) 1199 #define _va_return_ptr(LIST,VAL) \ 1200 (__va_return(LIST,__VAvoidp), (LIST)->tmp._ptr = (VAL)) 1201 #define __va_return_struct(LIST,TYPE_SIZE,TYPE_ALIGN,VAL_ADDR) \ 1202 (__va_return(LIST,__VAstruct), \ 1203 vacall_structcpy((void*)((LIST)->raddr),VAL_ADDR,TYPE_SIZE,TYPE_ALIGN) \ 1204 ) 1205 1206 1207 /* 1208 * Miscellaneous declarations. 1209 */ 1210 extern void vacall_structcpy (void* dest, const void* src, unsigned long size, unsigned long alignment); 1211 1212 1213 #endif /* _VACALL_INTERNAL_H */ 1214