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_R_H 19 #define _VACALL_R_H 20 21 #include <stddef.h> 22 23 #include "ffcall-abi.h" 24 25 26 /* Use a consistent prefix for all symbols in libcallback. */ 27 #define vacall_start callback_start 28 #define vacall_start_struct callback_start_struct 29 #define vacall_arg_char callback_arg_char 30 #define vacall_arg_schar callback_arg_schar 31 #define vacall_arg_uchar callback_arg_uchar 32 #define vacall_arg_short callback_arg_short 33 #define vacall_arg_ushort callback_arg_ushort 34 #define vacall_arg_int callback_arg_int 35 #define vacall_arg_uint callback_arg_uint 36 #define vacall_arg_long callback_arg_long 37 #define vacall_arg_ulong callback_arg_ulong 38 #define vacall_arg_longlong callback_arg_longlong 39 #define vacall_arg_ulonglong callback_arg_ulonglong 40 #define vacall_arg_float callback_arg_float 41 #define vacall_arg_double callback_arg_double 42 #define vacall_arg_ptr callback_arg_ptr 43 #define vacall_arg_struct callback_arg_struct 44 #define vacall_return_void callback_return_void 45 #define vacall_return_char callback_return_char 46 #define vacall_return_schar callback_return_schar 47 #define vacall_return_uchar callback_return_uchar 48 #define vacall_return_short callback_return_short 49 #define vacall_return_ushort callback_return_ushort 50 #define vacall_return_int callback_return_int 51 #define vacall_return_uint callback_return_uint 52 #define vacall_return_long callback_return_long 53 #define vacall_return_ulong callback_return_ulong 54 #define vacall_return_longlong callback_return_longlong 55 #define vacall_return_ulonglong callback_return_ulonglong 56 #define vacall_return_float callback_return_float 57 #define vacall_return_double callback_return_double 58 #define vacall_return_ptr callback_return_ptr 59 #define vacall_return_struct callback_return_struct 60 #define vacall_error_type_mismatch callback_error_type_mismatch 61 #define vacall_error_struct_too_large callback_error_struct_too_large 62 #define vacall_structcpy callback_structcpy 63 #define vacall_struct_buffer callback_struct_buffer 64 65 66 /* Determine whether the current ABI is LLP64 67 ('long' = 32-bit, 'long long' = 'void*' = 64-bit). */ 68 #if defined(__x86_64__) && defined(_WIN32) && !defined(__CYGWIN__) 69 #define __VA_LLP64 1 70 #endif 71 72 /* Determine the alignment of a type at compile time. 73 */ 74 #if defined(__GNUC__) || defined(__IBM__ALIGNOF__) 75 #define __VA_alignof __alignof__ 76 #elif defined(__cplusplus) 77 template <class type> struct __VA_alignof_helper { char __slot1; type __slot2; }; 78 #define __VA_alignof(type) offsetof (__VA_alignof_helper<type>, __slot2) 79 #elif defined(__mips__) || defined(__mipsn32__) || defined(__mips64__) /* SGI compiler */ 80 #define __VA_alignof __builtin_alignof 81 #else 82 #define __VA_offsetof(type,ident) ((unsigned long)&(((type*)0)->ident)) 83 #define __VA_alignof(type) __VA_offsetof(struct { char __slot1; type __slot2; }, __slot2) 84 #endif 85 86 #ifdef __cplusplus 87 extern "C" { 88 #endif 89 90 /* __vaword represents a single word that can be pushed on the stack. 91 * __varword represents a general-purpose register. 92 */ 93 #if defined(__arm64__) && defined(__APPLE__) && defined(__MACH__) 94 typedef int __vaword; 95 typedef long __varword; 96 #elif defined(__mipsn32__) || defined(__x86_64_x32__) || defined(__VA_LLP64) 97 typedef long long __vaword; 98 typedef long long __varword; 99 #else 100 typedef long __vaword; 101 typedef long __varword; 102 #endif 103 104 /* C builtin types. 105 */ 106 enum __VAtype 107 { 108 __VAvoid, 109 __VAchar, 110 __VAschar, 111 __VAuchar, 112 __VAshort, 113 __VAushort, 114 __VAint, 115 __VAuint, 116 __VAlong, 117 __VAulong, 118 __VAlonglong, 119 __VAulonglong, 120 __VAfloat, 121 __VAdouble, 122 __VAvoidp, 123 __VAstruct 124 }; 125 126 enum __VA_alist_flags 127 { 128 129 /* how to return structs */ 130 /* There are basically 3 ways to return structs: 131 * a. The called function returns a pointer to static data. Not reentrant. 132 * Not supported any more. 133 * b. The caller passes the return structure address in a dedicated register 134 * or as a first (or last), invisible argument. The called function stores 135 * its result there. 136 * c. Like b, and the called function also returns the return structure 137 * address in the return value register. (This is not very distinguishable 138 * from b.) 139 * Independently of this, 140 * r. small structures (<= 4 or <= 8 bytes) may be returned in the return 141 * value register(s), or 142 * m. even small structures are passed in memory. 143 */ 144 /* gcc-2.6.3 employs the following strategy: 145 * - If PCC_STATIC_STRUCT_RETURN is defined in the machine description 146 * it uses method a, else method c. 147 * - If flag_pcc_struct_return is set (either by -fpcc-struct-return or if 148 * DEFAULT_PCC_STRUCT_RETURN is defined to 1 in the machine description) 149 * it uses method m, else (either by -freg-struct-return or if 150 * DEFAULT_PCC_STRUCT_RETURN is defined to 0 in the machine description) 151 * method r. 152 */ 153 __VA_SMALL_STRUCT_RETURN = 1<<1, /* r: special case for small structs */ 154 __VA_GCC_STRUCT_RETURN = 1<<2, /* consider 8 byte structs as small */ 155 #if defined(__sparc__) && !defined(__sparc64__) 156 __VA_SUNCC_STRUCT_RETURN = 1<<3, 157 __VA_SUNPROCC_STRUCT_RETURN = 1<<4, 158 #else 159 __VA_SUNCC_STRUCT_RETURN = 0, 160 __VA_SUNPROCC_STRUCT_RETURN = 0, 161 #endif 162 #if defined(__i386__) 163 __VA_MSVC_STRUCT_RETURN = 1<<4, 164 #endif 165 /* the default way to return structs */ 166 /* This choice here is based on the assumption that the function you are 167 * going to call has been compiled with the same compiler you are using to 168 * include this file. 169 * If you want to call functions with another struct returning convention, 170 * just #define __VA_STRUCT_RETURN ... 171 * before or after #including <vacall_r.h>. 172 */ 173 #ifndef __VA_STRUCT_RETURN 174 __VA_STRUCT_RETURN = 175 #if defined(__sparc__) && !defined(__sparc64__) && defined(__sun) && (defined(__SUNPRO_C) || defined(__SUNPRO_CC)) /* SUNWspro cc or CC */ 176 __VA_SUNPROCC_STRUCT_RETURN, 177 #else 178 #if (defined(__i386__) && (defined(_WIN32) || defined(__CYGWIN__) || (defined(__MACH__) && defined(__APPLE__)) || defined(__FreeBSD__) || defined(__DragonFly__) || defined(__OpenBSD__))) || defined(__m68k__) || defined(__mipsn32__) || defined(__mips64__) || defined(__sparc64__) || defined(__hppa__) || defined(__hppa64__) || defined(__arm__) || defined(__armhf__) || defined(__arm64__) || defined(__powerpc64_elfv2__) || defined(__ia64__) || defined(__x86_64__) || defined(__riscv32__) || defined(__riscv64__) 179 __VA_SMALL_STRUCT_RETURN | 180 #endif 181 #if defined(__GNUC__) && !((defined(__mipsn32__) || defined(__mips64__)) && ((__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || (__GNUC__ > 3))) 182 __VA_GCC_STRUCT_RETURN | 183 #endif 184 #if defined(__i386__) && defined(_WIN32) && !defined(__CYGWIN__) /* native Windows */ 185 __VA_MSVC_STRUCT_RETURN | 186 #endif 187 0, 188 #endif 189 #endif 190 191 /* how to return floats */ 192 #if defined(__m68k__) || (defined(__sparc__) && !defined(__sparc64__)) 193 __VA_SUNCC_FLOAT_RETURN = 1<<5, 194 #endif 195 #if defined(__m68k__) 196 __VA_FREG_FLOAT_RETURN = 1<<6, 197 #endif 198 /* the default way to return floats */ 199 /* This choice here is based on the assumption that the function you are 200 * going to call has been compiled with the same compiler you are using to 201 * include this file. 202 * If you want to call functions with another float returning convention, 203 * just #define __VA_FLOAT_RETURN ... 204 * before or after #including <vacall_r.h>. 205 */ 206 #ifndef __VA_FLOAT_RETURN 207 #if (defined(__m68k__) || (defined(__sparc__) && !defined(__sparc64__))) && !defined(__GNUC__) && defined(__sun) && !(defined(__SUNPRO_C) || defined(__SUNPRO_CC)) /* Sun cc or CC */ 208 __VA_FLOAT_RETURN = __VA_SUNCC_FLOAT_RETURN, 209 #elif defined(__m68k__) 210 __VA_FLOAT_RETURN = __VA_FREG_FLOAT_RETURN, 211 #else 212 __VA_FLOAT_RETURN = 0, 213 #endif 214 #endif 215 216 /* how to pass structs */ 217 #if defined(__mips__) || defined(__mipsn32__) || defined(__mips64__) 218 __VA_SGICC_STRUCT_ARGS = 1<<7, 219 #endif 220 #if defined(__powerpc__) || defined(__powerpc64__) 221 __VA_AIXCC_STRUCT_ARGS = 1<<7, 222 #endif 223 #if defined(__ia64__) 224 __VA_OLDGCC_STRUCT_ARGS = 1<<7, 225 #endif 226 /* the default way to pass structs */ 227 /* This choice here is based on the assumption that the function you are 228 * going to call has been compiled with the same compiler you are using to 229 * include this file. 230 * If you want to call functions with another structs passing convention, 231 * just #define __VA_STRUCT_ARGS ... 232 * before or after #including <vacall_r.h>. 233 */ 234 #ifndef __VA_STRUCT_ARGS 235 #if (defined(__mips__) && !defined(__mipsn32__) && !defined(__mips64__)) && !defined(__GNUC__) /* SGI mips cc */ 236 __VA_STRUCT_ARGS = __VA_SGICC_STRUCT_ARGS, 237 #else 238 #if (defined(__mipsn32__) || defined(__mips64__)) && (!defined(__GNUC__) || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || (__GNUC__ > 3)) /* SGI mips cc or gcc >= 3.4 */ 239 __VA_STRUCT_ARGS = __VA_SGICC_STRUCT_ARGS, 240 #else 241 #if defined(__powerpc__) && !defined(__powerpc64__) && defined(_AIX) && !defined(__GNUC__) /* AIX 32-bit cc, xlc */ 242 __VA_STRUCT_ARGS = __VA_AIXCC_STRUCT_ARGS, 243 #else 244 #if defined(__powerpc64__) && defined(_AIX) /* AIX 64-bit cc, xlc, gcc, xlclang */ 245 __VA_STRUCT_ARGS = __VA_AIXCC_STRUCT_ARGS, 246 #else 247 #if defined(__ia64__) && !(defined(__GNUC__) && (__GNUC__ >= 3)) 248 __VA_STRUCT_ARGS = __VA_OLDGCC_STRUCT_ARGS, 249 #else 250 __VA_STRUCT_ARGS = 0, 251 #endif 252 #endif 253 #endif 254 #endif 255 #endif 256 #endif 257 258 /* how to pass floats */ 259 /* ANSI C compilers and GNU gcc pass floats as floats. 260 * K&R C compilers pass floats as doubles. We don't support them any more. 261 */ 262 #if defined(__powerpc64__) 263 __VA_AIXCC_FLOAT_ARGS = 1<<8, /* pass floats in the low 4 bytes of an 8-bytes word */ 264 #endif 265 /* the default way to pass floats */ 266 /* This choice here is based on the assumption that the function you are 267 * going to call has been compiled with the same compiler you are using to 268 * include this file. 269 * If you want to call functions with another float passing convention, 270 * just #define __VA_FLOAT_ARGS ... 271 * before or after #including <vacall_r.h>. 272 */ 273 #ifndef __VA_FLOAT_ARGS 274 #if defined(__powerpc64__) && defined(_AIX) && (defined(__ibmxl__) || !defined(__GNUC__)) /* AIX 64-bit xlc, xlclang */ 275 __VA_FLOAT_ARGS = __VA_AIXCC_FLOAT_ARGS, 276 #else 277 __VA_FLOAT_ARGS = 0, 278 #endif 279 #endif 280 281 /* how to pass and return small integer arguments */ 282 __VA_ANSI_INTEGERS = 0, /* no promotions */ 283 __VA_TRADITIONAL_INTEGERS = 0, /* promote [u]char, [u]short to [u]int */ 284 /* Fortunately these two methods are compatible. Our macros work with both. */ 285 286 /* stack cleanup policy */ 287 __VA_CDECL_CLEANUP = 0, /* caller pops args after return */ 288 __VA_STDCALL_CLEANUP = 1<<9, /* callee pops args before return */ 289 /* currently only supported on __i386__ */ 290 #ifndef __VA_CLEANUP 291 __VA_CLEANUP = __VA_CDECL_CLEANUP, 292 #endif 293 294 /* These are for internal use only */ 295 #if defined(__i386__) || defined(__m68k__) || defined(__mipsn32__) || defined(__mips64__) || defined(__sparc64__) || defined(__alpha__) || defined(__hppa64__) || defined(__arm__) || defined(__armhf__) || defined(__arm64__) || defined(__powerpc__) || defined(__powerpc64__) || defined(__ia64__) || defined(__x86_64__) || (defined(__s390__) && !defined(__s390x__)) || defined(__riscv64__) 296 __VA_REGISTER_STRUCT_RETURN = 1<<10, 297 #endif 298 #if defined(__mipsn32__) || defined(__mips64__) 299 __VA_REGISTER_FLOATSTRUCT_RETURN = 1<<11, 300 __VA_REGISTER_DOUBLESTRUCT_RETURN = 1<<12, 301 #endif 302 303 __VA_flag_for_broken_compilers_that_dont_like_trailing_commas 304 }; 305 306 /* 307 * Definition of the ‘va_alist’ type. 308 */ 309 struct vacall_alist 310 /* GNU clisp pokes in internals of the alist! */ 311 #ifdef LISPFUN 312 { 313 /* some va_... macros need these flags */ 314 int flags; 315 #if defined(__i386__) || defined(__arm__) || defined(__armhf__) || (defined(__powerpc__) && !defined(__powerpc64__) && defined(__MACH__) && defined(__APPLE__)) 316 __vaword filler1; 317 #endif 318 /* temporary storage for return value */ 319 union { 320 char _char; 321 signed char _schar; 322 unsigned char _uchar; 323 short _short; 324 unsigned short _ushort; 325 int _int; 326 unsigned int _uint; 327 long _long; 328 unsigned long _ulong; 329 long long _longlong; 330 unsigned long long _ulonglong; 331 float _float; 332 double _double; 333 void* _ptr; 334 } tmp; 335 } 336 #endif 337 ; 338 typedef struct vacall_alist * va_alist; 339 340 341 /* 342 * Definition of the va_start_xxx macros. 343 */ 344 #define __VA_START_FLAGS \ 345 __VA_STRUCT_RETURN | __VA_FLOAT_RETURN | __VA_STRUCT_ARGS | __VA_FLOAT_ARGS | __VA_CLEANUP 346 347 extern void vacall_start (va_alist /* LIST */, int /* RETTYPE */, int /* FLAGS */); 348 349 #define va_start_void(LIST) vacall_start(LIST,__VAvoid, __VA_START_FLAGS) 350 #define va_start_char(LIST) vacall_start(LIST,__VAchar, __VA_START_FLAGS) 351 #define va_start_schar(LIST) vacall_start(LIST,__VAschar, __VA_START_FLAGS) 352 #define va_start_uchar(LIST) vacall_start(LIST,__VAuchar, __VA_START_FLAGS) 353 #define va_start_short(LIST) vacall_start(LIST,__VAshort, __VA_START_FLAGS) 354 #define va_start_ushort(LIST) vacall_start(LIST,__VAushort, __VA_START_FLAGS) 355 #define va_start_int(LIST) vacall_start(LIST,__VAint, __VA_START_FLAGS) 356 #define va_start_uint(LIST) vacall_start(LIST,__VAuint, __VA_START_FLAGS) 357 #define va_start_long(LIST) vacall_start(LIST,__VAlong, __VA_START_FLAGS) 358 #define va_start_ulong(LIST) vacall_start(LIST,__VAulong, __VA_START_FLAGS) 359 #define va_start_longlong(LIST) vacall_start(LIST,__VAlonglong, __VA_START_FLAGS) 360 #define va_start_ulonglong(LIST) vacall_start(LIST,__VAulonglong,__VA_START_FLAGS) 361 #define va_start_float(LIST) vacall_start(LIST,__VAfloat, __VA_START_FLAGS) 362 #define va_start_double(LIST) vacall_start(LIST,__VAdouble, __VA_START_FLAGS) 363 #define va_start_ptr(LIST,TYPE) vacall_start(LIST,__VAvoidp, __VA_START_FLAGS) 364 365 /* 366 * va_start_struct: Preparing structure return. 367 */ 368 extern void vacall_start_struct (va_alist /* LIST */, size_t /* TYPE_SIZE */, size_t /* TYPE_ALIGN */, int /* TYPE_SPLITTABLE */, int /* FLAGS */); 369 370 #define va_start_struct(LIST,TYPE,TYPE_SPLITTABLE) \ 371 _va_start_struct(LIST,sizeof(TYPE),__VA_alignof(TYPE),TYPE_SPLITTABLE) 372 /* _va_start_struct() is like va_start_struct(), except that you pass 373 * the type's size and alignment instead of the type itself. 374 * Undocumented, but used by GNU clisp. 375 */ 376 #define _va_start_struct(LIST,TYPE_SIZE,TYPE_ALIGN,TYPE_SPLITTABLE) \ 377 vacall_start_struct(LIST,TYPE_SIZE,TYPE_ALIGN,TYPE_SPLITTABLE,__VA_START_FLAGS) 378 379 380 /* 381 * Definition of the va_arg_xxx macros. 382 */ 383 384 extern char vacall_arg_char (va_alist /* LIST */); 385 extern signed char vacall_arg_schar (va_alist /* LIST */); 386 extern unsigned char vacall_arg_uchar (va_alist /* LIST */); 387 extern short vacall_arg_short (va_alist /* LIST */); 388 extern unsigned short vacall_arg_ushort (va_alist /* LIST */); 389 extern int vacall_arg_int (va_alist /* LIST */); 390 extern unsigned int vacall_arg_uint (va_alist /* LIST */); 391 extern long vacall_arg_long (va_alist /* LIST */); 392 extern unsigned long vacall_arg_ulong (va_alist /* LIST */); 393 394 #define va_arg_char(LIST) vacall_arg_char(LIST) 395 #define va_arg_schar(LIST) vacall_arg_schar(LIST) 396 #define va_arg_uchar(LIST) vacall_arg_uchar(LIST) 397 #define va_arg_short(LIST) vacall_arg_short(LIST) 398 #define va_arg_ushort(LIST) vacall_arg_ushort(LIST) 399 #define va_arg_int(LIST) vacall_arg_int(LIST) 400 #define va_arg_uint(LIST) vacall_arg_uint(LIST) 401 #define va_arg_long(LIST) vacall_arg_long(LIST) 402 #define va_arg_ulong(LIST) vacall_arg_ulong(LIST) 403 404 extern long long vacall_arg_longlong (va_alist /* LIST */); 405 extern unsigned long long vacall_arg_ulonglong (va_alist /* LIST */); 406 407 #define va_arg_longlong(LIST) vacall_arg_longlong(LIST) 408 #define va_arg_ulonglong(LIST) vacall_arg_ulonglong(LIST) 409 410 /* Floating point arguments. */ 411 412 extern float vacall_arg_float (va_alist /* LIST */); 413 extern double vacall_arg_double (va_alist /* LIST */); 414 415 #define va_arg_float(LIST) vacall_arg_float(LIST) 416 #define va_arg_double(LIST) vacall_arg_double(LIST) 417 418 /* Pointer arguments. */ 419 420 extern void* vacall_arg_ptr (va_alist /* LIST */); 421 #define va_arg_ptr(LIST,TYPE) ((TYPE)vacall_arg_ptr(LIST)) 422 423 /* Structure arguments. */ 424 425 extern void* vacall_arg_struct (va_alist /* LIST */, size_t /* TYPE_SIZE */, size_t /* TYPE_ALIGN */); 426 427 #define va_arg_struct(LIST,TYPE) \ 428 *(TYPE*)vacall_arg_struct(LIST,sizeof(TYPE),__VA_alignof(TYPE)) 429 /* _va_arg_struct() is like va_arg_struct(), except that you pass the type's 430 * size and alignment instead of the type and get the value's address instead 431 * of the value itself. 432 * Undocumented, but used by GNU clisp. 433 */ 434 #define _va_arg_struct(LIST,TYPE_SIZE,TYPE_ALIGN) \ 435 vacall_arg_struct(LIST,TYPE_SIZE,TYPE_ALIGN) 436 437 438 /* 439 * Definition of the va_return_xxx macros. 440 */ 441 442 extern void vacall_return_void (va_alist /* LIST */); 443 #define va_return_void(LIST) vacall_return_void(LIST) 444 445 extern void vacall_return_char (va_alist /* LIST */, char /* VAL */); 446 extern void vacall_return_schar (va_alist /* LIST */, signed char /* VAL */); 447 extern void vacall_return_uchar (va_alist /* LIST */, unsigned char /* VAL */); 448 extern void vacall_return_short (va_alist /* LIST */, short /* VAL */); 449 extern void vacall_return_ushort (va_alist /* LIST */, unsigned short /* VAL */); 450 extern void vacall_return_int (va_alist /* LIST */, int /* VAL */); 451 extern void vacall_return_uint (va_alist /* LIST */, unsigned int /* VAL */); 452 extern void vacall_return_long (va_alist /* LIST */, long /* VAL */); 453 extern void vacall_return_ulong (va_alist /* LIST */, unsigned long /* VAL */); 454 #define va_return_char(LIST,VAL) vacall_return_char(LIST,VAL) 455 #define va_return_schar(LIST,VAL) vacall_return_schar(LIST,VAL) 456 #define va_return_uchar(LIST,VAL) vacall_return_uchar(LIST,VAL) 457 #define va_return_short(LIST,VAL) vacall_return_short(LIST,VAL) 458 #define va_return_ushort(LIST,VAL) vacall_return_ushort(LIST,VAL) 459 #define va_return_int(LIST,VAL) vacall_return_int(LIST,VAL) 460 #define va_return_uint(LIST,VAL) vacall_return_uint(LIST,VAL) 461 #define va_return_long(LIST,VAL) vacall_return_long(LIST,VAL) 462 #define va_return_ulong(LIST,VAL) vacall_return_ulong(LIST,VAL) 463 464 extern void vacall_return_longlong (va_alist /* LIST */, long long /* VAL */); 465 extern void vacall_return_ulonglong (va_alist /* LIST */, unsigned long long /* VAL */); 466 #define va_return_longlong(LIST,VAL) vacall_return_longlong(LIST,VAL) 467 #define va_return_ulonglong(LIST,VAL) vacall_return_ulonglong(LIST,VAL) 468 469 extern void vacall_return_float (va_alist /* LIST */, float /* VAL */); 470 extern void vacall_return_double (va_alist /* LIST */, double /* VAL */); 471 #define va_return_float(LIST,VAL) vacall_return_float(LIST,VAL) 472 #define va_return_double(LIST,VAL) vacall_return_double(LIST,VAL) 473 474 extern void vacall_return_ptr (va_alist /* LIST */, void* /* VAL */); 475 #define va_return_ptr(LIST,TYPE,VAL) vacall_return_ptr(LIST,(void*)(TYPE)(VAL)) 476 477 extern void vacall_return_struct (va_alist /* LIST */, size_t /* TYPE_SIZE */, size_t /* TYPE_ALIGN */, const void* /* VAL_ADDR */); 478 479 #define va_return_struct(LIST,TYPE,VAL) \ 480 _va_return_struct(LIST,sizeof(TYPE),__VA_alignof(TYPE),&(VAL)) 481 /* Undocumented, but used by GNU clisp. */ 482 #define _va_return_struct(LIST,TYPE_SIZE,TYPE_ALIGN,VAL_ADDR) \ 483 vacall_return_struct(LIST,TYPE_SIZE,TYPE_ALIGN,VAL_ADDR) 484 485 486 /* Determine whether a struct type is word-splittable, i.e. whether each of 487 * its components fit into a register. 488 * The entire computation is done at compile time. 489 */ 490 #define va_word_splittable_1(slot1) \ 491 (__va_offset1(slot1)/sizeof(__vaword) == (__va_offset1(slot1)+sizeof(slot1)-1)/sizeof(__vaword)) 492 #define va_word_splittable_2(slot1,slot2) \ 493 ((__va_offset1(slot1)/sizeof(__vaword) == (__va_offset1(slot1)+sizeof(slot1)-1)/sizeof(__vaword)) \ 494 && (__va_offset2(slot1,slot2)/sizeof(__vaword) == (__va_offset2(slot1,slot2)+sizeof(slot2)-1)/sizeof(__vaword)) \ 495 ) 496 #define va_word_splittable_3(slot1,slot2,slot3) \ 497 ((__va_offset1(slot1)/sizeof(__vaword) == (__va_offset1(slot1)+sizeof(slot1)-1)/sizeof(__vaword)) \ 498 && (__va_offset2(slot1,slot2)/sizeof(__vaword) == (__va_offset2(slot1,slot2)+sizeof(slot2)-1)/sizeof(__vaword)) \ 499 && (__va_offset3(slot1,slot2,slot3)/sizeof(__vaword) == (__va_offset3(slot1,slot2,slot3)+sizeof(slot3)-1)/sizeof(__vaword)) \ 500 ) 501 #define va_word_splittable_4(slot1,slot2,slot3,slot4) \ 502 ((__va_offset1(slot1)/sizeof(__vaword) == (__va_offset1(slot1)+sizeof(slot1)-1)/sizeof(__vaword)) \ 503 && (__va_offset2(slot1,slot2)/sizeof(__vaword) == (__va_offset2(slot1,slot2)+sizeof(slot2)-1)/sizeof(__vaword)) \ 504 && (__va_offset3(slot1,slot2,slot3)/sizeof(__vaword) == (__va_offset3(slot1,slot2,slot3)+sizeof(slot3)-1)/sizeof(__vaword)) \ 505 && (__va_offset4(slot1,slot2,slot3,slot4)/sizeof(__vaword) == (__va_offset4(slot1,slot2,slot3,slot4)+sizeof(slot4)-1)/sizeof(__vaword)) \ 506 ) 507 #define __va_offset1(slot1) \ 508 0 509 #define __va_offset2(slot1,slot2) \ 510 ((__va_offset1(slot1)+sizeof(slot1)+__VA_alignof(slot2)-1) & -(long)__VA_alignof(slot2)) 511 #define __va_offset3(slot1,slot2,slot3) \ 512 ((__va_offset2(slot1,slot2)+sizeof(slot2)+__VA_alignof(slot3)-1) & -(long)__VA_alignof(slot3)) 513 #define __va_offset4(slot1,slot2,slot3,slot4) \ 514 ((__va_offset3(slot1,slot2,slot3)+sizeof(slot3)+__VA_alignof(slot4)-1) & -(long)__VA_alignof(slot4)) 515 516 517 /* 518 * Miscellaneous declarations. 519 */ 520 521 #if defined(__sparc__) || defined(__sparc64__) 522 /* On SPARC, PIC compiled code crashes when used outside of a shared library. 523 Therefore, don't use the callback_get_receiver indirection on this platform. */ 524 525 extern 526 #ifdef __cplusplus 527 "C" 528 #endif 529 void callback_receiver (); /* Actually it takes arguments and returns values! */ 530 531 #define callback_get_receiver() (&callback_receiver) 532 533 #else 534 535 /* A fake type for callback_receiver. 536 Actually it takes arguments and returns values. */ 537 typedef void (*__vacall_r_t) (void); 538 539 /* This function returns the address of callback_receiver. 540 callback_receiver is not a global symbol, because on ELF platforms, functions 541 with global visibility cannot accept additional arguments in registers. See 542 elf-hack.txt for more details. */ 543 extern 544 #ifdef __cplusplus 545 "C" 546 #endif 547 __vacall_r_t callback_get_receiver (void); 548 549 #endif 550 551 552 #ifdef __cplusplus 553 } 554 #endif 555 556 #endif /* _VACALL_R_H */ 557