Alien-LibJIT

 view release on metacpan or  search on metacpan

libjit/jit/jit-insn.c  view on Meta::CPAN

		return 1;
	}
	else
	{
		return 0;
	}
}

/*@
 * @deftypefun void jit_insn_label (jit_function_t @var{func}, jit_label_t *@var{label})
 * Start a new basic block within the function @var{func} and give it the
 * specified @var{label}.  If the call is made when a new block was just
 * created by any previous call then that block is reused, no new block
 * is created.  Returns zero if out of memory.
 *
 * If the contents of @var{label} are @code{jit_label_undefined}, then this
 * function will allocate a new label for this block.  Otherwise it will
 * reuse the specified label from a previous branch instruction.
 * @end deftypefun
@*/
int
jit_insn_label(jit_function_t func, jit_label_t *label)
{
	jit_block_t block;

	if(!_jit_function_ensure_builder(func))
	{
		return 0;
	}
	if(!jit_insn_flush_defer_pop(func, 0))
	{
		return 0;
	}

	/* Create a new block if the current one is not empty */
	block = func->builder->current_block;
	if(_jit_block_get_last(block))
	{
		block = _jit_block_create(func);
		if(!block)
		{
			return 0;
		}
	}

	/* Record the label */
	if(*label == jit_label_undefined)
	{
		*label = (func->builder->next_label)++;
	}
	if(!_jit_block_record_label(block, *label))
	{
		_jit_block_destroy(block);
		return 0;
	}

	/* If the block is newly created then insert it to the end of
	   the function's block list */
	if(block != func->builder->current_block)
	{
		_jit_block_attach_before(func->builder->exit_block, block, block);
		func->builder->current_block = block;
	}

	return 1;
}

/*@
 * @deftypefun int jit_insn_new_block (jit_function_t @var{func})
 * Start a new basic block, without giving it an explicit label.
 * @end deftypefun
@*/
int
jit_insn_new_block(jit_function_t func)
{
	jit_block_t block;
#ifdef _JIT_BLOCK_DEBUG
	jit_label_t label;
#endif

	/* Create a new block */
	block = _jit_block_create(func);
	if(!block)
	{
		return 0;
	}

#ifdef _JIT_BLOCK_DEBUG
	label = (func->builder->next_label)++;
	if(!_jit_block_record_label(block, label))
	{
		_jit_block_destroy(block);
		return 0;
	}
#endif

	/* Insert the block to the end of the function's block list */
	_jit_block_attach_before(func->builder->exit_block, block, block);
	func->builder->current_block = block;

	return 1;
}

