Using the built-in functions described below, you can record the arguments a function received, and call another function with the same arguments, without knowing the number or types of the arguments.
You can also record the return value of that function call, and later return that value, without knowing what data type the function tried to return (as long as your caller expects that data type).
However, these built-in functions may interact badly with some sophisticated features or other extensions of the language. It is, therefore, not recommended to use them outside very simple functions acting as mere forwarders for their arguments.
void * __builtin_apply_args () ¶This built-in function returns a pointer to data describing how to perform a call with the same arguments as are passed to the current function.
The function saves the arg pointer register, structure value address, and all registers that might be used to pass arguments to a function into a block of memory allocated on the stack. Then it returns the address of that block.
void * __builtin_apply (void (*function)(), void *arguments, size_t size) ¶This built-in function invokes function with a copy of the parameters described by arguments and size.
The value of arguments should be the value returned by
__builtin_apply_args. The argument size specifies the size
of the stack argument data, in bytes.
This function returns a pointer to data describing how to return whatever value is returned by function. The data is saved in a block of memory allocated on the stack.
It is not always simple to compute the proper value for size. The
value is used by __builtin_apply to compute the amount of data
that should be pushed on the stack and copied from the incoming argument
area.
void __builtin_return (void *result) ¶This built-in function returns the value described by result from
the containing function. You should specify, for result, a value
returned by __builtin_apply.
() ¶This built-in function represents all anonymous arguments of an inline
function. It can be used only in inline functions that are always
inlined, never compiled as a separate function, such as those using
__attribute__ ((__always_inline__)) or
__attribute__ ((__gnu_inline__)) extern inline functions.
It must be only passed as last argument to some other function
with variable arguments. This is useful for writing small wrapper
inlines for variable argument functions, when using preprocessor
macros is undesirable. For example:
extern int myprintf (FILE *f, const char *format, ...);
extern inline __attribute__ ((__gnu_inline__)) int
myprintf (FILE *f, const char *format, ...)
{
int r = fprintf (f, "myprintf: ");
if (r < 0)
return r;
int s = fprintf (f, format, __builtin_va_arg_pack ());
if (s < 0)
return s;
return r + s;
}
int __builtin_va_arg_pack_len () ¶This built-in function returns the number of anonymous arguments of
an inline function. It can be used only in inline functions that
are always inlined, never compiled as a separate function, such
as those using __attribute__ ((__always_inline__)) or
__attribute__ ((__gnu_inline__)) extern inline functions.
For example following does link- or run-time checking of open
arguments for optimized code:
#ifdef __OPTIMIZE__
extern inline __attribute__((__gnu_inline__)) int
myopen (const char *path, int oflag, ...)
{
if (__builtin_va_arg_pack_len () > 1)
warn_open_too_many_arguments ();
if (__builtin_constant_p (oflag))
{
if ((oflag & O_CREAT) != 0 && __builtin_va_arg_pack_len () < 1)
{
warn_open_missing_mode ();
return __open_2 (path, oflag);
}
return open (path, oflag, __builtin_va_arg_pack ());
}
if (__builtin_va_arg_pack_len () < 1)
return __open_2 (path, oflag);
return open (path, oflag, __builtin_va_arg_pack ());
}
#endif
type __builtin_call_with_static_chain (call_exp, pointer_exp) ¶The call_exp expression must be a function call, and the
pointer_exp expression must be a pointer. The pointer_exp
is passed to the function call in the target’s static chain location.
The result of the built-in is the result of the function call.
This built-in can be used to call Go closures from C, and it can be
used to call See Nested Functions using the code address and
static chain obtained with __builtin_call_code_address and
__builtin_call_static_chain, respectively.
int process(int (*callback)(int, void *), void *data)
{
int value = 5;
return (*callback)(value, data);
}
struct call_info {
int (*code)(int);
void *chain;
};
int callback(int arg, void *data)
{
struct call_info *ci = data;
return __builtin_call_with_static_chain(ci->code(arg), ci->chain);
}
int doit(int x)
{
int worker(int y)
{
return x + y;
}
struct call_info ci = {
ci.code = __builtin_call_code_address(worker),
ci.chain = __builtin_call_static_chain(worker),
};
return process(callback, &ci);
}
Note: This built-in is only available for C.
type __builtin_call_static_chain (pointer_exp) ¶The pointer_exp expression must a function identifier.
The result is the static chain pointer that can be used to call
the function in its current context using the built-in
__builtin_call_with_static_chain, or a null pointer if
no static chain is needed.
Note: The lifetime of a nested function that accesses the environment of an enclosing function is limited. Any use of the static chain after this lifetime has ended has undefined behavior.
type __builtin_call_code_address (pointer_exp) ¶The pointer_exp expression must be a function identifier.
The result is the static address of the function. For a nested function,
it represents the address of the underlying machine code and not of a
trampoline that would otherwise be generated to setup the static chain.
The code address can be used together with a static chain pointer to
call the function with the built-in __builtin_call_with_static_chain.
Note: Calling a function that requires a static chain using the code address directly in a function call expression has undefined behavior.