Exemple #1
0
int _jit_create_call_return_insns
	(jit_function_t func, jit_type_t signature,
	 jit_value_t *args, unsigned int num_args,
	 jit_value_t return_value, int is_nested)
{
	jit_type_t return_type;
	int ptr_return;

	/* Bail out now if we don't need to worry about return values */
	return_type = jit_type_normalize(jit_type_get_return(signature));
	ptr_return = jit_type_return_via_pointer(return_type);
	if(!return_value || ptr_return)
	{
		return 0;
	}

	/* Structure values must be flushed into the frame, and
	   everything else ends up in a register */
	if(jit_type_is_struct(return_type) || jit_type_is_union(return_type))
	{
		if(!jit_insn_flush_struct(func, return_value))
		{
			return 0;
		}
	}
#ifdef JIT_ARM_HAS_FLOAT_REGS
	else if(return_type->kind == JIT_TYPE_FLOAT32 ||
			return_type->kind == JIT_TYPE_FLOAT64 ||
			return_type->kind == JIT_TYPE_NFLOAT)
	{
		if(!jit_insn_return_reg(func, return_value, 16 /* f0 */))
		{
			return 0;
		}
	}
#endif
	else if(return_type->kind != JIT_TYPE_VOID)
	{
		if(!jit_insn_return_reg(func, return_value, 0 /* r0 */))
		{
			return 0;
		}
	}

	/* Everything is back where it needs to be */
	return 1;
}
/*
 * Initialize the local value to 0.
 */
