From: Richard Kenner Date: Fri, 14 Aug 1992 19:32:10 +0000 (-0400) Subject: Initial revision X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=6f837f81fcf631289a01f23bbc61476df7b2acdc;p=gcc.git Initial revision From-SVN: r1838 --- diff --git a/gcc/ginclude/va-alpha.h b/gcc/ginclude/va-alpha.h new file mode 100644 index 00000000000..37de6894b0f --- /dev/null +++ b/gcc/ginclude/va-alpha.h @@ -0,0 +1,186 @@ +/* GNU C varargs and stdargs support for the DEC Alpha. */ + +/* Note: We must use the name __builtin_savregs. GCC attaches special + significance to that name. In particular, regardless of where in a + function __builtin_saveregs is called, GCC moves the call up to the + very start of the function. */ + +/* Define __gnuc_va_list. */ + +#ifndef __GNUC_VA_LIST +#define __GNUC_VA_LIST + +typedef struct { + long __va_arg; /* Current argument number. */ + long *__va_stack; /* Start of arguments on stack */ + long *__va_iregs; /* Integer parameter registers ($16-$21) */ + long *__va_fregs; /* FP parameter registers ($f16-$f21) */ +} __gnuc_va_list; +#endif /* not __GNUC_VA_LIST */ + +/* If this is for internal libc use, don't define anything but + __gnuc_va_list. */ +#if defined (_STDARG_H) || defined (_VARARGS_H) + +#define va_list __gnuc_va_list +#define _VA_LIST +#define _VA_LIST_ + +#if !defined(_STDARG_H) + +/* varargs support */ +#define va_alist __builtin_va_alist +#define va_dcl +#define va_start(pvar) ((pvar) = * (__gnuc_va_list *) __builtin_saveregs ()) + +#else /* STDARG.H */ + +/* ANSI alternative. */ + +#define va_start(pvar, firstarg) \ + ((pvar) = *(__gnuc_va_list *) __builtin_saveregs ()) + +#endif /* _STDARG_H */ + +#define va_end(__va) + +/* Values returned by __builtin_classify_type. */ + +enum { + __no_type_class = -1, + __void_type_class, + __integer_type_class, + __char_type_class, + __enumeral_type_class, + __boolean_type_class, + __pointer_type_class, + __reference_type_class, + __offset_type_class, + __real_type_class, + __complex_type_class, + __function_type_class, + __method_type_class, + __record_type_class, + __union_type_class, + __array_type_class, + __string_type_class, + __set_type_class, + __file_type_class, + __lang_type_class +}; + +/* Note that parameters are always aligned at least to a word boundary + (when passed) regardless of what GCC's __alignof__ operator says. */ + +/* Avoid errors if compiling GCC v2 with GCC v1. */ +#if __GNUC__ == 1 +#define __extension__ +#endif + +/* Get the rounded number of words of a type. */ + +#define __va_nwords(__type) \ + ((sizeof (__type) + sizeof (long) - 1) / sizeof (long)) + +#define va_arg(__va, __type) \ +__extension__ \ +(* (__type *) \ + ({ \ + register void *__rv; /* result value */ \ + switch (__builtin_classify_type (* (__type *) 0)) \ + { \ + case __real_type_class: \ + \ + /* Get a pointer to the value. If we want a float instead of \ + a double, we have to make one and point to it instead. */ \ + \ + __rv = (void *) & (__va.__va_arg < 6 \ + ? __va.__va_fregs[__va.__va_arg] \ + : __va.__va_stack[__va.__va_arg - 6]); \ + \ + if (sizeof (__type) == sizeof (float)) \ + { \ + float __rf = * ((double *) __rv); \ + \ + __rv = (void *) &__rf; \ + } \ + \ + break; \ + \ + case __void_type_class: \ + case __integer_type_class: \ + case __char_type_class: \ + case __enumeral_type_class: \ + case __boolean_type_class: \ + case __pointer_type_class: \ + case __reference_type_class: \ + case __offset_type_class: \ + case __record_type_class: \ + case __union_type_class: \ + \ + /* Force this on the stack if it's alignment isn't right. */ \ + \ + if (__va.__va_arg < 6) \ + switch (sizeof (__type)) \ + { \ + case sizeof (char): \ + break; \ + case sizeof (short): \ + if (__alignof__ (__type) < sizeof (short)) \ + __va.__va_arg = 6; \ + break; \ + case 3: \ + case sizeof (int): \ + if (__alignof__ (__type) < sizeof (int)) \ + __va.__va_arg = 6; \ + break; \ + default: \ + if (__alignof__ (__type) < sizeof (long)) \ + __va.__va_arg = 6; \ + break; \ + } \ + \ + /* If this object is only one word long, just get it. If it is \ + longer, we need to worry about the possibility that it is \ + passed both in registers and in memory. */ \ + \ + if (sizeof (__type) <= sizeof (long) \ + || __va.__va_arg >= 6 \ + || __va.__va_arg + __va_nwords (__type) < 6) \ + __rv = (void *) & (__va.__va_arg < 6 \ + ? __va.__va_iregs[__va.__va_arg] \ + : __va.__va_stack[__va.__va_arg - 6]); \ + else \ + { \ + long __obj[__va_nwords (__type)]; \ + int __i; \ + \ + for (__i = 0; __i < __va_nwords (__type); __i++) \ + __obj[__i] = (__va.__va_arg < 6 \ + ? __va.__va_iregs[__va.__va_arg] \ + : __va.__va_stack[__va.__va_arg - 6]); \ + \ + __rv = (void *) &__obj[0]; \ + } \ + break; \ + \ + case __complex_type_class: \ + case __function_type_class: \ + case __method_type_class: \ + case __array_type_class: \ + case __string_type_class: \ + case __set_type_class: \ + case __file_type_class: \ + case __lang_type_class: \ + case __no_type_class: \ + default: \ + abort (); \ + } \ + \ + __va.__va_arg += __va_nwords (__type); \ + \ + __rv; \ +})) + +#endif /* defined (_STDARG_H) || defined (_VARARGS_H) */ +