int _jit_load_opcode(int base_opcode, jit_type_t type,
					 jit_value_t value, int no_temps)
{
	type = jit_type_normalize(type);
	if(!type)
	{
		return 0;
	}
	switch(type->kind)
	{
		case JIT_TYPE_SBYTE:
		{
			return base_opcode;
		}
		/* Not reached */

		case JIT_TYPE_UBYTE:
		{
			return base_opcode + 1;
		}
		/* Not reached */

		case JIT_TYPE_SHORT:
		{
			return base_opcode + 2;
		}
		/* Not reached */

		case JIT_TYPE_USHORT:
		{
			return base_opcode + 3;
		}
		/* Not reached */

		case JIT_TYPE_INT:
		case JIT_TYPE_UINT:
		{
			if(no_temps && value && (value->is_temporary || value->is_local))
			{
				return 0;
			}
			return base_opcode + 4;
		}
		/* Not reached */

		case JIT_TYPE_LONG:
		case JIT_TYPE_ULONG:
		{
			if(no_temps && value && (value->is_temporary || value->is_local))
			{
				return 0;
			}
			return base_opcode + 5;
		}
		/* Not reached */

libjit/jit/jit-insn.c  view on Meta::CPAN

	/* Round the size to the best alignment boundary on this platform */
	size = jit_insn_convert(func, size, jit_type_nuint, 0);
	size = jit_insn_add
		(func, size, jit_value_create_nint_constant
			(func, jit_type_nuint, JIT_BEST_ALIGNMENT - 1));
	size = jit_insn_and
		(func, size, jit_value_create_nint_constant
			(func, jit_type_nuint, ~((jit_nint)(JIT_BEST_ALIGNMENT - 1))));

	/* Allocate "size" bytes of memory from the stack */
	return apply_unary(func, JIT_OP_ALLOCA, size, jit_type_void_ptr);
}

/*@
 * @deftypefun int jit_insn_move_blocks_to_end (jit_function_t @var{func}, jit_label_t @var{from_label}, jit_label_t @var{to_label})
 * Move all of the blocks between @var{from_label} (inclusive) and
 * @var{to_label} (exclusive) to the end of the current function.
 * This is typically used to move the expression in a @code{while}
 * loop to the end of the body, where it can be executed more
 * efficiently.
 * @end deftypefun
@*/
int jit_insn_move_blocks_to_end
	(jit_function_t func, jit_label_t from_label, jit_label_t to_label)
{
	jit_block_t first, last, block;

	/* Make sure that deferred stack pops are flushed */
	if(!jit_insn_flush_defer_pop(func, 0))
	{
		return 0;
	}

	/* Find the first block that needs to be moved */
	first = jit_block_from_label(func, from_label);
	if(!first)
	{
		return 0;
	}

	/* Find the last block that needs to be moved */
	last = jit_block_from_label(func, to_label);
	if(!last)
	{
		return 0;
	}

	/* Sanity check -- the last block has to be after the first */
	for(block = first->next; block != last; block = block->next)
	{
		if (!block) {
			return 0;
		}
	}

	/* The last block is excluded from the blocks to move */
	block = last->prev;

	/* Move the blocks to the end */
	_jit_block_detach(first, block);
	_jit_block_attach_before(func->builder->exit_block, first, block);
	func->builder->current_block = block;

	/* Create a new block after the last one we moved, to start fresh */
	return jit_insn_new_block(func);
}

/*@
 * @deftypefun int jit_insn_move_blocks_to_start (jit_function_t @var{func}, jit_label_t @var{from_label}, jit_label_t @var{to_label})
 * Move all of the blocks between @var{from_label} (inclusive) and
 * @var{to_label} (exclusive) to the start of the current function.
 * This is typically used to move initialization code to the head
 * of the function.
 * @end deftypefun
@*/
int jit_insn_move_blocks_to_start
	(jit_function_t func, jit_label_t from_label, jit_label_t to_label)
{
	jit_block_t init, first, last, block;

	/* Make sure that deferred stack pops are flushed */
	if(!jit_insn_flush_defer_pop(func, 0))
	{
		return 0;
	}

	/* Find the first block that needs to be moved */
	first = jit_block_from_label(func, from_label);
	if(!first)
	{
		return 0;
	}

	/* Find the last block that needs to be moved */
	last = jit_block_from_label(func, to_label);
	if(!last)
	{
		return 0;
	}

	/* Init block */
	init = func->builder->init_block;

	/* Sanity check -- the first block has to be after the init */
	for(block = init->next; block != first; block = block->next)
	{
		if (!block) {
			return 0;
		}
	}
	/* Sanity check -- the last block has to be after the first */
	for(block = first->next; block != last; block = block->next)
	{
		if (!block) {
			return 0;
		}
	}

	/* The last block is excluded from the blocks to move */
	block = last->prev;

	/* Update the init block pointer */
	func->builder->init_block = block;

	/* Move the blocks after the original init block */
	if(init->next != first)
	{
		_jit_block_detach(first, block);
		_jit_block_attach_after(init, first, block);
	}

	/* Done */
	return 1;
}

/*@
 * @deftypefun int jit_insn_mark_offset (jit_function_t @var{func}, jit_int @var{offset})
 * Mark the current position in @var{func} as corresponding to the
 * specified bytecode @var{offset}.  This value will be returned
 * by @code{jit_stack_trace_get_offset}, and is useful for associating
 * code positions with source line numbers.
 * @end deftypefun
@*/
int jit_insn_mark_offset(jit_function_t func, jit_int offset)
{
	jit_block_t block;
	jit_insn_t last;
	jit_value_t value;

	/* Ensure that we have a builder for this function */
	if(!_jit_function_ensure_builder(func))
	{
		return 0;
	}

	value = jit_value_create_nint_constant(func, jit_type_int, offset);
	if (!value)
	{
		return 0;
	}

	/* If the previous instruction is mark offset too
	   then just replace the offset value in place --
	   we are not interested in bytecodes that produce
	   no real code. */
	block = func->builder->current_block;
	last = _jit_block_get_last(block);
	if (last && last->opcode == JIT_OP_MARK_OFFSET)
	{
		last->value1 = value;
		return 1;
	}

	return create_unary_note(func, JIT_OP_MARK_OFFSET, value);
}

/* Documentation is in jit-debugger.c */
int jit_insn_mark_breakpoint_variable
	(jit_function_t func, jit_value_t data1, jit_value_t data2)
{
#if defined(JIT_BACKEND_INTERP)
	/* Use the "mark_breakpoint" instruction for the interpreter */
	if(!jit_insn_new_block(func))
	{
		return 0;
	}
	return create_note(func, JIT_OP_MARK_BREAKPOINT, data1, data2);
#else
	/* Insert a call to "_jit_debugger_hook" on native platforms */



( run in 0.717 second using v1.01-cache-2.11-cpan-e1769b4cff6 )