void jit_function::insn_flush_struct(const jit_value& value) { if(!jit_insn_flush_struct(func, value.raw())) { out_of_memory(); } }
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; }
/*@ * @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; }