static int _ILJitLocalInit(ILJITCoder *coder, ILJitLocalSlot *slot)
{
	if((slot->flags & _IL_JIT_VALUE_INITIALIZED) == 0)
	{
		ILJitType type = jit_value_get_type(slot->value);

		if(!jit_type_is_struct(type))
		{
			int typeKind = jit_type_get_kind(type);
			ILJitValue constant = 0;

			if(_JIT_TYPEKIND_IS_FLOAT(typeKind))
			{
				if(!(constant = jit_value_create_nfloat_constant(coder->jitFunction,
															type,
															(jit_nfloat)0)))
				{
					return 0;
				}
				jit_insn_store(coder->jitFunction, slot->value, constant);
			}
			else
			{
				if(_JIT_TYPEKIND_IS_LONG(typeKind))
				{
					if(!(constant = jit_value_create_long_constant(coder->jitFunction,
															  type, (jit_long)0)))
					{
						return 0;
					}
					jit_insn_store(coder->jitFunction, slot->value, constant);
				}
				else
				{
					if(!(constant = jit_value_create_nint_constant(coder->jitFunction,
															  type, (jit_nint)0)))
					{
						return 0;
					}
					jit_insn_store(coder->jitFunction, slot->value, constant);
				}
			}
		}
		slot->flags |= _IL_JIT_VALUE_INITIALIZED;
	}
	return 1;
}
Exemple #3
0
/*@
 * @deftypefun jit_value_t jit_value_get_struct_pointer (jit_function_t @var{func})
 * Get the value that contains the structure return pointer for
 * a function.  If the function does not have a structure return pointer
 * (i.e. structures are returned in registers), then this returns NULL.
 * @end deftypefun
@*/
jit_value_t
jit_value_get_struct_pointer(jit_function_t func)
{
	jit_type_t type;
	jit_value_t value;

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

	type = jit_type_remove_tags(jit_type_get_return(func->signature));
	if(jit_type_is_struct(type) || jit_type_is_union(type))
	{
		if(jit_type_return_via_pointer(type))
		{
			if(!func->builder->struct_return)
			{
				type = jit_type_create_pointer(type, 1);
				if(!type)
				{
					return 0;
				}
				value = jit_value_create(func, type);
				func->builder->struct_return = value;
				if(value)
				{
					/* The value belongs to the entry block, no matter
					   where it happens to be created */
					value->block = func->builder->entry_block;
					value->is_parameter = 1;
				}
				jit_type_free(type);
			}
			return func->builder->struct_return;
		}
	}
	return 0;
}
Exemple #4
0
/*@
 * @deftypefun int _jit_create_call_return_insns (jit_function_t @var{func}, jit_type_t @var{signature}, jit_value_t *@var{args}, unsigned int @var{num_args}, jit_value_t @var{return_value}, int @var{is_nested})
 * Create instructions within @var{func} to clean up after a function call
 * and to place the function's result into @var{return_value}.
 * This should use @code{jit_insn_pop_stack} to pop values off the system
 * stack and @code{jit_insn_return_reg} to tell @code{libjit} which
 * register contains the return value.  In the case of a @code{void}
 * function, @var{return_value} will be NULL.
 *
 * Note: the argument values are passed again because it may not be possible
 * to determine how many bytes to pop from the stack from the @var{signature}
 * alone; especially if the called function is vararg.
 * @end deftypefun
@*/
int _jit_create_call_return_insns
	(jit_function_t func, jit_type_t signature,
	 jit_value_t *args, unsigned int num_args,
	 jit_value_t return_value, int is_nested)
{
	jit_nint pop_items;
	unsigned int size;
	jit_type_t return_type;
	int ptr_return;

	/* Calculate the number of items that we need to pop */
	pop_items = 0;
	while(num_args > 0)
	{
		--num_args;
		size = jit_type_get_size(jit_value_get_type(args[num_args]));
		pop_items += JIT_NUM_ITEMS_IN_STRUCT(size);
	}
	return_type = jit_type_get_return(signature);
	return_type = jit_type_remove_tags(return_type);
	ptr_return = jit_type_return_via_pointer(return_type);
	if(ptr_return)
	{
		++pop_items;
	}
	if(is_nested)
	{
		/* The interpreter needs two arguments for the parent frame info */
		pop_items += 2;
	}

	/* Pop the items from the system stack */
	if(pop_items > 0)
	{
		if(!jit_insn_pop_stack(func, pop_items))
		{
			return 0;
		}
	}

	/* Bail out now if we don't need to worry about return values */
	if(!return_value || ptr_return)
	{
		return 1;
	}

	/* Structure values must be flushed into the frame, and
	   everything else ends up in the top-most stack register */
	if(jit_type_is_struct(return_type) || jit_type_is_union(return_type))
	{
		if(!jit_insn_flush_struct(func, return_value))
		{
			return 0;
		}
	}
	else if(return_type->kind != JIT_TYPE_VOID)
	{
		if(!jit_insn_return_reg(func, return_value, 0))
		{
			return 0;
		}
	}

	/* Everything is back where it needs to be */
	return 1;
}
int _jit_create_call_return_insns
	(jit_function_t func, jit_type_t signature,
	 jit_value_t *args, unsigned int num_args,
	 jit_value_t return_value, int is_nested)
{
	jit_nint pop_bytes;
	unsigned int size;
	jit_type_t return_type;
	int ptr_return;

	/* Calculate the number of bytes that we need to pop */
	return_type = jit_type_normalize(jit_type_get_return(signature));
	ptr_return = jit_type_return_via_pointer(return_type);
#if JIT_APPLY_X86_FASTCALL == 1
	if(jit_type_get_abi(signature) == jit_abi_stdcall ||
        jit_type_get_abi(signature) == jit_abi_thiscall||
        jit_type_get_abi(signature) == jit_abi_fastcall)
	{
		/* STDCALL, THISCALL and FASTCALL functions pop their own arguments */
		pop_bytes = 0;
	}
	else
#endif
	{
		pop_bytes = 0;
		while(num_args > 0)
		{
			--num_args;
			size = jit_type_get_size(jit_value_get_type(args[num_args]));
			pop_bytes += ROUND_STACK(size);
		}
#if JIT_APPLY_X86_POP_STRUCT_RETURN == 1
		if(ptr_return && is_nested)
		{
			/* Note: we only need this for nested functions, because
			   regular functions will pop the structure return for us */
			pop_bytes += sizeof(void *);
		}
#else
		if(ptr_return)
		{
			pop_bytes += sizeof(void *);
		}
#endif
		if(is_nested)
		{
			pop_bytes += sizeof(void *);
		}
	}

	/* Pop the bytes from the system stack */
	if(pop_bytes > 0)
	{
		if(!jit_insn_defer_pop_stack(func, pop_bytes))
		{
			return 0;
		}
	}

	/* Bail out now if we don't need to worry about return values */
	if(!return_value || ptr_return)
	{
		return 1;
	}

	/* Structure values must be flushed into the frame, and
	   everything else ends up in a register */
	if(jit_type_is_struct(return_type) || jit_type_is_union(return_type))
	{
		if(!jit_insn_flush_struct(func, return_value))
		{
			return 0;
		}
	}
	else if(return_type == jit_type_float32 ||
			return_type == jit_type_float64 ||
            return_type == jit_type_nfloat  ||
            jit_type_get_kind(return_type) == JIT_TYPE_FLOAT32 ||
            jit_type_get_kind(return_type) == JIT_TYPE_FLOAT64 ||
            jit_type_get_kind(return_type) == JIT_TYPE_NFLOAT )
	{
		if(!jit_insn_return_reg(func, return_value, X86_REG_ST0))
		{
			return 0;
		}
	}
	else if(return_type->kind != JIT_TYPE_VOID)
	{
		if(!jit_insn_return_reg(func, return_value, X86_REG_EAX))
		{
			return 0;
		}
	}

	/* Everything is back where it needs to be */
	return 1;
}