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