gcc: Constructing Calls

1 
1 6.5 Constructing Function Calls
1 ===============================
1 
1 Using the built-in functions described below, you can record the
1 arguments a function received, and call another function with the same
1 arguments, without knowing the number or types of the arguments.
1 
1  You can also record the return value of that function call, and later
1 return that value, without knowing what data type the function tried to
1 return (as long as your caller expects that data type).
1 
1  However, these built-in functions may interact badly with some
1 sophisticated features or other extensions of the language.  It is,
1 therefore, not recommended to use them outside very simple functions
1 acting as mere forwarders for their arguments.
1 
1  -- Built-in Function: void * __builtin_apply_args ()
1      This built-in function returns a pointer to data describing how to
1      perform a call with the same arguments as are passed to the current
1      function.
1 
1      The function saves the arg pointer register, structure value
1      address, and all registers that might be used to pass arguments to
1      a function into a block of memory allocated on the stack.  Then it
1      returns the address of that block.
1 
1  -- Built-in Function: void * __builtin_apply (void (*FUNCTION)(), void
1           *ARGUMENTS, size_t SIZE)
1      This built-in function invokes FUNCTION with a copy of the
1      parameters described by ARGUMENTS and SIZE.
1 
1      The value of ARGUMENTS should be the value returned by
1      '__builtin_apply_args'.  The argument SIZE specifies the size of
1      the stack argument data, in bytes.
1 
1      This function returns a pointer to data describing how to return
1      whatever value is returned by FUNCTION.  The data is saved in a
1      block of memory allocated on the stack.
1 
1      It is not always simple to compute the proper value for SIZE.  The
1      value is used by '__builtin_apply' to compute the amount of data
1      that should be pushed on the stack and copied from the incoming
1      argument area.
1 
1  -- Built-in Function: void __builtin_return (void *RESULT)
1      This built-in function returns the value described by RESULT from
1      the containing function.  You should specify, for RESULT, a value
1      returned by '__builtin_apply'.
1 
1  -- Built-in Function: __builtin_va_arg_pack ()
1      This built-in function represents all anonymous arguments of an
1      inline function.  It can be used only in inline functions that are
1      always inlined, never compiled as a separate function, such as
1      those using '__attribute__ ((__always_inline__))' or '__attribute__
1      ((__gnu_inline__))' extern inline functions.  It must be only
1      passed as last argument to some other function with variable
1      arguments.  This is useful for writing small wrapper inlines for
1      variable argument functions, when using preprocessor macros is
1      undesirable.  For example:
1           extern int myprintf (FILE *f, const char *format, ...);
1           extern inline __attribute__ ((__gnu_inline__)) int
1           myprintf (FILE *f, const char *format, ...)
1           {
1             int r = fprintf (f, "myprintf: ");
1             if (r < 0)
1               return r;
1             int s = fprintf (f, format, __builtin_va_arg_pack ());
1             if (s < 0)
1               return s;
1             return r + s;
1           }
1 
1  -- Built-in Function: size_t __builtin_va_arg_pack_len ()
1      This built-in function returns the number of anonymous arguments of
1      an inline function.  It can be used only in inline functions that
1      are always inlined, never compiled as a separate function, such as
1      those using '__attribute__ ((__always_inline__))' or '__attribute__
1      ((__gnu_inline__))' extern inline functions.  For example following
1      does link- or run-time checking of open arguments for optimized
1      code:
1           #ifdef __OPTIMIZE__
1           extern inline __attribute__((__gnu_inline__)) int
1           myopen (const char *path, int oflag, ...)
1           {
1             if (__builtin_va_arg_pack_len () > 1)
1               warn_open_too_many_arguments ();
1 
1             if (__builtin_constant_p (oflag))
1               {
1                 if ((oflag & O_CREAT) != 0 && __builtin_va_arg_pack_len () < 1)
1                   {
1                     warn_open_missing_mode ();
1                     return __open_2 (path, oflag);
1                   }
1                 return open (path, oflag, __builtin_va_arg_pack ());
1               }
1 
1             if (__builtin_va_arg_pack_len () < 1)
1               return __open_2 (path, oflag);
1 
1             return open (path, oflag, __builtin_va_arg_pack ());
1           }
1           #endif
1