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 )