Function application and closures
=================================

Sometimes all you have for a function is a pointer to it and a dynamic description of its arguments.  Calling such a function can be extremely difficult in standard C.  The routines in this section, particularly jit_apply, provide a convenient interface for doing this.

At other times, you may wish to wrap up one of your own dynamic functions in such a way that it appears to be a regular C function.  This is performed with jit_closure_create.

 -- Function: void jit_apply (jit_type_t signature, void *FUNC, void **ARGS, unsigned int NUM_FIXED_ARGS, void *RETURN_VALUE)
     Call a function that has a particular function signature. If the signature has more than NUM_FIXED_ARGS arguments, then it is assumed to be a vararg call, with the additional arguments passed in the vararg argument area on the stack. The SIGNATURE must specify the type of all arguments, including those in the vararg argument area.

 -- Function: void jit_apply_raw (jit_type_t SIGNATURE, void *FUNC, void *ARGS, void *RETURN_VALUE)
     Call a function, passing a set of raw arguments.  This can only be used if jit_raw_supported returns non-zero for the signature. The ARGS value is assumed to be an array of jit_nint values that correspond to each of the arguments.  Raw function calls are slightly faster than their non-raw counterparts, but can only be used in certain circumstances.

 -- Function: int jit_raw_supported (jit_type_t SIGNATURE)
     Determine if jit_apply_raw can be used to call functions with a particular signature.  Returns zero if not.

 -- Function: void * jit_closure_create (jit_context_t CONTEXT, jit_type_t SIGNATURE, jit_closure_func FUNC, void *USER_DATA)
     Create a closure from a function signature, a closure handling function, and a user data value.  Returns NULL if out of memory, or if closures are not supported.  The FUNC argument should have the following prototype:

          void func(jit_type_t signature, void *result, void **args, void *user_data);

     If the closure signature includes variable arguments, then args will contain pointers to the fixed arguments, followed by a jit_closure_va_list_t value for accessing the remainder of the arguments.

     The memory for the closure will be reclaimed when the CONTEXT is destroyed.

 -- Function: int jit_supports_closures (void)
     Determine if this platform has support for closures.

 -- Function: jit_nint jit_closure_va_get_nint (jit_closure_va_list_t VA)
 -- Function: jit_nuint jit_closure_va_get_nuint (jit_closure_va_list_t VA)
 -- Function: jit_long jit_closure_va_get_long (jit_closure_va_list_t VA)
 -- Function: jit_ulong jit_closure_va_get_ulong (jit_closure_va_list_t VA)
 -- Function: jit_float32 jit_closure_va_get_float32 (jit_closure_va_list_t VA)
 -- Function: jit_float64 jit_closure_va_get_float64 (jit_closure_va_list_t VA)
 -- Function: jit_nfloat jit_closure_va_get_nfloat (jit_closure_va_list_t VA)
 -- Function: void * jit_closure_va_get_ptr (jit_closure_va_list_t VA)
     Get the next value of a specific type from a closure's variable arguments.

 -- Function: void jit_closure_va_get_struct (jit_closure_va_list_t VA, void *BUF, jit_type_t TYPE)
     Get a structure or union value of a specific TYPE from a closure's variable arguments, and copy it into BUF.