github.com/goccy/go-jit@v0.0.0-20200514131505-ff78d45cf6af/internal/ccall/jit-apply.c (about)

     1  /*
     2   * jit-apply.c - Dynamic invocation and closure support functions.
     3   *
     4   * Copyright (C) 2004  Southern Storm Software, Pty Ltd.
     5   *
     6   * This file is part of the libjit library.
     7   *
     8   * The libjit library is free software: you can redistribute it and/or
     9   * modify it under the terms of the GNU Lesser General Public License
    10   * as published by the Free Software Foundation, either version 2.1 of
    11   * the License, or (at your option) any later version.
    12   *
    13   * The libjit library is distributed in the hope that it will be useful,
    14   * but WITHOUT ANY WARRANTY; without even the implied warranty of
    15   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    16   * Lesser General Public License for more details.
    17   *
    18   * You should have received a copy of the GNU Lesser General Public
    19   * License along with the libjit library.  If not, see
    20   * <http://www.gnu.org/licenses/>.
    21   */
    22  
    23  #include "jit-internal.h"
    24  #include "jit-apply-rules.h"
    25  #include "jit-apply-func.h"
    26  #if HAVE_STDLIB_H
    27  # include <stdlib.h>
    28  #endif
    29  #if HAVE_ALLOCA_H
    30  # include <alloca.h>
    31  #endif
    32  #ifdef JIT_WIN32_PLATFORM
    33  # include <malloc.h>
    34  # ifndef alloca
    35  #  define alloca	_alloca
    36  # endif
    37  #endif
    38  
    39  /*
    40  
    41  If you need to tweak the way that this code behaves for a specific
    42  platform, then you would normally do it in "tools/gen-apply.c" or
    43  the CPU-specific "jit-apply-XXX.h" file, not here.
    44  
    45  */
    46  
    47  /*@
    48  
    49  @section Function application and closures
    50  @cindex Function application
    51  @cindex Closures
    52  @cindex jit-apply.h
    53  
    54  Sometimes all you have for a function is a pointer to it and a dynamic
    55  description of its arguments.  Calling such a function can be extremely
    56  difficult in standard C.  The routines in this section, particularly
    57  @code{jit_apply}, provide a convenient interface for doing this.
    58  
    59  At other times, you may wish to wrap up one of your own dynamic functions
    60  in such a way that it appears to be a regular C function.  This is
    61  performed with @code{jit_closure_create}.
    62  
    63  @*/
    64  
    65  typedef enum
    66  {
    67  	_JIT_APPLY_RETURN_TYPE_OTHER = 0,
    68  	_JIT_APPLY_RETURN_TYPE_FLOAT32 = 1,
    69  	_JIT_APPLY_RETURN_TYPE_FLOAT64 = 2,
    70  	_JIT_APPLY_RETURN_TYPE_NFLOAT = 3
    71  } _jit_apply_return_type;
    72  
    73  /*
    74   * Flags that indicate which structure sizes are returned in registers.
    75   */
    76  unsigned char const _jit_apply_return_in_reg[] =
    77  		JIT_APPLY_STRUCT_RETURN_IN_REG_INIT;
    78  
    79  /*
    80   * Get the maximum argument stack size of a signature type.
    81   */
    82  static unsigned int
    83  jit_type_get_max_arg_size(jit_type_t signature)
    84  {
    85  	unsigned int size;
    86  	unsigned int typeSize;
    87  	unsigned int param;
    88  	jit_type_t type;
    89  	if(signature->size)
    90  	{
    91  		/* We have a cached argument size from last time */
    92  		return signature->size;
    93  	}
    94  	size = 0;
    95  	param = jit_type_num_params(signature);
    96  	while(param > 0)
    97  	{
    98  		--param;
    99  		type = jit_type_remove_tags(jit_type_get_param(signature, param));
   100  		switch(type->kind)
   101  		{
   102  		case JIT_TYPE_SBYTE:
   103  		case JIT_TYPE_UBYTE:
   104  		case JIT_TYPE_SHORT:
   105  		case JIT_TYPE_USHORT:
   106  		case JIT_TYPE_INT:
   107  		case JIT_TYPE_UINT:
   108  		case JIT_TYPE_NINT:
   109  		case JIT_TYPE_NUINT:
   110  		case JIT_TYPE_PTR:
   111  		case JIT_TYPE_SIGNATURE:
   112  			size += sizeof(jit_nint);
   113  			break;
   114  
   115  		case JIT_TYPE_LONG:
   116  		case JIT_TYPE_ULONG:
   117  #ifdef JIT_NATIVE_INT32
   118  			/* Add one extra word for possible alignment padding */
   119  			size += sizeof(jit_long) + sizeof(jit_nint);
   120  #else
   121  			size += sizeof(jit_nint);
   122  #endif
   123  			break;
   124  
   125  		case JIT_TYPE_FLOAT32:
   126  		case JIT_TYPE_FLOAT64:
   127  		case JIT_TYPE_NFLOAT:
   128  			/* Allocate space for an "nfloat" and an alignment word */
   129  			size += sizeof(jit_nfloat) + sizeof(jit_nint) * 2 - 1;
   130  			size &= ~(sizeof(jit_nint) - 1);
   131  			break;
   132  
   133  		case JIT_TYPE_STRUCT:
   134  		case JIT_TYPE_UNION:
   135  			/* Allocate space for the structure and an alignment word */
   136  			typeSize = jit_type_get_size(type);
   137  			size += typeSize + sizeof(jit_nint) * 2 - 1;
   138  			size &= ~(sizeof(jit_nint) - 1);
   139  			break;
   140  		}
   141  	}
   142  	type = jit_type_get_return(signature);
   143  	if(jit_type_is_struct(type) || jit_type_is_union(type))
   144  	{
   145  		/* Add one extra word for the possibility of a structure pointer */
   146  		size += sizeof(jit_nint);
   147  	}
   148  	signature->size = size;
   149  	return size;
   150  }
   151  
   152  /*
   153   * Copy apply arguments into position.
   154   */
   155  static void
   156  jit_apply_builder_add_arguments(jit_apply_builder *builder, jit_type_t signature,
   157  				void **args, unsigned int index, unsigned int num_args)
   158  {
   159  	unsigned int param;
   160  	for(param = 0; param < num_args; ++param)
   161  	{
   162  		void *arg = args[param];
   163  		jit_type_t type = jit_type_get_param(signature, index + param);
   164  		type = jit_type_remove_tags(type);
   165  		switch(type->kind)
   166  		{
   167  		case JIT_TYPE_SBYTE:
   168  			jit_apply_builder_add_sbyte(builder, *((jit_sbyte *) arg));
   169  			break;
   170  
   171  		case JIT_TYPE_UBYTE:
   172  			jit_apply_builder_add_ubyte(builder, *((jit_ubyte *) arg));
   173  			break;
   174  
   175  		case JIT_TYPE_SHORT:
   176  			jit_apply_builder_add_short(builder, *((jit_short *) arg));
   177  			break;
   178  
   179  		case JIT_TYPE_USHORT:
   180  			jit_apply_builder_add_ushort(builder, *((jit_ushort *) arg));
   181  			break;
   182  
   183  		case JIT_TYPE_INT:
   184  			jit_apply_builder_add_int(builder, *((jit_int *) arg));
   185  			break;
   186  
   187  		case JIT_TYPE_UINT:
   188  			jit_apply_builder_add_uint(builder, *((jit_uint *) arg));
   189  			break;
   190  
   191  		case JIT_TYPE_NINT:
   192  		case JIT_TYPE_PTR:
   193  		case JIT_TYPE_SIGNATURE:
   194  			jit_apply_builder_add_nint(builder, *((jit_nint *) arg));
   195  			break;
   196  
   197  		case JIT_TYPE_NUINT:
   198  			jit_apply_builder_add_nuint(builder, *((jit_nuint *) arg));
   199  			break;
   200  
   201  		case JIT_TYPE_LONG:
   202  			jit_apply_builder_add_long(builder, *((jit_long *) arg));
   203  			break;
   204  
   205  		case JIT_TYPE_ULONG:
   206  			jit_apply_builder_add_ulong(builder, *((jit_ulong *) arg));
   207  			break;
   208  
   209  		case JIT_TYPE_FLOAT32:
   210  			jit_apply_builder_add_float32(builder, *((jit_float32 *) arg));
   211  			break;
   212  
   213  		case JIT_TYPE_FLOAT64:
   214  			jit_apply_builder_add_float64(builder, *((jit_float64 *) arg));
   215  			break;
   216  
   217  		case JIT_TYPE_NFLOAT:
   218  			jit_apply_builder_add_nfloat(builder, *((jit_nfloat *) arg));
   219  			break;
   220  
   221  		case JIT_TYPE_STRUCT:
   222  		case JIT_TYPE_UNION:
   223  #ifdef HAVE_JIT_BUILTIN_APPLY_STRUCT
   224  			_jit_builtin_apply_add_struct(builder, arg, type);
   225  #else
   226  			jit_apply_builder_add_struct(builder, arg,
   227  						     jit_type_get_size(type),
   228  						     jit_type_get_alignment(type));
   229  #endif
   230  			break;
   231  		}
   232  	}
   233  }
   234  
   235  /*
   236   * Get the return value after calling a function using "__builtin_apply".
   237   */
   238  static void
   239  jit_apply_builder_get_return(jit_apply_builder *builder, void *rv,
   240  			     jit_type_t type, jit_apply_return *result)
   241  {
   242  #ifndef HAVE_JIT_BUILTIN_APPLY_STRUCT_RETURN
   243  	unsigned int size;
   244  #endif
   245  
   246  	switch(type->kind)
   247  	{
   248  	case JIT_TYPE_SBYTE:
   249  		*((jit_sbyte *) rv) = jit_apply_return_get_sbyte(result);
   250  		break;
   251  
   252  	case JIT_TYPE_UBYTE:
   253  		*((jit_ubyte *) rv) = jit_apply_return_get_ubyte(result);
   254  		break;
   255  
   256  	case JIT_TYPE_SHORT:
   257  		*((jit_short *) rv) = jit_apply_return_get_short(result);
   258  		break;
   259  
   260  	case JIT_TYPE_USHORT:
   261  		*((jit_ushort *) rv) = jit_apply_return_get_ushort(result);
   262  		break;
   263  
   264  	case JIT_TYPE_INT:
   265  		*((jit_int *) rv) = jit_apply_return_get_int(result);
   266  		break;
   267  
   268  	case JIT_TYPE_UINT:
   269  		*((jit_uint *) rv) = jit_apply_return_get_uint(result);
   270  		break;
   271  
   272  	case JIT_TYPE_NINT:
   273  	case JIT_TYPE_PTR:
   274  	case JIT_TYPE_SIGNATURE:
   275  		*((jit_nint *) rv) = jit_apply_return_get_nint(result);
   276  		break;
   277  
   278  	case JIT_TYPE_NUINT:
   279  		*((jit_nuint *) rv) = jit_apply_return_get_nuint(result);
   280  		break;
   281  
   282  	case JIT_TYPE_LONG:
   283  		*((jit_long *) rv) = jit_apply_return_get_long(result);
   284  		break;
   285  
   286  	case JIT_TYPE_ULONG:
   287  		*((jit_ulong *) rv) = jit_apply_return_get_ulong(result);
   288  		break;
   289  
   290  	case JIT_TYPE_FLOAT32:
   291  		*((jit_float32 *) rv) = jit_apply_return_get_float32(result);
   292  		break;
   293  
   294  	case JIT_TYPE_FLOAT64:
   295  		*((jit_float64 *) rv) = jit_apply_return_get_float64(result);
   296  		break;
   297  
   298  	case JIT_TYPE_NFLOAT:
   299  		*((jit_nfloat *) rv) = jit_apply_return_get_nfloat(result);
   300  		break;
   301  
   302  	case JIT_TYPE_STRUCT:
   303  	case JIT_TYPE_UNION:
   304  #ifdef HAVE_JIT_BUILTIN_APPLY_STRUCT_RETURN
   305  		_jit_builtin_apply_get_struct_return(builder, rv, result, type);
   306  #else
   307  		size = jit_type_get_size(type);
   308  		jit_apply_builder_get_struct_return(builder, size, rv, result);
   309  #endif
   310  		break;
   311  	}
   312  }
   313  
   314  /*@
   315   * @deftypefun void jit_apply (jit_type_t signature, void *@var{func}, void **@var{args}, unsigned int @var{num_fixed_args}, void *@var{return_value})
   316   * Call a function that has a particular function signature.
   317   * If the signature has more than @var{num_fixed_args} arguments,
   318   * then it is assumed to be a vararg call, with the additional
   319   * arguments passed in the vararg argument area on the stack.
   320   * The @var{signature} must specify the type of all arguments,
   321   * including those in the vararg argument area.
   322   * @end deftypefun
   323  @*/
   324  void
   325  jit_apply(jit_type_t signature, void *func,
   326  	  void **args, unsigned int num_fixed_args,
   327  	  void *return_value)
   328  {
   329  	jit_apply_builder builder;
   330  	unsigned int size;
   331  	jit_apply_return *apply_return;
   332  	jit_type_t type;
   333  
   334  	/* Initialize the argument builder */
   335  	jit_apply_builder_init(&builder, signature);
   336  
   337  	/* Handle the structure return argument */
   338  	type = jit_type_remove_tags(jit_type_get_return(signature));
   339  	if(jit_type_is_struct(type) || jit_type_is_union(type))
   340  	{
   341  		size = jit_type_get_size(type);
   342  		jit_apply_builder_add_struct_return(&builder, size,
   343  						    return_value);
   344  	}
   345  
   346  	/* Copy the arguments into position */
   347  	jit_apply_builder_add_arguments(&builder, signature, args, 0,
   348  					num_fixed_args);
   349  	jit_apply_builder_start_varargs(&builder);
   350  	jit_apply_builder_add_arguments(&builder, signature,
   351  					args + num_fixed_args, num_fixed_args,
   352  					jit_type_num_params(signature) - num_fixed_args);
   353  
   354  	/* Call the function using "__builtin_apply" or something similar */
   355  	if(type->kind < JIT_TYPE_FLOAT32 || type->kind > JIT_TYPE_NFLOAT)
   356  	{
   357  		jit_builtin_apply(func, builder.apply_args, builder.stack_used,
   358  				  0, apply_return);
   359  	}
   360  	else
   361  	{
   362  		jit_builtin_apply(func, builder.apply_args, builder.stack_used,
   363  				  1, apply_return);
   364  	}
   365  
   366  	/* Copy the return value into position */
   367  	if(return_value != 0 && type != jit_type_void)
   368  	{
   369  		jit_apply_builder_get_return(&builder, return_value, type,
   370  					     apply_return);
   371  	}
   372  }
   373  
   374  /*@
   375   * @deftypefun void jit_apply_raw (jit_type_t @var{signature}, void *@var{func}, void *@var{args}, void *@var{return_value})
   376   * Call a function, passing a set of raw arguments.  This can only
   377   * be used if @code{jit_raw_supported} returns non-zero for the signature.
   378   * The @var{args} value is assumed to be an array of @code{jit_nint} values
   379   * that correspond to each of the arguments.  Raw function calls
   380   * are slightly faster than their non-raw counterparts, but can
   381   * only be used in certain circumstances.
   382   * @end deftypefun
   383  @*/
   384  void
   385  jit_apply_raw(jit_type_t signature, void *func,
   386  	      void *args, void *return_value)
   387  {
   388  	jit_apply_return *apply_return;
   389  	unsigned int size;
   390  	jit_type_t type;
   391  
   392  	/* Call the function using "__builtin_apply" or something similar */
   393  	type = jit_type_remove_tags(jit_type_get_return(signature));
   394  	size = jit_type_num_params(signature) * sizeof(jit_nint);
   395  	if(type->kind < JIT_TYPE_FLOAT32 || type->kind > JIT_TYPE_NFLOAT)
   396  	{
   397  		jit_builtin_apply(func, args, size, 0, apply_return);
   398  	}
   399  	else
   400  	{
   401  		jit_builtin_apply(func, args, size, 1, apply_return);
   402  	}
   403  
   404  	/* Copy the return value into position */
   405  	if(return_value != 0 && type != jit_type_void)
   406  	{
   407  		jit_apply_builder_get_return(0, return_value, type,
   408  					     apply_return);
   409  	}
   410  }
   411  
   412  /*@
   413   * @deftypefun int jit_raw_supported (jit_type_t @var{signature})
   414   * Determine if @code{jit_apply_raw} can be used to call functions
   415   * with a particular signature.  Returns zero if not.
   416   * @end deftypefun
   417  @*/
   418  int jit_raw_supported(jit_type_t signature)
   419  {
   420  #if JIT_APPLY_NUM_WORD_REGS == 0 && JIT_APPLY_NUM_FLOAT_REGS == 0 && \
   421  	JIT_APPLY_STRUCT_RETURN_SPECIAL_REG == 0
   422  
   423  	unsigned int param;
   424  	jit_type_t type;
   425  
   426  #if JIT_APPLY_X86_FASTCALL != 0
   427  	/* Cannot use raw calls with fastcall functions */
   428  	if(jit_type_get_abi(signature) == jit_abi_fastcall)
   429  	{
   430  		return 0;
   431  	}
   432  #endif
   433  
   434  	/* Check that all of the arguments are word-sized */
   435  	param = jit_type_num_params(signature);
   436  	while(param > 0)
   437  	{
   438  		--param;
   439  		type = jit_type_normalize(jit_type_get_param(signature, param));
   440  		if(type->kind < JIT_TYPE_SBYTE || type->kind > JIT_TYPE_NUINT)
   441  		{
   442  			return 0;
   443  		}
   444  	}
   445  
   446  	/* Check that the return value does not involve structures */
   447  	type = jit_type_get_return(signature);
   448  	if(jit_type_is_struct(type) || jit_type_is_union(type))
   449  	{
   450  		return 0;
   451  	}
   452  
   453  	/* The signature is suitable for use with "jit_apply_raw" */
   454  	return 1;
   455  
   456  #else
   457  	/* We cannot use raw calls if we need to use registers in applys */
   458  	return 0;
   459  #endif
   460  }
   461  
   462  /*
   463   * Define the structure of a vararg list for closures.
   464   */
   465  struct jit_closure_va_list
   466  {
   467  	jit_apply_builder builder;
   468  };
   469  
   470  #ifdef jit_closure_size
   471  
   472  /*
   473   * Define the closure structure.
   474   */
   475  typedef struct jit_closure *jit_closure_t;
   476  struct jit_closure
   477  {
   478  	unsigned char 		buf[jit_closure_size];
   479  	jit_type_t    		signature;
   480  	jit_closure_func	func;
   481  	void		       *user_data;
   482  };
   483  
   484  /*
   485   * Handler that is called when a closure is invoked.
   486   */
   487  static void closure_handler(jit_closure_t closure, void *apply_args)
   488  {
   489  	jit_type_t signature = closure->signature;
   490  	jit_type_t type;
   491  	jit_apply_builder parser;
   492  	void *return_buffer;
   493  	void **args;
   494  	void *temp_arg;
   495  	unsigned int num_params;
   496  	unsigned int param;
   497  	jit_apply_return apply_return;
   498  	_jit_apply_return_type return_type;
   499  
   500  	/* Initialize the argument parser */
   501  	jit_apply_parser_init(&parser, closure->signature, apply_args);
   502  
   503  	/* Allocate space for the return value */
   504  	type = jit_type_normalize(jit_type_get_return(signature));
   505  	if(!type || type == jit_type_void)
   506  	{
   507  		return_buffer = 0;
   508  	}
   509  	else if(jit_type_return_via_pointer(type))
   510  	{
   511  		jit_apply_parser_get_struct_return(&parser, return_buffer);
   512  	}
   513  	else
   514  	{
   515  		return_buffer = alloca(jit_type_get_size(type));
   516  	}
   517  
   518  	/* Allocate space for the argument buffer.  We allow for one
   519  	   extra argument to hold the "va" list */
   520  	num_params = jit_type_num_params(signature);
   521  	args = (void **)alloca((num_params + 1) * sizeof(void *));
   522  
   523  	/* Extract the fixed arguments */
   524  	for(param = 0; param < num_params; ++param)
   525  	{
   526  		type = jit_type_normalize(jit_type_get_param(signature, param));
   527  		if(!type)
   528  		{
   529  			args[param] = 0;
   530  			continue;
   531  		}
   532  		temp_arg = alloca(jit_type_get_size(type));
   533  		args[param] = temp_arg;
   534  		switch(type->kind)
   535  		{
   536  			case JIT_TYPE_SBYTE:
   537  			{
   538  				jit_apply_parser_get_sbyte
   539  					(&parser, *((jit_sbyte *)temp_arg));
   540  			}
   541  			break;
   542  
   543  			case JIT_TYPE_UBYTE:
   544  			{
   545  				jit_apply_parser_get_ubyte
   546  					(&parser, *((jit_ubyte *)temp_arg));
   547  			}
   548  			break;
   549  
   550  			case JIT_TYPE_SHORT:
   551  			{
   552  				jit_apply_parser_get_short
   553  					(&parser, *((jit_short *)temp_arg));
   554  			}
   555  			break;
   556  
   557  			case JIT_TYPE_USHORT:
   558  			{
   559  				jit_apply_parser_get_ushort
   560  					(&parser, *((jit_ushort *)temp_arg));
   561  			}
   562  			break;
   563  
   564  			case JIT_TYPE_INT:
   565  			{
   566  				jit_apply_parser_get_int
   567  					(&parser, *((jit_int *)temp_arg));
   568  			}
   569  			break;
   570  
   571  			case JIT_TYPE_UINT:
   572  			{
   573  				jit_apply_parser_get_uint
   574  					(&parser, *((jit_uint *)temp_arg));
   575  			}
   576  			break;
   577  
   578  			case JIT_TYPE_LONG:
   579  			{
   580  				jit_apply_parser_get_long
   581  					(&parser, *((jit_long *)temp_arg));
   582  			}
   583  			break;
   584  
   585  			case JIT_TYPE_ULONG:
   586  			{
   587  				jit_apply_parser_get_ulong
   588  					(&parser, *((jit_ulong *)temp_arg));
   589  			}
   590  			break;
   591  
   592  			case JIT_TYPE_FLOAT32:
   593  			{
   594  				jit_apply_parser_get_float32
   595  					(&parser, *((jit_float32 *)temp_arg));
   596  			}
   597  			break;
   598  
   599  			case JIT_TYPE_FLOAT64:
   600  			{
   601  				jit_apply_parser_get_float64
   602  					(&parser, *((jit_float64 *)temp_arg));
   603  			}
   604  			break;
   605  
   606  			case JIT_TYPE_NFLOAT:
   607  			{
   608  				jit_apply_parser_get_nfloat
   609  					(&parser, *((jit_nfloat *)temp_arg));
   610  			}
   611  			break;
   612  
   613  			case JIT_TYPE_STRUCT:
   614  			case JIT_TYPE_UNION:
   615  			{
   616  #ifdef HAVE_JIT_BUILTIN_APPLY_STRUCT
   617  				_jit_builtin_apply_get_struct(&parser, temp_arg, type);
   618  #else
   619  				jit_apply_parser_get_struct(&parser, jit_type_get_size(type),
   620  							    jit_type_get_alignment(type), temp_arg);
   621  #endif
   622  			}
   623  			break;
   624  		}
   625  	}
   626  
   627  	/* Adjust the argument parser for the start of the va arguments */
   628  	jit_apply_parser_start_varargs(&parser);
   629  
   630  	/* Record the address of the va handler in the last argument slot.
   631  	   Not all functions will need this, but it doesn't hurt to include it */
   632  	args[num_params] = &parser;
   633  
   634  	/* Call the user's closure handling function */
   635  	(*(closure->func))(signature, return_buffer, args, closure->user_data);
   636  
   637  	/* Set up the "apply return" buffer */
   638  	jit_memzero(&apply_return, sizeof(apply_return));
   639  	type = jit_type_normalize(jit_type_get_return(signature));
   640  	return_type = _JIT_APPLY_RETURN_TYPE_OTHER;
   641  	if(type)
   642  	{
   643  		switch(type->kind)
   644  		{
   645  			case JIT_TYPE_SBYTE:
   646  			{
   647  				jit_apply_return_set_sbyte
   648  					(&apply_return, *((jit_sbyte *)return_buffer));
   649  			}
   650  			break;
   651  
   652  			case JIT_TYPE_UBYTE:
   653  			{
   654  				jit_apply_return_set_ubyte
   655  					(&apply_return, *((jit_ubyte *)return_buffer));
   656  			}
   657  			break;
   658  
   659  			case JIT_TYPE_SHORT:
   660  			{
   661  				jit_apply_return_set_short
   662  					(&apply_return, *((jit_short *)return_buffer));
   663  			}
   664  			break;
   665  
   666  			case JIT_TYPE_USHORT:
   667  			{
   668  				jit_apply_return_set_ushort
   669  					(&apply_return, *((jit_ushort *)return_buffer));
   670  			}
   671  			break;
   672  
   673  			case JIT_TYPE_INT:
   674  			{
   675  				jit_apply_return_set_int
   676  					(&apply_return, *((jit_int *)return_buffer));
   677  			}
   678  			break;
   679  
   680  			case JIT_TYPE_UINT:
   681  			{
   682  				jit_apply_return_set_uint
   683  					(&apply_return, *((jit_uint *)return_buffer));
   684  			}
   685  			break;
   686  
   687  			case JIT_TYPE_LONG:
   688  			{
   689  				jit_apply_return_set_long
   690  					(&apply_return, *((jit_long *)return_buffer));
   691  			}
   692  			break;
   693  
   694  			case JIT_TYPE_ULONG:
   695  			{
   696  				jit_apply_return_set_ulong
   697  					(&apply_return, *((jit_ulong *)return_buffer));
   698  			}
   699  			break;
   700  
   701  			case JIT_TYPE_FLOAT32:
   702  			{
   703  				jit_apply_return_set_float32
   704  					(&apply_return, *((jit_float32 *)return_buffer));
   705  				return_type = _JIT_APPLY_RETURN_TYPE_FLOAT32;
   706  			}
   707  			break;
   708  
   709  			case JIT_TYPE_FLOAT64:
   710  			{
   711  				jit_apply_return_set_float64
   712  					(&apply_return, *((jit_float64 *)return_buffer));
   713  				return_type = _JIT_APPLY_RETURN_TYPE_FLOAT64;
   714  			}
   715  			break;
   716  
   717  			case JIT_TYPE_NFLOAT:
   718  			{
   719  				jit_apply_return_set_nfloat
   720  					(&apply_return, *((jit_nfloat *)return_buffer));
   721  				return_type = _JIT_APPLY_RETURN_TYPE_NFLOAT;
   722  			}
   723  			break;
   724  
   725  			case JIT_TYPE_STRUCT:
   726  			case JIT_TYPE_UNION:
   727  			{
   728  				if(!jit_type_return_via_pointer(type))
   729  				{
   730  					jit_memcpy(&apply_return, return_buffer,
   731  							   jit_type_get_size(type));
   732  				}
   733  			}
   734  			break;
   735  		}
   736  	}
   737  
   738  	/* Return the result to the caller */
   739  	switch(return_type)
   740  	{
   741  		case _JIT_APPLY_RETURN_TYPE_FLOAT32:
   742  		{
   743  			jit_builtin_return_float(&apply_return);
   744  		}
   745  		break;
   746  
   747  		case _JIT_APPLY_RETURN_TYPE_FLOAT64:
   748  		{
   749  			jit_builtin_return_double(&apply_return);
   750  		}
   751  		break;
   752  
   753  		case _JIT_APPLY_RETURN_TYPE_NFLOAT:
   754  		{
   755  			jit_builtin_return_nfloat(&apply_return);
   756  		}
   757  		break;
   758  
   759  		default:
   760  		{
   761  			jit_builtin_return_int(&apply_return);
   762  		}
   763  	}
   764  }
   765  
   766  #endif /* jit_closure_size */
   767  
   768  /*@
   769   * @deftypefun {void *} jit_closure_create (jit_context_t @var{context}, jit_type_t @var{signature}, jit_closure_func @var{func}, void *@var{user_data})
   770   * Create a closure from a function signature, a closure handling function,
   771   * and a user data value.  Returns NULL if out of memory, or if closures are
   772   * not supported.  The @var{func} argument should have the following
   773   * prototype:
   774   *
   775   * @example
   776   * void func(jit_type_t signature, void *result, void **args, void *user_data);
   777   * @end example
   778   *
   779   * If the closure signature includes variable arguments, then @code{args}
   780   * will contain pointers to the fixed arguments, followed by a
   781   * @code{jit_closure_va_list_t} value for accessing the remainder of
   782   * the arguments.
   783   *
   784   * The memory for the closure will be reclaimed when the @var{context}
   785   * is destroyed.
   786   * @end deftypefun
   787  @*/
   788  void *
   789  jit_closure_create(jit_context_t context, jit_type_t signature, jit_closure_func func, void *user_data)
   790  {
   791  #ifdef jit_closure_size
   792  	jit_closure_t closure;
   793  
   794  	/* Validate the parameters */
   795  	if(!context || !signature || !func)
   796  	{
   797  		return 0;
   798  	}
   799  
   800  	/* Acquire the memory context */
   801  	_jit_memory_lock(context);
   802  	if(!_jit_memory_ensure(context))
   803  	{
   804  		_jit_memory_unlock(context);
   805  		return 0;
   806  	}
   807  
   808  	/* Allocate memory space for the closure */
   809  	closure = (jit_closure_t) _jit_memory_alloc_closure(context);
   810  	if(!closure)
   811  	{
   812  		_jit_memory_unlock(context);
   813  		return 0;
   814  	}
   815  
   816  	/* Fill in the closure fields */
   817  	_jit_create_closure(closure->buf, (void *)closure_handler, closure, signature);
   818  	closure->signature = signature;
   819  	closure->func = func;
   820  	closure->user_data = user_data;
   821  
   822  	/* Release the memory context, as we are finished with it */
   823  	_jit_memory_unlock(context);
   824  
   825  	/* Perform a cache flush on the closure's code */
   826  	_jit_flush_exec(closure->buf, sizeof(closure->buf));
   827  
   828  	/* Return the completed closure to the caller */
   829  	return closure;
   830  
   831  #else
   832  	/* Closures are not supported on this platform */
   833  	return 0;
   834  #endif
   835  }
   836  
   837  /*@
   838   * @deftypefun int jit_supports_closures (void)
   839   * Determine if this platform has support for closures.
   840   * @end deftypefun
   841  @*/
   842  int
   843  jit_supports_closures(void)
   844  {
   845  #ifdef jit_closure_size
   846  	return 1;
   847  #else
   848  	return 0;
   849  #endif
   850  }
   851  
   852  unsigned int
   853  jit_get_closure_size(void)
   854  {
   855  #ifdef jit_closure_size
   856  	return jit_closure_size;
   857  #else
   858  	return 0;
   859  #endif
   860  }
   861  
   862  unsigned int
   863  jit_get_closure_alignment(void)
   864  {
   865  #ifdef jit_closure_size
   866  	return jit_closure_align;
   867  #else
   868  	return 0;
   869  #endif
   870  }
   871  
   872  unsigned int
   873  jit_get_trampoline_size(void)
   874  {
   875  	int size = 0;
   876  #if defined(jit_redirector_size)
   877  	size += jit_redirector_size;
   878  #endif
   879  #if defined(jit_indirector_size)
   880  	size += jit_indirector_size;
   881  #endif
   882  	return size;
   883  }
   884  
   885  unsigned int
   886  jit_get_trampoline_alignment(void)
   887  {
   888  #if defined(jit_redirector_size) || defined(jit_indirector_size)
   889  	return 1;
   890  #else
   891  	return 0;
   892  #endif
   893  }
   894  
   895  /*@
   896   * @deftypefun jit_nint jit_closure_va_get_nint (jit_closure_va_list_t @var{va})
   897   * @deftypefunx jit_nuint jit_closure_va_get_nuint (jit_closure_va_list_t @var{va})
   898   * @deftypefunx jit_long jit_closure_va_get_long (jit_closure_va_list_t @var{va})
   899   * @deftypefunx jit_ulong jit_closure_va_get_ulong (jit_closure_va_list_t @var{va})
   900   * @deftypefunx jit_float32 jit_closure_va_get_float32 (jit_closure_va_list_t @var{va})
   901   * @deftypefunx jit_float64 jit_closure_va_get_float64 (jit_closure_va_list_t @var{va})
   902   * @deftypefunx jit_nfloat jit_closure_va_get_nfloat (jit_closure_va_list_t @var{va})
   903   * @deftypefunx {void *} jit_closure_va_get_ptr (jit_closure_va_list_t @var{va})
   904   * Get the next value of a specific type from a closure's variable arguments.
   905   * @end deftypefun
   906  @*/
   907  jit_nint jit_closure_va_get_nint(jit_closure_va_list_t va)
   908  {
   909  	jit_nint value;
   910  	jit_apply_parser_get_nint(&(va->builder), value);
   911  	return value;
   912  }
   913  
   914  jit_nuint jit_closure_va_get_nuint(jit_closure_va_list_t va)
   915  {
   916  	jit_nuint value;
   917  	jit_apply_parser_get_nuint(&(va->builder), value);
   918  	return value;
   919  }
   920  
   921  jit_long jit_closure_va_get_long(jit_closure_va_list_t va)
   922  {
   923  	jit_long value;
   924  	jit_apply_parser_get_long(&(va->builder), value);
   925  	return value;
   926  }
   927  
   928  jit_ulong jit_closure_va_get_ulong(jit_closure_va_list_t va)
   929  {
   930  	jit_ulong value;
   931  	jit_apply_parser_get_ulong(&(va->builder), value);
   932  	return value;
   933  }
   934  
   935  jit_float32 jit_closure_va_get_float32(jit_closure_va_list_t va)
   936  {
   937  	jit_float32 value;
   938  	jit_apply_parser_get_float32(&(va->builder), value);
   939  	return value;
   940  }
   941  
   942  jit_float64 jit_closure_va_get_float64(jit_closure_va_list_t va)
   943  {
   944  	jit_float64 value;
   945  	jit_apply_parser_get_float64(&(va->builder), value);
   946  	return value;
   947  }
   948  
   949  jit_nfloat jit_closure_va_get_nfloat(jit_closure_va_list_t va)
   950  {
   951  	jit_nfloat value;
   952  	jit_apply_parser_get_nfloat(&(va->builder), value);
   953  	return value;
   954  }
   955  
   956  void *jit_closure_va_get_ptr(jit_closure_va_list_t va)
   957  {
   958  	jit_nint value;
   959  	jit_apply_parser_get_nint(&(va->builder), value);
   960  	return (void *)value;
   961  }
   962  
   963  /*@
   964   * @deftypefun void jit_closure_va_get_struct (jit_closure_va_list_t @var{va}, void *@var{buf}, jit_type_t @var{type})
   965   * Get a structure or union value of a specific @var{type} from a closure's
   966   * variable arguments, and copy it into @var{buf}.
   967   * @end deftypefun
   968  @*/
   969  void
   970  jit_closure_va_get_struct(jit_closure_va_list_t va, void *buf, jit_type_t type)
   971  {
   972  #ifdef HAVE_JIT_BUILTIN_APPLY_STRUCT
   973  	_jit_builtin_apply_get_struct(&(va->builder), buf, type);
   974  #else
   975  	jit_apply_parser_get_struct
   976  		(&(va->builder), jit_type_get_size(type),
   977  		 jit_type_get_alignment(type), buf);
   978  #endif
   979  }