Alien-LibJIT
view release on metacpan or search on metacpan
libjit/jit/jit-insn.c view on Meta::CPAN
/* Clear the original "catch_pc" value within "setjmp_value" */
if(!jit_insn_store_relative
(func, jit_insn_address_of(func, func->builder->setjmp_value),
jit_jmp_catch_pc_offset, jit_value_create_nint_constant
(func, jit_type_void_ptr, 0)))
{
return 0;
}
/* Jump to this function's exception catcher */
if(!jit_insn_branch(func, &(func->builder->catcher_label)))
{
return 0;
}
/* Mark the position of the rethrow label */
if(!jit_insn_label(func, &rethrow_label))
{
return 0;
}
/* Call "_jit_unwind_pop_and_rethrow" to pop the current
"setjmp" context and then rethrow the current exception */
type = jit_type_create_signature
(jit_abi_cdecl, jit_type_void, 0, 0, 1);
if(!type)
{
return 0;
}
jit_insn_call_native
(func, "_jit_unwind_pop_and_rethrow",
(void *)_jit_unwind_pop_and_rethrow, type, 0, 0,
JIT_CALL_NOTHROW | JIT_CALL_NORETURN);
jit_type_free(type);
/* Insert the target to jump to the normal code. */
if(!jit_insn_label(func, &code_label))
{
return 0;
}
/* Force the start of a new block to mark the end of the init code */
if(!jit_insn_label(func, &end_label))
{
return 0;
}
/* Move the initialization code to the head of the function so that
it is performed once upon entry to the function */
return jit_insn_move_blocks_to_start(func, start_label, end_label);
#else
/* The interpreter doesn't need the "setjmp" setup block */
func->builder->catcher_label = jit_label_undefined;
return 1;
#endif
}
/*@
* @deftypefun int jit_insn_uses_catcher (jit_function_t @var{func})
* Notify the function building process that @var{func} contains
* some form of @code{catch} clause for catching exceptions. This must
* be called before any instruction that is covered by a @code{try},
* ideally at the start of the function output process.
* @end deftypefun
@*/
int jit_insn_uses_catcher(jit_function_t func)
{
if(!_jit_function_ensure_builder(func))
{
return 0;
}
if(func->has_try)
{
return 1;
}
func->has_try = 1;
func->builder->may_throw = 1;
func->builder->non_leaf = 1;
return initialize_setjmp_block(func);
}
/*@
* @deftypefun jit_value_t jit_insn_start_catcher (jit_function_t @var{func})
* Start the catcher block for @var{func}. There should be exactly one
* catcher block for any function that involves a @code{try}. All
* exceptions that are thrown within the function will cause control
* to jump to this point. Returns a value that holds the exception
* that was thrown.
* @end deftypefun
@*/
jit_value_t jit_insn_start_catcher(jit_function_t func)
{
jit_value_t value;
#if !defined(JIT_BACKEND_INTERP)
jit_value_t last_exception;
jit_type_t type;
#endif
if(!_jit_function_ensure_builder(func))
{
return 0;
}
if(!jit_insn_label(func, &(func->builder->catcher_label)))
{
return 0;
}
value = jit_insn_thrown_exception(func);
if(!value)
{
return 0;
}
#if defined(JIT_BACKEND_INTERP)
/* In the interpreter, the exception object will be on the top of
the operand stack when control reaches the catcher */
if(!jit_insn_incoming_reg(func, value, 0))
{
return 0;
}
#else
type = jit_type_create_signature(jit_abi_cdecl, jit_type_void_ptr, 0, 0, 1);
if(!type)
{
return 0;
}
libjit/jit/jit-insn.c view on Meta::CPAN
/* The current block ends in a dead instruction */
func->builder->current_block->ends_in_dead = 1;
/* Create a new block for the following code */
return jit_insn_new_block(func);
}
/*@
* @deftypefun int jit_insn_call_finally (jit_function_t @var{func}, jit_label_t *@var{finally_label})
* Call a @code{finally} clause.
* @end deftypefun
@*/
int jit_insn_call_finally(jit_function_t func, jit_label_t *finally_label)
{
jit_insn_t insn;
/* Ensure that we have a function builder */
if(!_jit_function_ensure_builder(func))
{
return 0;
}
/* Flush any stack pops that were deferred previously */
if(!jit_insn_flush_defer_pop(func, 0))
{
return 0;
}
/* Allocate the label number if necessary */
if(*finally_label == jit_label_undefined)
{
*finally_label = (func->builder->next_label)++;
}
/* Calling a finally handler makes the function not a leaf because
we may need to do a native "call" to invoke the handler */
func->builder->non_leaf = 1;
/* Add a new branch instruction to branch to the finally handler */
insn = _jit_block_add_insn(func->builder->current_block);
if(!insn)
{
return 0;
}
insn->opcode = (short)JIT_OP_CALL_FINALLY;
insn->flags = JIT_INSN_DEST_IS_LABEL;
insn->dest = (jit_value_t)(*finally_label);
/* Create a new block for the following code */
return jit_insn_new_block(func);
}
/*@
* @deftypefun jit_value_t jit_insn_start_filter (jit_function_t @var{func}, jit_label_t *@var{label}, jit_type_t @var{type})
* Define the start of a filter. Filters are embedded subroutines within
* functions that are used to filter exceptions in @code{catch} blocks.
*
* A filter subroutine takes a single argument (usually a pointer) and
* returns a single result (usually a boolean). The filter has complete
* access to the local variables of the function, and can use any of
* them in the filtering process.
*
* This function returns a temporary value of the specified @var{type},
* indicating the parameter that is supplied to the filter.
* @end deftypefun
@*/
jit_value_t jit_insn_start_filter
(jit_function_t func, jit_label_t *label, jit_type_t type)
{
/* Set a label at this point to start a new block */
if(!jit_insn_label(func, label))
{
return 0;
}
/* Create a note to load the filter's parameter at runtime */
return create_dest_note(func, JIT_OP_ENTER_FILTER, type);
}
/*@
* @deftypefun int jit_insn_return_from_filter (jit_function_t @var{func}, jit_value_t @var{value})
* Return from a filter subroutine with the specified @code{value} as
* its result.
* @end deftypefun
@*/
int jit_insn_return_from_filter(jit_function_t func, jit_value_t value)
{
/* Flush any deferred stack pops before we return */
if(!jit_insn_flush_defer_pop(func, 0))
{
return 0;
}
/* Mark the end of the "filter" clause */
if(!create_unary_note(func, JIT_OP_LEAVE_FILTER, value))
{
return 0;
}
/* The current block ends in a dead instruction */
func->builder->current_block->ends_in_dead = 1;
/* Create a new block for the following code */
return jit_insn_new_block(func);
}
/*@
* @deftypefun jit_value_t jit_insn_call_filter (jit_function_t @var{func}, jit_label_t *@var{label}, jit_value_t @var{value}, jit_type_t @var{type})
* Call the filter subroutine at @var{label}, passing it @var{value} as
* its argument. This function returns a value of the specified
* @var{type}, indicating the filter's result.
* @end deftypefun
@*/
jit_value_t jit_insn_call_filter
(jit_function_t func, jit_label_t *label,
jit_value_t value, jit_type_t type)
{
jit_insn_t insn;
/* Ensure that we have a function builder */
if(!_jit_function_ensure_builder(func))
( run in 1.267 second using v1.01-cache-2.11-cpan-5b529ec07f3 )