Alien-LibJIT

 view release on metacpan or  search on metacpan

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

 * @deftypefun void jit_insn_store (jit_function_t @var{func}, jit_value_t @var{dest}, jit_value_t @var{value})
 * Store the contents of @var{value} at the location referred to by
 * @var{dest}.  The @var{dest} should be a @code{jit_value_t} representing a
 * local variable or temporary.  Use @code{jit_insn_store_relative} to store
 * to a location referred to by a pointer.
 * @end deftypefun
@*/
int jit_insn_store(jit_function_t func, jit_value_t dest, jit_value_t value)
{
	jit_insn_t insn;
	if(!dest || !value)
	{
		return 0;
	}
	if(!_jit_function_ensure_builder(func))
	{
		return 0;
	}
	value = jit_insn_convert(func, value, dest->type, 0);
	if(!value)
	{
		return 0;
	}
	insn = _jit_block_add_insn(func->builder->current_block);
	if(!insn)
	{
		return 0;
	}
	jit_value_ref(func, dest);
	jit_value_ref(func, value);
	insn->opcode = (short)_jit_store_opcode
		(JIT_OP_COPY_INT, JIT_OP_COPY_STORE_BYTE, dest->type);
	insn->dest = dest;
	insn->value1 = value;
	return 1;
}

/*
 * Scan back through the current block, looking for an address instruction that
 * involves "value" as its destination. Returns NULL if no such instruction was
 * found, or it is blocked by a later use of "value".
 *
 * The instruction found may then be combined into a new single instruction with
 * the following "load_relative", "store_relative", or another "relative_add".
 *
 * For instance, consider the code like this:
 *
 * i) y = address_of(x)
 * ...
 * j) z = add_relative(y, a)
 *
 * Let's suppose that we need to add a "store_realtive(z, b, v)" instruction.
 * The "find_base_insn()" call will return the instruction "j" and we will be
 * able to emit the instruction "store_relative(y, a + b, v)" instead. If "z"
 * is not used elsewhere then "j" will be optimized away by the dead code
 * elimination pass.
 *
 * Repetitive use of this procedure for a chain of "add_relative" instructions
 * converts it into a series of indpenedent instructions each using the very
 * first address in the chain as its base. Therefore regardless of the initial
 * chain length it is always enough to make single "find_base_insn()" call to
 * get the base address of the entire chain (think induction).
 *
 * Note that in this situation the second "find_base_insn()" call will return
 * the instruction "i" that obtains the base address as the address of a local
 * frame variable. This instruction is a candidate for being moved down to
 * where the "load_relative" or "store_relative" occurs. This might make it
 * easier for the code generator to handle field accesses whitin local
 * variables.
 *
 * The "plast" argument indicates if the found instruction is already the last
 * one, so there is no need to move it down.
 */
static jit_insn_t
find_base_insn(
	jit_function_t func,
	jit_insn_iter_t iter,
	jit_value_t value,
	int *plast)
{
	int last;
	jit_insn_t insn;
	jit_insn_iter_t iter2;
	jit_insn_t insn2;

	/* The "value" could be vulnerable to aliasing effects so we cannot
	   optimize it */
	if(value->is_addressable || value->is_volatile)
	{
		return 0;
	}

	/* We are about to check the last instruction before the current one */
	last = 1;

	/* Iterate back through the block looking for a suitable instruction */
	while((insn = jit_insn_iter_previous(&iter)) != 0)
	{
		/* This instruction uses "value" in some way */
		if(insn->dest == value)
		{
			/* This is the instruction we were looking for */
			if(insn->opcode == JIT_OP_ADDRESS_OF)
			{
				*plast = last;
				return insn;
			}
			if(insn->opcode == JIT_OP_ADD_RELATIVE)
			{
				value = insn->value1;
				if(value->is_addressable || value->is_volatile)
				{
					return 0;
				}

				/* Scan forwards to ensure that "insn->value1"
				   is not modified anywhere in the instructions
				   that follow */
				iter2 = iter;
				jit_insn_iter_next(&iter2);
				while((insn2 = jit_insn_iter_next(&iter2)) != 0)



( run in 0.326 second using v1.01-cache-2.11-cpan-1edf4fed603 )