Alien-LibJIT

 view release on metacpan or  search on metacpan

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

						return 0;
					}
				}

				*plast = last;
				return insn;
			}

			/* Oops. This instruction modifies "value" and blocks
			   any previous address_of or add_relative instructions */
			if((insn->flags & JIT_INSN_DEST_IS_VALUE) == 0)
			{
				break;
			}
		}

		/* We are to check instructions that preceed the last one */
		last = 0;
	}
	return 0;
}

/*@
 * @deftypefun jit_value_t jit_insn_load_relative (jit_function_t @var{func}, jit_value_t @var{value}, jit_nint @var{offset}, jit_type_t @var{type})
 * Load a value of the specified @var{type} from the effective address
 * @code{(@var{value} + @var{offset})}, where @var{value} is a pointer.
 * @end deftypefun
@*/
jit_value_t jit_insn_load_relative
		(jit_function_t func, jit_value_t value,
		 jit_nint offset, jit_type_t type)
{
	jit_insn_iter_t iter;
	jit_insn_t insn;
	int last;

	if(!value)
	{
		return 0;
	}
	if(!_jit_function_ensure_builder(func))
	{
		return 0;
	}

	jit_insn_iter_init_last(&iter, func->builder->current_block);
	insn = find_base_insn(func, iter, value, &last);
	if(insn && insn->opcode == JIT_OP_ADD_RELATIVE)
	{
		/* We have a previous "add_relative" instruction for this
		   pointer. Adjust the current offset accordingly */
		offset += jit_value_get_nint_constant(insn->value2);
		value = insn->value1;
		insn = find_base_insn(func, iter, value, &last);
		last = 0;
	}
	if(insn && insn->opcode == JIT_OP_ADDRESS_OF && !last)
	{
		/* Shift the "address_of" instruction down, to make
		   it easier for the code generator to handle field
		   accesses within local and global variables */
		value = jit_insn_address_of(func, insn->value1);
		if(!value)
		{
			return 0;
		}
	}
	return apply_binary
		(func, _jit_load_opcode(JIT_OP_LOAD_RELATIVE_SBYTE, type, 0, 0), value,
		 jit_value_create_nint_constant(func, jit_type_nint, offset), type);
}

/*@
 * @deftypefun int jit_insn_store_relative (jit_function_t @var{func}, jit_value_t @var{dest}, jit_nint @var{offset}, jit_value_t @var{value})
 * Store @var{value} at the effective address @code{(@var{dest} + @var{offset})},
 * where @var{dest} is a pointer.
 * @end deftypefun
@*/
int jit_insn_store_relative
		(jit_function_t func, jit_value_t dest,
		 jit_nint offset, jit_value_t value)
{
	jit_insn_iter_t iter;
	jit_insn_t insn;
	int last;
	jit_value_t offset_value;

	if(!dest || !value)
	{
		return 0;
	}
	if(!_jit_function_ensure_builder(func))
	{
		return 0;
	}

	jit_insn_iter_init_last(&iter, func->builder->current_block);
	insn = find_base_insn(func, iter, dest, &last);
	if(insn && insn->opcode == JIT_OP_ADD_RELATIVE)
	{
		/* We have a previous "add_relative" instruction for this
		   pointer. Adjust the current offset accordingly */
		offset += jit_value_get_nint_constant(insn->value2);
		dest = insn->value1;
		insn = find_base_insn(func, iter, value, &last);
		last = 0;
	}
	if(insn && insn->opcode == JIT_OP_ADDRESS_OF && !last)
	{
		/* Shift the "address_of" instruction down, to make
		   it easier for the code generator to handle field
		   accesses within local and global variables */
		dest = jit_insn_address_of(func, insn->value1);
		if(!dest)
		{
			return 0;
		}
	}

	offset_value = jit_value_create_nint_constant(func, jit_type_nint, offset);
	if(!offset_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_STORE_RELATIVE_BYTE, 0, value->type);
	insn->flags = JIT_INSN_DEST_IS_VALUE;
	insn->dest = dest;
	insn->value1 = value;
	insn->value2 = offset_value;
	return 1;
}

/*@
 * @deftypefun jit_value_t jit_insn_add_relative (jit_function_t @var{func}, jit_value_t @var{value}, jit_nint @var{offset})
 * Add the constant @var{offset} to the specified pointer @var{value}.
 * This is functionally identical to calling @code{jit_insn_add}, but
 * the JIT can optimize the code better if it knows that the addition
 * is being used to perform a relative adjustment on a pointer.
 * In particular, multiple relative adjustments on the same pointer
 * can be collapsed into a single adjustment.
 * @end deftypefun
@*/
jit_value_t jit_insn_add_relative
		(jit_function_t func, jit_value_t value, jit_nint offset)
{
	jit_insn_iter_t iter;
	jit_insn_t insn;
	int last;

	if(!value)
	{
		return 0;
	}
	if(!_jit_function_ensure_builder(func))
	{
		return 0;
	}

	jit_insn_iter_init_last(&iter, func->builder->current_block);
	insn = find_base_insn(func, iter, value, &last);
	if(insn && insn->opcode == JIT_OP_ADD_RELATIVE)
	{
		/* We have a previous "add_relative" instruction for this
		   pointer. Adjust the current offset accordingly */
		offset += jit_value_get_nint_constant(insn->value2);



( run in 0.477 second using v1.01-cache-2.11-cpan-cdf2f3d4e48 )