GNU CC comes with an implementation of `varargs.h' and `stdarg.h' that work without change on machines that pass arguments on the stack. Other machines require their own implementations of varargs, and the two machine independent header files must have conditionals to include it.
ANSI `stdarg.h' differs from traditional `varargs.h' mainly in
the calling convention for
va_start. The traditional
implementation takes just one argument, which is the variable in which
to store the argument pointer. The ANSI implementation of
va_start takes an additional second argument. The user is
supposed to write the last named argument of the function here.
va_start should not use this argument. The way to find
the end of the named arguments is with the built-in functions described
__builtin_saveregs, unless you use
SETUP_INCOMING_VARARGS(see below) instead. On some machines,
__builtin_saveregsis open-coded under the control of the macro
EXPAND_BUILTIN_SAVEREGS. On other machines, it calls a routine written in assembler language, found in `libgcc2.c'. Code generated for the call to
__builtin_saveregsappears at the beginning of the function, as opposed to where the call to
__builtin_saveregsis written, regardless of what the code is. This is because the registers must be saved before the function starts to use them for its own purposes.
CUMULATIVE_ARGSdata type to record how many registers in each category have been used so far
__builtin_args_infoaccesses the same data structure of type
CUMULATIVE_ARGSafter the ordinary argument layout is finished with it, with category specifying which word to access. Thus, the value indicates the first unused register in a given category. Normally, you would use
__builtin_args_infoin the implementation of
va_start, accessing each category just once and storing the value in the
va_listobject. This is because
va_listwill have to update the values, and there is no way to alter the values accessed by
__builtin_args_info, for stack arguments. It returns the address of the first anonymous stack argument, as type
void *. If
ARGS_GROW_DOWNWARD, it returns the address of the location above the first anonymous stack argument. Use it in
va_startto initialize the pointer for fetching arguments from the stack. Also use it in
va_startto verify that the second parameter lastarg is the last named argument of the current function.
va_arghas to embody these conventions. The easiest way to categorize the specified data type is to use
__builtin_classify_typeignores the value of object, considering only its data type. It returns an integer describing what kind of type that is--integer, floating, pointer, structure, and so on. The file `typeclass.h' defines an enumeration that you can use to interpret the values of
These machine description macros help implement varargs:
__builtin_saveregs. This code will be moved to the very beginning of the function, before any parameter access are made. The return value of this function should be an RTX that contains the value to use as the return of
__builtin_saveregs. The argument args is a
tree_listcontaining the arguments that were passed to
__builtin_saveregs. If this macro is not defined, the compiler will output an ordinary call to the library function `__builtin_saveregs'.
SETUP_INCOMING_VARARGS (args_so_far, mode, type,
__builtin_saveregsand defining the macro
EXPAND_BUILTIN_SAVEREGS. Use it to store the anonymous register arguments into the stack so that all the arguments appear to have been passed consecutively on the stack. Once this is done, you can use the standard implementation of varargs that works for machines that pass all their arguments on the stack. The argument args_so_far is the
CUMULATIVE_ARGSdata structure, containing the values that obtain after processing of the named arguments. The arguments mode and type describe the last named argument--its machine mode and its data type as a tree node. The macro implementation should do two things: first, push onto the stack all the argument registers not used for the named arguments, and second, store the size of the data thus pushed into the
int-valued variable whose name is supplied as the argument pretend_args_size. The value that you store here will serve as additional offset for setting up the stack frame. Because you must generate code to push the anonymous arguments at compile time without knowing their data types,
SETUP_INCOMING_VARARGSis only useful on machines that have just a single category of argument register and use it uniformly for all data types. If the argument second_time is nonzero, it means that the arguments of the function are being analyzed for the second time. This happens for an inline function, which is not actually compiled until the end of the source file. The macro
SETUP_INCOMING_VARARGSshould not generate any instructions in this case.
FUNCTION_ARGis set for varargs and stdarg functions. If this macro returns a nonzero value, the named argument is always true for named arguments, and false for unnamed arguments. If it returns a value of zero, but
SETUP_INCOMING_VARARGSis defined, then all arguments are treated as named. Otherwise, all named arguments except the last are treated as named. You need not define this macro if it always returns zero.