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

     1  /*
     2   * jit-compile.c - Function compilation.
     3   *
     4   * Copyright (C) 2004, 2006-2008  Southern Storm Software, Pty Ltd.
     5   * Copyright (C) 2012  Aleksey Demakov
     6   *
     7   * This file is part of the libjit library.
     8   *
     9   * The libjit library is free software: you can redistribute it and/or
    10   * modify it under the terms of the GNU Lesser General Public License
    11   * as published by the Free Software Foundation, either version 2.1 of
    12   * the License, or (at your option) any later version.
    13   *
    14   * The libjit library is distributed in the hope that it will be useful,
    15   * but WITHOUT ANY WARRANTY; without even the implied warranty of
    16   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    17   * Lesser General Public License for more details.
    18   *
    19   * You should have received a copy of the GNU Lesser General Public
    20   * License along with the libjit library.  If not, see
    21   * <http://www.gnu.org/licenses/>.
    22   */
    23  
    24  #include "jit-internal.h"
    25  #include "jit-rules.h"
    26  #include "jit-reg-alloc.h"
    27  #include "jit-setjmp.h"
    28  #ifdef _JIT_COMPILE_DEBUG
    29  # include <jit/jit-dump.h>
    30  # include <stdio.h>
    31  #endif
    32  
    33  /*
    34   * Misc data needed for compilation
    35   */
    36  typedef struct
    37  {
    38  	jit_function_t		func;
    39  
    40  	int			memory_locked;
    41  	int 			memory_started;
    42  
    43  	int			restart;
    44  	int			page_factor;
    45  
    46  	struct jit_gencode	gen;
    47  
    48  } _jit_compile_t;
    49  
    50  #define _JIT_RESULT_TO_OBJECT(x)	((void *) ((jit_nint) (x) - JIT_RESULT_OK))
    51  #define _JIT_RESULT_FROM_OBJECT(x)	((jit_nint) ((void *) (x)) + JIT_RESULT_OK)
    52  
    53  /*
    54   * This exception handler overrides a user-defined handler during compilation.
    55   */
    56  static void *
    57  internal_exception_handler(int exception_type)
    58  {
    59  	return _JIT_RESULT_TO_OBJECT(exception_type);
    60  }
    61  
    62  /*
    63   * Optimize a function.
    64   */
    65  static void
    66  optimize(jit_function_t func)
    67  {
    68  	if(func->is_optimized || func->optimization_level == JIT_OPTLEVEL_NONE)
    69  	{
    70  		/* The function is already optimized or does not need optimization */
    71  		return;
    72  	}
    73  
    74  	/* Build control flow graph */
    75  	_jit_block_build_cfg(func);
    76  
    77  	/* Eliminate useless control flow */
    78  	_jit_block_clean_cfg(func);
    79  
    80  	/* Optimization is done */
    81  	func->is_optimized = 1;
    82  }
    83  
    84  /*@
    85   * @deftypefun int jit_optimize (jit_function_t @var{func})
    86   * Optimize a function by analyzing and transforming its intermediate
    87   * representation. If the function was already compiled or optimized,
    88   * then do nothing.
    89   *
    90   * Returns @code{JIT_RESUlT_OK} on success, otherwise it might return
    91   * @code{JIT_RESULT_OUT_OF_MEMORY}, @code{JIT_RESULT_COMPILE_ERROR} or
    92   * possibly some other more specific @code{JIT_RESULT_} code.
    93   *
    94   * Normally this function should not be used because @code{jit_compile}
    95   * performs all the optimization anyway.  However it might be useful for
    96   * debugging to verify the effect of the @code{libjit} code optimization.
    97   * This might be done, for instance, by calling @code{jit_dump_function}
    98   * before and after @code{jit_optimize}.
    99   * @end deftypefun
   100  @*/
   101  int
   102  jit_optimize(jit_function_t func)
   103  {
   104  	jit_jmp_buf jbuf;
   105  	jit_exception_func handler;
   106  
   107  	/* Bail out on invalid parameter */
   108  	if(!func)
   109  	{
   110  		return JIT_RESULT_NULL_FUNCTION;
   111  	}
   112  
   113  	/* Bail out if there is nothing to do here */
   114  	if(!func->builder)
   115  	{
   116  		if(func->is_compiled)
   117  		{
   118  			/* The function is already compiled and we can't optimize it */
   119  			return JIT_RESULT_OK;
   120  		}
   121  		else
   122  		{
   123  			/* We don't have anything to optimize at all */
   124  			return JIT_RESULT_NULL_FUNCTION;
   125  		}
   126  	}
   127  
   128  	/* Override user's exception handler */
   129  	handler = jit_exception_set_handler(internal_exception_handler);
   130  
   131  	/* Establish a "setjmp" point here so that we can unwind the
   132  	   stack to this point when an exception occurs and then prevent
   133  	   the exception from propagating further up the stack */
   134  	_jit_unwind_push_setjmp(&jbuf);
   135  	if(setjmp(jbuf.buf))
   136  	{
   137  		_jit_unwind_pop_setjmp();
   138  		jit_exception_set_handler(handler);
   139  		return _JIT_RESULT_FROM_OBJECT(jit_exception_get_last_and_clear());
   140  	}
   141  
   142  	/* Perform the optimizations */
   143  	optimize(func);
   144  
   145  	/* Restore the "setjmp" contexts and exit */
   146  	_jit_unwind_pop_setjmp();
   147  	jit_exception_set_handler(handler);
   148  	return JIT_RESULT_OK;
   149  }
   150  
   151  /*
   152   * Mark the current position with a bytecode offset value.
   153   */
   154  void
   155  mark_offset(jit_gencode_t gen, jit_function_t func, unsigned long offset)
   156  {
   157  	unsigned long native_offset = gen->ptr - gen->mem_start;
   158  	if(!_jit_varint_encode_uint(&gen->offset_encoder, (jit_uint) offset))
   159  	{
   160  		jit_exception_builtin(JIT_RESULT_OUT_OF_MEMORY);
   161  	}
   162  	if(!_jit_varint_encode_uint(&gen->offset_encoder, (jit_uint) native_offset))
   163  	{
   164  		jit_exception_builtin(JIT_RESULT_OUT_OF_MEMORY);
   165  	}
   166  }
   167  
   168  /*
   169   * Compile a single basic block within a function.
   170   */
   171  static void
   172  compile_block(jit_gencode_t gen, jit_function_t func, jit_block_t block)
   173  {
   174  	jit_insn_iter_t iter;
   175  	jit_insn_t insn;
   176  
   177  #ifdef _JIT_COMPILE_DEBUG
   178  	printf("Block #%d: %d\n\n", func->builder->block_count++, block->label);
   179  #endif
   180  
   181  	/* Iterate over all blocks in the function */
   182  	jit_insn_iter_init(&iter, block);
   183  	while((insn = jit_insn_iter_next(&iter)) != 0)
   184  	{
   185  #ifdef _JIT_COMPILE_DEBUG
   186  		unsigned char *p1, *p2;
   187  		p1 = gen->ptr;
   188  		printf("Insn #%d: ", func->builder->insn_count++);
   189  		jit_dump_insn(stdout, func, insn);
   190  		printf("\nStart of binary code: 0x%08x\n", p1);
   191  #endif
   192  
   193  		switch(insn->opcode)
   194  		{
   195  		case JIT_OP_NOP:
   196  			/* Ignore NOP's */
   197  			break;
   198  
   199  		case JIT_OP_CHECK_NULL:
   200  			/* Determine if we can optimize the null check away */
   201  			if(!_jit_insn_check_is_redundant(&iter))
   202  			{
   203  				_jit_gen_insn(gen, func, block, insn);
   204  			}
   205  			break;
   206  
   207  #ifndef JIT_BACKEND_INTERP
   208  		case JIT_OP_CALL:
   209  		case JIT_OP_CALL_TAIL:
   210  		case JIT_OP_CALL_INDIRECT:
   211  		case JIT_OP_CALL_INDIRECT_TAIL:
   212  		case JIT_OP_CALL_VTABLE_PTR:
   213  		case JIT_OP_CALL_VTABLE_PTR_TAIL:
   214  		case JIT_OP_CALL_EXTERNAL:
   215  		case JIT_OP_CALL_EXTERNAL_TAIL:
   216  			/* Spill all caller-saved registers before a call */
   217  			_jit_regs_spill_all(gen);
   218  			/* Generate code for the instruction with the back end */
   219  			_jit_gen_insn(gen, func, block, insn);
   220  			/* Free outgoing registers if any */
   221  			_jit_regs_clear_all_outgoing(gen);
   222  			break;
   223  #endif
   224  
   225  #ifndef JIT_BACKEND_INTERP
   226  		case JIT_OP_IMPORT:
   227  			/* Make sure the import target has a frame_offset */
   228  			_jit_gen_fix_value(insn->value2);
   229  
   230  			/* change the current instruction to an instruction calculating the
   231  			   address of the import target */
   232  			insn->opcode = JIT_OP_ADD_RELATIVE;
   233  			insn->value2 = jit_value_create_nint_constant(func, jit_type_nint,
   234  				insn->value2->frame_offset);
   235  
   236  			/* generate the instruction */
   237  			_jit_gen_insn(gen, func, block, insn);
   238  			break;
   239  #endif
   240  
   241  #ifndef JIT_BACKEND_INTERP
   242  		case JIT_OP_INCOMING_REG:
   243  			/* Assign a register to an incoming value */
   244  			_jit_regs_set_incoming(gen,
   245  					       (int)jit_value_get_nint_constant(insn->value2),
   246  					       insn->value1);
   247  			/* Generate code for the instruction with the back end */
   248  			_jit_gen_insn(gen, func, block, insn);
   249  			break;
   250  #endif
   251  
   252  		case JIT_OP_INCOMING_FRAME_POSN:
   253  			/* Set the frame position for an incoming value */
   254  			insn->value1->frame_offset = jit_value_get_nint_constant(insn->value2);
   255  			insn->value1->in_register = 0;
   256  			insn->value1->has_frame_offset = 1;
   257  			if(insn->value1->has_global_register)
   258  			{
   259  				insn->value1->in_global_register = 1;
   260  				_jit_gen_load_global(gen, insn->value1->global_reg, insn->value1);
   261  			}
   262  			else
   263  			{
   264  				insn->value1->in_frame = 1;
   265  			}
   266  			break;
   267  
   268  #ifndef JIT_BACKEND_INTERP
   269  		case JIT_OP_OUTGOING_REG:
   270  			/* Copy a value into an outgoing register */
   271  			_jit_regs_set_outgoing(gen,
   272  					       (int)jit_value_get_nint_constant(insn->value2),
   273  					       insn->value1);
   274  			break;
   275  #endif
   276  
   277  #ifndef JIT_BACKEND_INTERP
   278  		case JIT_OP_RETURN_REG:
   279  			/* Assign a register to a return value */
   280  			_jit_regs_set_incoming(gen,
   281  					       (int)jit_value_get_nint_constant(insn->value2),
   282  					       insn->value1);
   283  			/* Generate code for the instruction with the back end */
   284  			_jit_gen_insn(gen, func, block, insn);
   285  			break;
   286  #endif
   287  
   288  		case JIT_OP_MARK_OFFSET:
   289  			/* Mark the current code position as corresponding
   290  			   to a particular bytecode offset */
   291  			mark_offset(gen, func, (unsigned long)(long)jit_value_get_nint_constant(insn->value1));
   292  			break;
   293  
   294  		default:
   295  			/* Generate code for the instruction with the back end */
   296  			_jit_gen_insn(gen, func, block, insn);
   297  			break;
   298  		}
   299  
   300  #ifdef _JIT_COMPILE_DEBUG
   301  		p2 = gen->ptr;
   302  		printf("Length of binary code: %d\n\n", p2 - p1);
   303  		fflush(stdout);
   304  #endif
   305  	}
   306  }
   307  
   308  /*
   309   * Reset value on codegen restart.
   310   */
   311  static void
   312  reset_value(jit_value_t value)
   313  {
   314  	value->reg = -1;
   315  	value->in_register = 0;
   316  	value->in_global_register = value->has_global_register;
   317  	value->in_frame = 0;
   318  }
   319  
   320  /*
   321   * Clean up the compilation state on codegen restart.
   322   */
   323  static void
   324  cleanup_on_restart(jit_gencode_t gen, jit_function_t func)
   325  {
   326  	jit_block_t block;
   327  	jit_insn_iter_t iter;
   328  	jit_insn_t insn;
   329  
   330  	block = 0;
   331  	while((block = jit_block_next(func, block)) != 0)
   332  	{
   333  		/* Clear the block addresses and fixup lists */
   334  		block->address = 0;
   335  		block->fixup_list = 0;
   336  		block->fixup_absolute_list = 0;
   337  
   338  		/* Reset values referred to by block instructions */
   339  		jit_insn_iter_init(&iter, block);
   340  		while((insn = jit_insn_iter_next(&iter)) != 0)
   341  		{
   342  			if(insn->dest && (insn->flags & JIT_INSN_DEST_OTHER_FLAGS) == 0)
   343  			{
   344  				reset_value(insn->dest);
   345  			}
   346  			if(insn->value1 && (insn->flags & JIT_INSN_VALUE1_OTHER_FLAGS) == 0)
   347  			{
   348  				reset_value(insn->value1);
   349  			}
   350  			if(insn->value2 && (insn->flags & JIT_INSN_VALUE2_OTHER_FLAGS) == 0)
   351  			{
   352  				reset_value(insn->value2);
   353  			}
   354  		}
   355  	}
   356  
   357  	/* Reset values referred to by builder */
   358  	if(func->builder->setjmp_value)
   359  	{
   360  		reset_value(func->builder->setjmp_value);
   361  	}
   362  	if(func->builder->parent_frame)
   363  	{
   364  		reset_value(func->builder->parent_frame);
   365  	}
   366  
   367  	/* Reset the "touched" registers mask. The first time compilation
   368  	   might have followed wrong code paths and thus allocated wrong
   369  	   registers. */
   370  	if(func->builder->has_tail_call)
   371  	{
   372  		/* For functions with tail calls _jit_regs_alloc_global()
   373  		   does not allocate any global registers. The "permanent"
   374  		   mask has all global registers set to prevent their use. */
   375  		gen->touched = jit_regused_init;
   376  	}
   377  	else
   378  	{
   379  		gen->touched = gen->permanent;
   380  	}
   381  
   382  	/* Reset the epilog fixup list */
   383  	gen->epilog_fixup = 0;
   384  }
   385  
   386  /*
   387   * Acquire the memory context.
   388   */
   389  static void
   390  memory_acquire(_jit_compile_t *state)
   391  {
   392  	/* Store the function's context as codegen context */
   393  	state->gen.context = state->func->context;
   394  
   395  	/* Acquire the memory context lock */
   396  	_jit_memory_lock(state->gen.context);
   397  
   398  	/* Remember that the lock is acquired */
   399  	state->memory_locked = 1;
   400  
   401  	if(!_jit_memory_ensure(state->gen.context))
   402  	{
   403  		jit_exception_builtin(JIT_RESULT_OUT_OF_MEMORY);
   404  	}
   405  }
   406  
   407  /*
   408   * Release the memory context.
   409   */
   410  static void
   411  memory_release(_jit_compile_t *state)
   412  {
   413  	/* Release the lock if it was previously acquired */
   414  	if(state->memory_locked)
   415  	{
   416  		_jit_memory_unlock(state->gen.context);
   417  		state->memory_locked = 0;
   418  	}
   419  }
   420  
   421  /*
   422   * Align the method code on a particular boundary if the
   423   * difference between the current position and the aligned
   424   * boundary is less than "diff".  The "nop" value is used
   425   * to pad unused bytes.
   426   */
   427  static void
   428  memory_align(_jit_compile_t *state, int align, int diff, int nop)
   429  {
   430  	jit_nuint p, n;
   431  
   432  	/* Adjust the required alignment */
   433  	if(align < 1)
   434  	{
   435  		align = 1;
   436  	}
   437  
   438  	/* Determine the location of the next alignment boundary */
   439  	p = (jit_nuint) state->gen.ptr;
   440  	n = (p + (jit_nuint) align - 1) & ~((jit_nuint) align - 1);
   441  	if(p == n || (p - n) >= (jit_nuint) diff)
   442  	{
   443  		return;
   444  	}
   445  
   446  	/* Determine the actual alignment */
   447  	align = (int) (n - p);
   448  
   449  	/* Detect overflow of the free memory region */
   450  	_jit_gen_check_space(&state->gen, align);
   451  
   452  #ifdef jit_should_pad
   453  	/* Use CPU-specific padding, because it may be more efficient */
   454  	_jit_pad_buffer(state->gen.ptr, align);
   455  #else
   456  	jit_memset(state->gen.ptr, nop, align);
   457  	state->gen.ptr += align;
   458  #endif
   459  }
   460  
   461  /*
   462   * Prepare to start code generation with just allocated code space.
   463   */
   464  static void
   465  memory_start(_jit_compile_t *state)
   466  {
   467  	/* Remember the memory context state */
   468  	state->memory_started = 1;
   469  
   470  	/* Store the bounds of the available space */
   471  	state->gen.mem_start = _jit_memory_get_break(state->gen.context);
   472  	state->gen.mem_limit = _jit_memory_get_limit(state->gen.context);
   473  
   474  	/* Align the function code start as required */
   475  	state->gen.ptr = state->gen.mem_start;
   476  	memory_align(state, JIT_FUNCTION_ALIGNMENT, JIT_FUNCTION_ALIGNMENT, 0);
   477  
   478  	/* Prepare the bytecode offset encoder */
   479  	_jit_varint_init_encoder(&state->gen.offset_encoder);
   480  }
   481  
   482  /*
   483   * Allocate some amount of code space.
   484   */
   485  static void
   486  memory_alloc(_jit_compile_t *state)
   487  {
   488  	int result;
   489  
   490  	/* Try to allocate within the current memory limit */
   491  	result = _jit_memory_start_function(state->gen.context, state->func);
   492  	if(result == JIT_MEMORY_RESTART)
   493  	{
   494  		/* Not enough space. Request to extend the limit and retry */
   495  		_jit_memory_extend_limit(state->gen.context, state->page_factor++);
   496  		result = _jit_memory_start_function(state->gen.context, state->func);
   497  	}
   498  	if(result != JIT_MEMORY_OK)
   499  	{
   500  		/* Failed to allocate any space */
   501  		jit_exception_builtin(JIT_RESULT_OUT_OF_MEMORY);
   502  	}
   503  
   504  	/* Start with with allocated space */
   505  	memory_start(state);
   506  }
   507  
   508  /*
   509   * Finish code generation.
   510   */
   511  static void
   512  memory_flush(_jit_compile_t *state)
   513  {
   514  	int result;
   515  
   516  	if(state->memory_started)
   517  	{
   518  		/* Reset the memory state */
   519  		state->memory_started = 0;
   520  
   521  		/* Let the memory context know the address we ended at */
   522  		_jit_memory_set_break(state->gen.context, state->gen.code_end);
   523  
   524  		/* Finally end the function */
   525  		result = _jit_memory_end_function(state->gen.context, JIT_MEMORY_OK);
   526  		if(result != JIT_MEMORY_OK)
   527  		{
   528  			if(result == JIT_MEMORY_RESTART)
   529  			{
   530  				/* Throw an internal exception that causes
   531  				   a larger code space to be allocated and
   532  				   the code generation to restart */
   533  				jit_exception_builtin(JIT_RESULT_MEMORY_FULL);
   534  			}
   535  			else
   536  			{
   537  				/* Throw exception that indicates failure
   538  				   to allocate enough code space */
   539  				jit_exception_builtin(JIT_RESULT_OUT_OF_MEMORY);
   540  			}
   541  		}
   542  
   543  #ifndef JIT_BACKEND_INTERP
   544  		/* On success perform a CPU cache flush, to make the code executable */
   545  		_jit_flush_exec(state->gen.code_start,
   546  			        state->gen.code_end - state->gen.code_start);
   547  #endif
   548  
   549  		/* Terminate the debug information and flush it */
   550  		if(!_jit_varint_encode_end(&state->gen.offset_encoder))
   551  		{
   552  			jit_exception_builtin(JIT_RESULT_OUT_OF_MEMORY);
   553  		}
   554  		state->func->bytecode_offset = _jit_varint_get_data(&state->gen.offset_encoder);
   555  	}
   556  }
   557  
   558  /*
   559   * Give back the allocated space in case of failure to generate the code.
   560   */
   561  static void
   562  memory_abort(_jit_compile_t *state)
   563  {
   564  	if(state->memory_started)
   565  	{
   566  		state->memory_started = 0;
   567  
   568  		/* Release the code space */
   569  		_jit_memory_end_function(state->gen.context, JIT_MEMORY_RESTART);
   570  
   571  		/* Free encoded bytecode offset data */
   572  		_jit_varint_free_data(_jit_varint_get_data(&state->gen.offset_encoder));
   573  	}
   574  }
   575  
   576  /*
   577   * Allocate more code space.
   578   */
   579  static void
   580  memory_realloc(_jit_compile_t *state)
   581  {
   582  	int result;
   583  
   584  	/* Release the previously allocated code space */
   585  	memory_abort(state);
   586  
   587  	/* Request to extend memory limit and retry space allocation */
   588  	_jit_memory_extend_limit(state->gen.context, state->page_factor++);
   589  	result = _jit_memory_start_function(state->gen.context, state->func);
   590  	if(result != JIT_MEMORY_OK)
   591  	{
   592  		/* Failed to allocate enough space */
   593  		jit_exception_builtin(JIT_RESULT_OUT_OF_MEMORY);
   594  	}
   595  
   596  	/* Start with with allocated space */
   597  	memory_start(state);
   598  }
   599  
   600  /*
   601   * Prepare function info needed for code generation.
   602   */
   603  static void
   604  codegen_prepare(_jit_compile_t *state)
   605  {
   606  	/* Intuit "nothrow" and "noreturn" flags for this function */
   607  	if(!state->func->builder->may_throw)
   608  	{
   609  		state->func->no_throw = 1;
   610  	}
   611  	if(!state->func->builder->ordinary_return)
   612  	{
   613  		state->func->no_return = 1;
   614  	}
   615  
   616  	/* Compute liveness and "next use" information for this function */
   617  	_jit_function_compute_liveness(state->func);
   618  
   619  	/* Allocate global registers to variables within the function */
   620  #ifndef JIT_BACKEND_INTERP
   621  	_jit_regs_alloc_global(&state->gen, state->func);
   622  #endif
   623  }
   624  
   625  /*
   626   * Run codegen.
   627   */
   628  static void
   629  codegen(_jit_compile_t *state)
   630  {
   631  	jit_function_t func = state->func;
   632  	struct jit_gencode *gen = &state->gen;
   633  	jit_block_t block;
   634  
   635  	/* Remember the start code address (due to alignment it may differ from
   636  	   the available space start - gen->start) */
   637  	gen->code_start = gen->ptr;
   638  
   639  #ifdef JIT_PROLOG_SIZE
   640  	/* Output space for the function prolog */
   641  	_jit_gen_check_space(gen, JIT_PROLOG_SIZE);
   642  	gen->ptr += JIT_PROLOG_SIZE;
   643  #endif
   644  
   645  	/* Generate code for the blocks in the function */
   646  	block = 0;
   647  	while((block = jit_block_next(func, block)) != 0)
   648  	{
   649  		/* Notify the back end that the block is starting */
   650  		_jit_gen_start_block(gen, block);
   651  
   652  #ifndef JIT_BACKEND_INTERP
   653  		/* Clear the local register assignments */
   654  		_jit_regs_init_for_block(gen);
   655  #endif
   656  
   657  		/* Generate the block's code */
   658  		compile_block(gen, func, block);
   659  
   660  #ifndef JIT_BACKEND_INTERP
   661  		/* Spill all live register values back to their frame positions */
   662  		_jit_regs_spill_all(gen);
   663  #endif
   664  
   665  		/* Notify the back end that the block is finished */
   666  		_jit_gen_end_block(gen, block);
   667  	}
   668  
   669  	/* Output the function epilog.  All return paths will jump to here */
   670  	_jit_gen_epilog(gen, func);
   671  
   672  	/* Remember the end code address */
   673  	gen->code_end = gen->ptr;
   674  
   675  #ifdef JIT_PROLOG_SIZE
   676  	/* Back-patch the function prolog and get the real entry point */
   677  	gen->code_start = _jit_gen_prolog(gen, func, gen->code_start);
   678  #endif
   679  
   680  #if !defined(JIT_BACKEND_INTERP) && (!defined(jit_redirector_size) || !defined(jit_indirector_size))
   681  	/* If the function is recompilable, then we need an extra entry
   682  	   point to properly redirect previous references to the function */
   683  	if(func->is_recompilable && !func->indirector)
   684  	{
   685  		/* TODO: use _jit_create_indirector() instead of
   686  		   _jit_gen_redirector() as both do the same. */
   687  		func->indirector = _jit_gen_redirector(&gen, func);
   688  	}
   689  #endif
   690  }
   691  
   692  /*
   693   * Compile a function and return its entry point.
   694   */
   695  static int
   696  compile(_jit_compile_t *state, jit_function_t func)
   697  {
   698  	jit_exception_func handler;
   699  	jit_jmp_buf jbuf;
   700  	int result;
   701  
   702  	/* Initialize compilation state */
   703  	jit_memzero(state, sizeof(_jit_compile_t));
   704  	state->func = func;
   705  
   706  	/* Replace user's exception handler with internal handler */
   707  	handler = jit_exception_set_handler(internal_exception_handler);
   708  
   709  	/* Establish a "setjmp" point here so that we can unwind the
   710  	   stack to this point when an exception occurs and then prevent
   711  	   the exception from propagating further up the stack */
   712  	_jit_unwind_push_setjmp(&jbuf);
   713  
   714   restart:
   715  	/* Handle compilation exceptions */
   716  	if(setjmp(jbuf.buf))
   717  	{
   718  		result = _JIT_RESULT_FROM_OBJECT(jit_exception_get_last_and_clear());
   719  		if(result == JIT_RESULT_MEMORY_FULL)
   720  		{
   721  			/* Restart code generation after the memory full condition */
   722  			state->restart = 1;
   723  			goto restart;
   724  		}
   725  
   726  		/* Release allocated code space and exit */
   727  		memory_abort(state);
   728  		goto exit;
   729  	}
   730  
   731  	if(state->restart == 0)
   732  	{
   733  		/* Start compilation */
   734  
   735  		/* Perform machine-independent optimizations */
   736  		optimize(state->func);
   737  
   738  		/* Prepare data needed for code generation */
   739  		codegen_prepare(state);
   740  
   741  		/* Allocate some space */
   742  		memory_acquire(state);
   743  		memory_alloc(state);
   744  	}
   745  	else
   746  	{
   747  		/* Restart compilation */
   748  
   749  		/* Clean up the compilation state */
   750  		cleanup_on_restart(&state->gen, state->func);
   751  
   752  		/* Allocate more space */
   753  		memory_realloc(state);
   754  	}
   755  
   756  #ifdef _JIT_COMPILE_DEBUG
   757  	if(state->restart == 0)
   758  	{
   759  		printf("\n*** Start code generation ***\n\n");
   760  	}
   761  	else
   762  	{
   763  		printf("\n*** Restart code generation ***\n\n");
   764  	}
   765  	state->func->builder->block_count = 0;
   766  	state->func->builder->insn_count = 0;
   767  #endif
   768  
   769  #ifdef jit_extra_gen_init
   770  	/* Initialize information that may need to be reset both
   771  	   on start and restart */
   772  	jit_extra_gen_init(&state->gen);
   773  #endif
   774  
   775  	/* Perform code generation */
   776  	codegen(state);
   777  
   778  #ifdef jit_extra_gen_cleanup
   779  	/* Clean up the extra code generation state */
   780  	jit_extra_gen_cleanup(&state->gen);
   781  #endif
   782  
   783  	/* End the function's output process */
   784  	memory_flush(state);
   785  
   786  	/* Compilation done, no exceptions occurred */
   787  	result = JIT_RESULT_OK;
   788  
   789   exit:
   790  	/* Release the memory context */
   791  	memory_release(state);
   792  
   793  	/* Restore the "setjmp" context */
   794  	_jit_unwind_pop_setjmp();
   795  
   796  	/* Restore user's exception handler */
   797  	jit_exception_set_handler(handler);
   798  
   799  	return result;
   800  }
   801  
   802  /*@
   803   * @deftypefun int jit_compile (jit_function_t @var{func})
   804   * Compile a function to its executable form.  If the function was
   805   * already compiled, then do nothing.  Returns zero on error.
   806   *
   807   * If an error occurs, you can use @code{jit_function_abandon} to
   808   * completely destroy the function.  Once the function has been compiled
   809   * successfully, it can no longer be abandoned.
   810   *
   811   * Sometimes you may wish to recompile a function, to apply greater
   812   * levels of optimization the second time around.  You must call
   813   * @code{jit_function_set_recompilable} before you compile the function
   814   * the first time.  On the second time around, build the function's
   815   * instructions again, and call @code{jit_compile} a second time.
   816   * @end deftypefun
   817  @*/
   818  int
   819  jit_compile(jit_function_t func)
   820  {
   821  	_jit_compile_t state;
   822  	int result;
   823  
   824  	/* Bail out on invalid parameter */
   825  	if(!func)
   826  	{
   827  		return JIT_RESULT_NULL_FUNCTION;
   828  	}
   829  
   830  	/* Bail out if there is nothing to do here */
   831  	if(!func->builder)
   832  	{
   833  		if(func->is_compiled)
   834  		{
   835  			/* The function is already compiled, and we don't need to recompile */
   836  			return JIT_RESULT_OK;
   837  		}
   838  		else
   839  		{
   840  			/* We don't have anything to compile at all */
   841  			return JIT_RESULT_NULL_FUNCTION;
   842  		}
   843  	}
   844  
   845  	/* Compile and record the entry point */
   846  	result = compile(&state, func);
   847  	if(result == JIT_RESULT_OK)
   848  	{
   849  		func->entry_point = state.gen.code_start;
   850  		func->is_compiled = 1;
   851  
   852  		/* Free the builder structure, which we no longer require */
   853  		_jit_function_free_builder(func);
   854  	}
   855  
   856  	return result;
   857  }
   858  
   859  /*@
   860   * @deftypefun int jit_compile_entry (jit_function_t @var{func}, void **@var{entry_point})
   861   * Compile a function to its executable form but do not make it
   862   * available for invocation yet.  It may be made available later
   863   * with @code{jit_function_setup_entry}.
   864   * @end deftypefun
   865  @*/
   866  int
   867  jit_compile_entry(jit_function_t func, void **entry_point)
   868  {
   869  	_jit_compile_t state;
   870  	int result;
   871  
   872  	/* Init entry_point */
   873  	if(entry_point)
   874  	{
   875  		*entry_point = 0;
   876  	}
   877  	else
   878  	{
   879  		return JIT_RESULT_NULL_REFERENCE;
   880  	}
   881  
   882  	/* Bail out on invalid parameter */
   883  	if(!func)
   884  	{
   885  		return JIT_RESULT_NULL_FUNCTION;
   886  	}
   887  
   888  	/* Bail out if there is nothing to do here */
   889  	if(!func->builder)
   890  	{
   891  		if(func->is_compiled)
   892  		{
   893  			/* The function is already compiled, and we don't need to recompile */
   894  			*entry_point = func->entry_point;
   895  			return JIT_RESULT_OK;
   896  		}
   897  		else
   898  		{
   899  			/* We don't have anything to compile at all */
   900  			return JIT_RESULT_NULL_FUNCTION;
   901  		}
   902  	}
   903  
   904  	/* Compile and return the entry point */
   905  	result = compile(&state, func);
   906  	if(result == JIT_RESULT_OK)
   907  	{
   908  		*entry_point = state.gen.code_start;
   909  	}
   910  
   911  	return result;
   912  }
   913  
   914  /*@
   915   * @deftypefun int jit_function_setup_entry (jit_function_t @var{func}, void *@var{entry_point})
   916   * Make a function compiled with @code{jit_function_compile_entry}
   917   * available for invocation and free the resources used for
   918   * compilation.  If @var{entry_point} is null then it only
   919   * frees the resources.
   920   * @end deftypefun
   921  @*/
   922  void
   923  jit_function_setup_entry(jit_function_t func, void *entry_point)
   924  {
   925  	/* Bail out if we have nothing to do */
   926  	if(!func)
   927  	{
   928  		return;
   929  	}
   930  	/* Record the entry point */
   931  	if(entry_point)
   932  	{
   933  		func->entry_point = entry_point;
   934  		func->is_compiled = 1;
   935  	}
   936  	_jit_function_free_builder(func);
   937  }
   938  
   939  /*@
   940   * @deftypefun int jit_function_compile (jit_function_t @var{func})
   941   * Compile a function to its executable form.  If the function was
   942   * already compiled, then do nothing.  Returns zero on error.
   943   *
   944   * If an error occurs, you can use @code{jit_function_abandon} to
   945   * completely destroy the function.  Once the function has been compiled
   946   * successfully, it can no longer be abandoned.
   947   *
   948   * Sometimes you may wish to recompile a function, to apply greater
   949   * levels of optimization the second time around.  You must call
   950   * @code{jit_function_set_recompilable} before you compile the function
   951   * the first time.  On the second time around, build the function's
   952   * instructions again, and call @code{jit_function_compile}
   953   * a second time.
   954   * @end deftypefun
   955  @*/
   956  int
   957  jit_function_compile(jit_function_t func)
   958  {
   959  	return (JIT_RESULT_OK == jit_compile(func));
   960  }
   961  
   962  /*@
   963   * @deftypefun int jit_function_compile_entry (jit_function_t @var{func}, void **@var{entry_point})
   964   * Compile a function to its executable form but do not make it
   965   * available for invocation yet.  It may be made available later
   966   * with @code{jit_function_setup_entry}.
   967   * @end deftypefun
   968  @*/
   969  int
   970  jit_function_compile_entry(jit_function_t func, void **entry_point)
   971  {
   972  	return (JIT_RESULT_OK == jit_compile_entry(func, entry_point));
   973  }
   974  
   975  void *
   976  _jit_function_compile_on_demand(jit_function_t func)
   977  {
   978  	_jit_compile_t state;
   979  	int result;
   980  
   981  	/* Lock down the context */
   982  	jit_context_build_start(func->context);
   983  
   984  	/* Fast return if we are already compiled */
   985  	if(func->is_compiled)
   986  	{
   987  		jit_context_build_end(func->context);
   988  		return func->entry_point;
   989  	}
   990  
   991  	if(!func->on_demand)
   992  	{
   993  		/* Bail out with an error if the user didn't supply an
   994  		   on-demand compiler */
   995  		result = JIT_RESULT_COMPILE_ERROR;
   996  	}
   997  	else
   998  	{
   999  		/* Call the user's on-demand compiler. */
  1000  		result = (func->on_demand)(func);
  1001  		if(result == JIT_RESULT_OK && !func->is_compiled)
  1002  		{
  1003  			/* Compile the function if the user didn't do so */
  1004  			result = compile(&state, func);
  1005  			if(result == JIT_RESULT_OK)
  1006  			{
  1007  				func->entry_point = state.gen.code_start;
  1008  				func->is_compiled = 1;
  1009  			}
  1010  		}
  1011  		_jit_function_free_builder(func);
  1012  	}
  1013  
  1014  	/* Unlock the context and report the result */
  1015  	jit_context_build_end(func->context);
  1016  	if(result != JIT_RESULT_OK)
  1017  	{
  1018  		jit_exception_builtin(result);
  1019  		/* Normally this should be unreachable but just in case... */
  1020  		return 0;
  1021  	}
  1022  
  1023  	return func->entry_point;
  1024  }
  1025  
  1026  #define	JIT_CACHE_NO_OFFSET		(~((unsigned long)0))
  1027  
  1028  unsigned long
  1029  _jit_function_get_bytecode(jit_function_t func,
  1030  			   void *func_info, void *pc, int exact)
  1031  {
  1032  	unsigned long offset = JIT_CACHE_NO_OFFSET;
  1033  	void *start;
  1034  	unsigned long native_offset;
  1035  	jit_varint_decoder_t decoder;
  1036  	jit_uint off, noff;
  1037  
  1038  	start = _jit_memory_get_function_start(func->context, func_info);
  1039  	native_offset = pc - start;
  1040  
  1041  	_jit_varint_init_decoder(&decoder, func->bytecode_offset);
  1042  	for(;;)
  1043  	{
  1044  		off = _jit_varint_decode_uint(&decoder);
  1045  		noff = _jit_varint_decode_uint(&decoder);
  1046  		if(_jit_varint_decode_end(&decoder))
  1047  		{
  1048  			if(exact)
  1049  			{
  1050  				offset = JIT_CACHE_NO_OFFSET;
  1051  			}
  1052  			break;
  1053  		}
  1054  		if(noff >= native_offset)
  1055  		{
  1056  			if(noff == native_offset)
  1057  			{
  1058  				offset = off;
  1059  			}
  1060  			else if (exact)
  1061  			{
  1062  				offset = JIT_CACHE_NO_OFFSET;
  1063  			}
  1064  			break;
  1065  		}
  1066  		offset = off;
  1067  	}
  1068  
  1069  	return offset;
  1070  }