xref: /original-bsd/sys/sparc/include/stdarg.h (revision 3705696b)
1 /*
2  * Copyright (c) 1992, 1993
3  *	The Regents of the University of California.  All rights reserved.
4  *
5  * This software was developed by the Computer Systems Engineering group
6  * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
7  * contributed to Berkeley.
8  *
9  * All advertising materials mentioning features or use of this software
10  * must display the following acknowledgement:
11  *	This product includes software developed by the University of
12  *	California, Lawrence Berkeley Laboratory.
13  *
14  * %sccs.include.redist.c%
15  *
16  *	@(#)stdarg.h	8.1 (Berkeley) 06/11/93
17  *
18  * from: $Header: stdarg.h,v 1.8 93/05/07 18:10:14 torek Exp $
19  */
20 
21 /*
22  * SPARC stdarg.h
23  */
24 
25 #ifndef _MACHINE_STDARG_H
26 #define _MACHINE_STDARG_H
27 
28 typedef char *va_list;
29 
30 /*
31  * va_start sets ap to point to the first variable argument.
32  * The `last fixed argument' parameter l is ignored (and should
33  * never have been included in the ANSI standard!).
34  *
35  * va_end cleans up after va_start.  There is nothing to do there.
36  */
37 #define va_start(ap, l)	(__builtin_saveregs(), \
38 			 ap = (char *)__builtin_next_arg())
39 #define va_end(ap)	/* empty */
40 
41 #if __GNUC__ == 1
42 #define __extension__	/* hack for bootstrapping via gcc 1.x */
43 #endif
44 
45 /*
46  * va_arg picks up the next argument of type `ty'.  Appending an
47  * asterisk to ty must produce a pointer to ty (i.e., ty may not be,
48  * e.g., `int (*)()').  In addition, ty must not be any type which
49  * undergoes promotion to some other type (e.g., char): it must
50  * be the promoted type instead.
51  *
52  * Gcc-2.x tries to use ldd/std for double and quad_t values, but Sun's
53  * brain-damaged calling convention does not quad-align these.  Thus,
54  * for 8-byte arguments, we have to pick up the actual value four bytes
55  * at a time, and use type punning (i.e., a union) to produce the result.
56  * (We could also do this with a libc function, actually, by returning
57  * 8 byte integers in %o0+%o1 and the same 8 bytes as a double in %f0+%f1.)
58  *
59  * Note: we cannot use the union trick (which generates better code) for
60  * C++, since `ty' might be a type with a constructor (these may not appear
61  * in a union).
62  *
63  * The extraneous casts through `void *' avoid gcc alignment warnings.
64  */
65 #ifdef __cplusplus
66 #define	__va_8byte(ap, ty) ({ \
67 	int __va_i[2]; \
68 	__va_i[0] = ((int *)(void *)(ap))[0]; \
69 	__va_i[1] = ((int *)(void *)(ap))[1]; \
70 	(ap) += 8; *(ty *)(void *)__va_i; })
71 #else
72 #define	__va_8byte(ap, ty) ({ \
73 	union { ty __d; int __i[2]; } __va_u; \
74 	__va_u.__i[0] = ((int *)(void *)(ap))[0]; \
75 	__va_u.__i[1] = ((int *)(void *)(ap))[1]; \
76 	(ap) += 8; __va_u.__d; })
77 #endif /* __cplusplus */
78 
79 #define va_arg(ap, ty) __extension__ ({ \
80     ty __va_temp; /* to check for invisible-ptr struct-valued args */ \
81     __builtin_classify_type(__va_temp) >= 12 ? \
82 	((ty **)(void *)((ap) += sizeof(ty *)))[-1][0] : \
83     sizeof(ty) == 8 ? __va_8byte(ap, ty) : \
84 	((ty *)(void *)(ap += sizeof(ty)))[-1]; })
85 
86 #endif /* _MACHINE_STDARG_H */
87