Alien-LibJIT
view release on metacpan or search on metacpan
libjit/jit/jit-rules-interp.c view on Meta::CPAN
* and then once you have them working you can move on to the floating point
* operations.
* @end deftypefun
@*/
int _jit_opcode_is_supported(int opcode)
{
/* We support all opcodes in the interpreter */
return 1;
}
/*
* Calculate the size of the argument area for an interpreted function.
*/
unsigned int _jit_interp_calculate_arg_size
(jit_function_t func, jit_type_t signature)
{
unsigned int size = 0;
jit_type_t type;
unsigned int num_params;
unsigned int param;
/* Determine if we need nested parameter information */
if(func->nested_parent)
{
size += 2 * sizeof(jit_item);
}
/* Determine if we need a structure pointer argument */
type = jit_type_get_return(signature);
if(jit_type_return_via_pointer(type))
{
size += sizeof(jit_item);
}
/* Calculate the total size of the regular arguments */
num_params = jit_type_num_params(signature);
for(param = 0; param < num_params; ++param)
{
type = jit_type_normalize(jit_type_get_param(signature, param));
if(type->kind == JIT_TYPE_STRUCT || type->kind == JIT_TYPE_UNION)
{
size += JIT_NUM_ITEMS_IN_STRUCT(jit_type_get_size(type)) *
sizeof(jit_item);
}
else
{
size += sizeof(jit_item);
}
}
/* Return the final size to the caller */
return size;
}
/*@
* @deftypefun {void *} _jit_gen_prolog (jit_gencode_t @var{gen}, jit_function_t @var{func}, void *@var{buf})
* Generate the prolog for a function into a previously-prepared
* buffer area of @code{JIT_PROLOG_SIZE} bytes in size. Returns
* the start of the prolog, which may be different than @var{buf}.
*
* This function is called at the end of the code generation process,
* not the beginning. At this point, it is known which callee save
* registers must be preserved, allowing the back end to output the
* most compact prolog possible.
* @end deftypefun
@*/
void *_jit_gen_prolog(jit_gencode_t gen, jit_function_t func, void *buf)
{
/* Output the jit_function_interp structure at the beginning */
jit_function_interp_t interp = (jit_function_interp_t)buf;
unsigned int max_working_area =
gen->max_working_area + gen->extra_working_space;
interp->func = func;
interp->args_size = _jit_interp_calculate_arg_size(func, func->signature);
interp->frame_size =
(func->builder->frame_size + max_working_area) * sizeof(jit_item);
interp->working_area = max_working_area;
return buf;
}
/*@
* @deftypefun void _jit_gen_epilog (jit_gencode_t @var{gen}, jit_function_t @var{func})
* Generate a function epilog, restoring the registers that
* were saved on entry to the function, and then returning.
*
* Only one epilog is generated per function. Functions with multiple
* @code{jit_insn_return} instructions will all jump to the common epilog.
* This is needed because the code generator may not know which callee
* save registers need to be restored by the epilog until the full function
* has been processed.
* @end deftypefun
@*/
void _jit_gen_epilog(jit_gencode_t gen, jit_function_t func)
{
/* The interpreter doesn't use epilogs */
}
/*@
* @deftypefun {void *} _jit_gen_redirector (jit_gencode_t @var{gen}, jit_function_t @var{func})
* Generate code for a redirector, which makes an indirect jump
* to the contents of @code{@var{func}->entry_point}. Redirectors
* are used on recompilable functions in place of the regular
* entry point. This allows @code{libjit} to redirect existing
* calls to the new version after recompilation.
* @end deftypefun
@*/
void *_jit_gen_redirector(jit_gencode_t gen, jit_function_t func)
{
/* The interpreter doesn't need redirectors */
return 0;
}
/*@
* @deftypefun void _jit_gen_spill_reg (jit_gencode_t @var{gen}, int @var{reg}, int @var{other_reg}, jit_value_t @var{value})
* Generate instructions to spill a pseudo register to the local
* variable frame. If @var{other_reg} is not -1, then it indicates
* the second register in a 64-bit register pair.
*
* This function will typically call @code{_jit_gen_fix_value} to
* fix the value's frame position, and will then generate the
* appropriate spill instructions.
* @end deftypefun
@*/
void _jit_gen_spill_reg(jit_gencode_t gen, int reg,
int other_reg, jit_value_t value)
{
/* Registers are not used in the interpreted back end */
}
/*@
* @deftypefun void _jit_gen_free_reg (jit_gencode_t @var{gen}, int @var{reg}, int @var{other_reg}, int @var{value_used})
* Generate instructions to free a register without spilling its value.
* This is called when a register's contents become invalid, or its
* value is no longer required. If @var{value_used} is set to a non-zero
* value, then it indicates that the register's value was just used.
* Otherwise, there is a value in the register but it was never used.
*
* On most platforms, this function won't need to do anything to free
* the register. But some do need to take explicit action. For example,
* x86 needs an explicit instruction to remove a floating-point value
* from the FPU's stack if its value has not been used yet.
* @end deftypefun
@*/
void _jit_gen_free_reg(jit_gencode_t gen, int reg,
int other_reg, int value_used)
{
/* Registers are not used in the interpreted back end */
}
/*@
( run in 0.641 second using v1.01-cache-2.11-cpan-5735350b133 )