home *** CD-ROM | disk | FTP | other *** search
- Newsgroups: gnu.gcc.help
- Path: sparky!uunet!stanford.edu!ames!haven.umd.edu!darwin.sura.net!wupost!gumby!destroyer!ncar!csn!news.den.mmc.com!traffic!kevin
- From: kevin@traffic.den.mmc.com (Kevin Rodgers)
- Subject: Re: gcc-2.2.2: varargs problem?
- Message-ID: <1992Aug31.160101.15510@den.mmc.com>
- Sender: news@den.mmc.com (News)
- Nntp-Posting-Host: traffic.den.mmc.com
- Organization: Martin Marietta Western Internal Systems, Technical Operations
- References: <1992Aug28.215327.2534@unixg.ubc.ca>
- Date: Mon, 31 Aug 1992 16:01:01 GMT
- Lines: 150
-
- In article <1992Aug28.215327.2534@unixg.ubc.ca> lindholm@ucs.ubc.ca (George Lindholm) writes:
- >How do I prototype and define a procedure that takes a variable number of
- >arguments?
-
- Here's the beginning of the relevant Info node:
-
- |File: gcc.info, Node: Varargs, Next: Trampolines, Prev: Stack and Calling, Up: Target Macros
- |
- |Implementing the Varargs Macros
- |===============================
- |
- | 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.
- |
- | However, `va_start' should not use this argument. The way to find
- |the end of the named arguments is with the built-in functions described
- |below.
-
- What is the justification for these last two sentences? Gcc 2.2.2 seems
- to compile vanilla ANSI stdarg code (under SunOS 4.1.1) just fine.
-
- And FYI, here's the rest of that Info node:
-
- |`__builtin_saveregs ()'
- | Use this built-in function to save the argument registers in
- | memory so that the varargs mechanism can access them. Both ANSI
- | and traditional versions of `va_start' must use
- | `__builtin_saveregs', unless you use `SETUP_INCOMING_VARARGS' (see
- | below) instead.
- |
- | On some machines, `__builtin_saveregs' is 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'.
- |
- | Regardless of what code is generated for the call to
- | `__builtin_saveregs', it appears at the beginning of the function,
- | not where the call to `__builtin_saveregs' is written. This is
- | because the registers must be saved before the function starts to
- | use them for its own purposes.
- |
- |`__builtin_args_info (CATEGORY)'
- | Use this built-in function to find the first anonymous arguments in
- | registers.
- |
- | In general, a machine may have several categories of registers
- | used for arguments, each for a particular category of data types.
- | (For example, on some machines, floating-point registers are used
- | for floating-point arguments while other arguments are passed in
- | the general registers.) To make non-varargs functions use the
- | proper calling convention, you have defined the `CUMULATIVE_ARGS'
- | data type to record how many registers in each category have been
- | used so far
- |
- | `__builtin_args_info' accesses the same data structure of type
- | `CUMULATIVE_ARGS' after 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_info' in the implementation
- | of `va_start', accessing each category just once and storing the
- | value in the `va_list' object. This is because `va_list' will
- | have to update the values, and there is no way to alter the values
- | accessed by `__builtin_args_info'.
- |
- |`__builtin_next_arg ()'
- | This is the equivalent of `__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_start' to initialize the pointer for
- | fetching arguments from the stack.
- |
- |`__builtin_classify_type (OBJECT)'
- | Since each machine has its own conventions for which data types are
- | passed in which kind of register, your implementation of `va_arg'
- | has to embody these conventions. The easiest way to categorize the
- | specified data type is to use `__builtin_classify_type' together
- | with `sizeof' and `__alignof__'.
- |
- | `__builtin_classify_type' ignores 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 `__builtin_classify_type'.
- |
- | These machine description macros help implement varargs:
- |
- |`EXPAND_BUILTIN_SAVEREGS (ARGS)'
- | If defined, is a C expression that produces the machine-specific
- | code for a call to `__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_list' containing 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, PRETEND_ARGS_SIZE, SECOND_TIME)'
- | This macro offers an alternative to using `__builtin_saveregs' and
- | 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_ARGS' data 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_VARARGS' is 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_VARARGS' should not generate any instructions in
- | this case.
- --
- Kevin Rodgers kevin@traffic.den.mmc.com
- Martin Marietta MS A16401 (303) 790-3971
- 116 Inverness Dr. East
- Englewood CO 80112 USA GO BUFFS!
-