Alien-LibJIT
view release on metacpan or search on metacpan
libjit/jit/jit-rules-interp.c view on Meta::CPAN
@table @code
@item name
The name of the register. This is used for debugging purposes.
@item cpu_reg
The raw CPU register number. Registers in @code{libjit} are
referred to by their pseudo register numbers, corresponding to
their index within @code{JIT_REG_INFO}. However, these pseudo
register numbers may not necessarily correspond to the register
numbers used by the actual CPU. This field provides a mapping.
@item other_reg
The second pseudo register in a 64-bit register pair, or -1 if
the current register cannot be used as the first pseudo register
in a 64-bit register pair. This field only has meaning on 32-bit
platforms, and should always be set to -1 on 64-bit platforms.
@item flags
Flag bits that describe the pseudo register's properties.
@end table
@noindent
The following flags may be present:
@table @code
@item JIT_REG_WORD
This register can hold an integer word value.
@item JIT_REG_LONG
This register can hold a 64-bit long value without needing a
second register. Normally only used on 64-bit platforms.
@item JIT_REG_FLOAT32
This register can hold a 32-bit floating-point value.
@item JIT_REG_FLOAT64
This register can hold a 64-bit floating-point value.
@item JIT_REG_NFLOAT
This register can hold a native floating-point value.
@item JIT_REG_FRAME
This register holds the frame pointer. You will almost always supply
@code{JIT_REG_FIXED} for this register.
@item JIT_REG_STACK_PTR
This register holds the stack pointer. You will almost always supply
@code{JIT_REG_FIXED} for this register.
@item JIT_REG_FIXED
This register has a fixed meaning and cannot be used for general allocation.
@item JIT_REG_CALL_USED
This register will be destroyed by a function call.
@item JIT_REG_IN_STACK
This register is in a stack-like arrangement.
@item JIT_REG_GLOBAL
This register is a candidate for global register allocation.
@end table
A CPU may have some registers arranged into a stack. In this case
operations can typically only occur at the top of the stack, and
may automatically pop values as a side-effect of the operation.
An example of such architecture is x87 floating point unit. Such
CPU requires three additional macros.
@table @code
@item JIT_REG_STACK
If defined, this indicates the presence of the register stack.
@item JIT_REG_STACK_START
The index of the first register in the @code{JIT_REG_INFO} array that is used
in a stack-like arrangement.
@item JIT_REG_STACK_END
The index of the last register in the @code{JIT_REG_INFO} array that is used
in a stack-like arrangement.
@end table
The entries in the @code{JIT_REG_INFO} array from @code{JIT_REG_STACK_START}
up to @code{JIT_REG_STACK_END} must also have the @code{JIT_REG_IN_STACK}
flag set.
@subsection Other architecture macros
@noindent
The rule file may also have definitions of the following macros:
@table @code
@item JIT_NUM_GLOBAL_REGS
The number of registers that are used for global register allocation.
Set to zero if global register allocation should not be used.
@item JIT_ALWAYS_REG_REG
Define this to 1 if arithmetic operations must always be performed
on registers. Define this to 0 if register/memory and memory/register
operations are possible.
@item JIT_PROLOG_SIZE
If defined, this indicates the maximum size of the function prolog.
@item JIT_FUNCTION_ALIGNMENT
This value indicates the alignment required for the start of a function.
e.g. define this to 32 if functions should be aligned on a 32-byte
boundary.
@item JIT_ALIGN_OVERRIDES
Define this to 1 if the platform allows reads and writes on
any byte boundary. Define to 0 if only properly-aligned
memory accesses are allowed. Normally only defined to 1 under x86.
@item jit_extra_gen_state
@itemx jit_extra_gen_init
@itemx jit_extra_gen_cleanup
The @code{jit_extra_gen_state} macro can be supplied to add extra fields
to the @code{struct jit_gencode} type in @code{jit-rules.h}, for
extra CPU-specific code generation state information.
The @code{jit_extra_gen_init} macro initializes this extra information,
and the @code{jit_extra_gen_cleanup} macro cleans it up when code
generation is complete.
@end table
@subsection Architecture-dependent functions
@*/
/*
* Output a native word to the current method.
*/
#define jit_cache_native(gen,value) \
do { \
_jit_gen_check_space((gen), sizeof(jit_nuint)); \
*((jit_nuint *)((gen)->ptr)) = (jit_nuint)(value); \
(gen)->ptr += sizeof(jit_nuint); \
} while (0)
/*
* Write an interpreter opcode to the cache.
*/
#define jit_cache_opcode(gen,opcode) \
jit_cache_native((gen), (jit_nint)(opcode))
/*
* Write "n" bytes to the cache, rounded up to a multiple of "void *".
*/
#define jit_cache_add_n(gen,buf,size) \
do { \
unsigned int __size = \
((size) + sizeof(void *) - 1) & ~(sizeof(void *) - 1); \
_jit_gen_check_space((gen), __size); \
jit_memcpy((gen)->ptr, (buf), (size)); \
libjit/jit/jit-rules-interp.c view on Meta::CPAN
* 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 */
}
/*@
* @deftypefun void _jit_gen_load_value (jit_gencode_t @var{gen}, int @var{reg}, int @var{other_reg}, jit_value_t @var{value})
* Generate instructions to load a value into a register. The value will
* either be a constant or a slot in the frame. You should fix frame slots
* with @code{_jit_gen_fix_value}.
* @end deftypefun
@*/
void _jit_gen_load_value
(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_spill_global (jit_gencode_t @var{gen}, int @var{reg}, jit_value_t @var{value})
* Spill the contents of @var{value} from its corresponding global register.
* This is used in rare cases when a machine instruction requires its operand
* to be in the specific register that happens to be global. In such cases the
* register is spilled just before the instruction and loaded back immediately
* after it.
* @end deftypefun
@*/
void _jit_gen_spill_global(jit_gencode_t gen, int reg, jit_value_t value)
{
/* Global registers are not used in the interpreted back end */
}
/*@
* @deftypefun void _jit_gen_load_global (jit_gencode_t @var{gen}, int @var{reg}, jit_value_t @var{value})
* Load the contents of @var{value} into its corresponding global register.
* This is used at the head of a function to pull parameters out of stack
* slots into their global register copies.
* @end deftypefun
@*/
void _jit_gen_load_global(jit_gencode_t gen, int reg, jit_value_t value)
{
/* Global registers are not used in the interpreted back end */
}
/*@
* @deftypefun void _jit_gen_exch_top (jit_gencode_t @var{gen}, int @var{reg})
* Generate instructions to exchange the contents of the top stack register
* with a stack register specified by the @var{reg} argument.
*
* It needs to be implemented only by backends that support stack registers.
* @end deftypefun
@*/
void _jit_gen_exch_top(jit_gencode_t gen, int reg)
{
/* Stack registers are not used in the interpreted back end */
}
/*@
* @deftypefun void _jit_gen_move_top (jit_gencode_t @var{gen}, int @var{reg})
* Generate instructions to copy the contents of the top stack register
* into a stack register specified by the @code{reg} argument and pop
* the top register after this. If @code{reg} is equal to the top register
* then the top register is just popped without copying it.
*
* It needs to be implemented only by backends that support stack registers.
* @end deftypefun
@*/
void _jit_gen_move_top(jit_gencode_t gen, int reg)
{
/* Stack registers are not used in the interpreted back end */
}
/*@
* @deftypefun void _jit_gen_spill_top (jit_gencode_t @var{gen}, int @var{reg}, jit_value_t @var{value}, int @var{pop})
* Generate instructions to spill the top stack register to the local
* variable frame. The @var{pop} argument indicates if the top register
* is popped from the stack.
*
* It needs to be implemented only by backends that support stack registers.
* @end deftypefun
@*/
void _jit_gen_spill_top(jit_gencode_t gen, int reg, jit_value_t value, int pop)
{
/* Stack registers are not used in the interpreted back end */
}
/*@
* @deftypefun void _jit_gen_fix_value (jit_value_t @var{value})
* Fix the position of a value within the local variable frame.
* If it doesn't already have a position, then assign one for it.
* @end deftypefun
@*/
void _jit_gen_fix_value(jit_value_t value)
{
if(!(value->has_frame_offset) && !(value->is_constant))
{
jit_nint size = (jit_nint)
(JIT_NUM_ITEMS_IN_STRUCT(jit_type_get_size(value->type)));
value->frame_offset = value->block->func->builder->frame_size;
value->block->func->builder->frame_size += size;
libjit/jit/jit-rules-interp.c view on Meta::CPAN
}
break;
}
}
/*@
* @deftypefun void _jit_gen_start_block (jit_gencode_t @var{gen}, jit_block_t @var{block})
* Called to notify the back end that the start of a basic block
* has been reached.
* @end deftypefun
@*/
void _jit_gen_start_block(jit_gencode_t gen, jit_block_t block)
{
void **fixup;
void **next;
/* Set the address of this block */
block->address = (void *)(gen->ptr);
/* If this block has pending fixups, then apply them now */
fixup = (void **)(block->fixup_list);
while(fixup != 0)
{
next = (void **)(fixup[1]);
fixup[1] = (void *)(jit_nint)(((void **)(block->address)) - fixup);
fixup = next;
}
block->fixup_list = 0;
fixup = (void **)(block->fixup_absolute_list);
while(fixup != 0)
{
next = (void **)(fixup[0]);
fixup[0] = (void *)(jit_nint)((void **)(block->address));
fixup = next;
}
block->fixup_absolute_list = 0;
/* If this is the exception catcher block, then we need to update
the exception cookie for the function to point to here */
if(block->label == block->func->builder->catcher_label &&
block->func->has_try)
{
block->func->cookie = block->address;
}
}
/*@
* @deftypefun void _jit_gen_end_block (jit_gencode_t @var{gen})
* Called to notify the back end that the end of a basic block
* has been reached.
* @end deftypefun
@*/
void _jit_gen_end_block(jit_gencode_t gen, jit_block_t block)
{
/* Reset the working area size to zero for the next block */
gen->working_area = 0;
}
/*@
* @deftypefun int _jit_gen_is_global_candidate (jit_type_t @var{type})
* Determine if @var{type} is a candidate for allocation within
* global registers.
* @end deftypefun
@*/
int _jit_gen_is_global_candidate(jit_type_t type)
{
/* Global register allocation is not used by the interpreter */
return 0;
}
/*@
* @deftypefun int _jit_reg_get_pair (jit_type_t @var{type}, int @var{reg})
* Determine if a type requires a register pair. If so then for the specified
* register @var{reg} return the other register of the corresponding pair.
* Return -1 if no pair is required.
*
* This function is used only for native 32-bit backends.
* @end deftypefun
@*/
int _jit_reg_get_pair(jit_type_t type, int reg)
{
/* We don't register pairs on 64-bit platforms or the interpreter */
return -1;
}
#endif /* JIT_BACKEND_INTERP */
( run in 0.839 second using v1.01-cache-2.11-cpan-f0fbb3f571b )