void jit_function::insn_push(const jit_value& value) { if(!jit_insn_push(func, value.raw())) { out_of_memory(); } }
/*@ * @deftypefun int _jit_create_call_setup_insns (jit_function_t @var{func}, jit_type_t @var{signature}, jit_value_t *@var{args}, unsigned int @var{num_args}, int @var{is_nested}, int @var{nested_level}, jit_value_t *@var{struct_return}, int @var{flags}) * Create instructions within @var{func} necessary to set up for a * function call to a function with the specified @var{signature}. * Use @code{jit_insn_push} to push values onto the system stack, * or @code{jit_insn_outgoing_reg} to copy values into call registers. * * If @var{is_nested} is non-zero, then it indicates that we are calling a * nested function within the current function's nested relationship tree. * The @var{nested_level} value will be -1 to call a child, zero to call a * sibling of @var{func}, 1 to call a sibling of the parent, 2 to call * a sibling of the grandparent, etc. The @code{jit_insn_setup_for_nested} * instruction should be used to create the nested function setup code. * * If the function returns a structure by pointer, then @var{struct_return} * must be set to a new local variable that will contain the returned * structure. Otherwise it should be set to NULL. * @end deftypefun @*/ int _jit_create_call_setup_insns (jit_function_t func, jit_type_t signature, jit_value_t *args, unsigned int num_args, int is_nested, int nested_level, jit_value_t *struct_return, int flags) { jit_type_t type; jit_type_t vtype; jit_value_t value; unsigned int arg_num; jit_nint offset; jit_nuint size; /* Regular or tail call? */ if((flags & JIT_CALL_TAIL) == 0) { /* Push all of the arguments in reverse order */ while(num_args > 0) { --num_args; type = jit_type_get_param(signature, num_args); type = jit_type_remove_tags(type); if(type->kind == JIT_TYPE_STRUCT || type->kind == JIT_TYPE_UNION) { /* If the value is a pointer, then we are pushing a structure argument by pointer rather than by local variable */ vtype = jit_type_normalize(jit_value_get_type(args[num_args])); if(vtype->kind <= JIT_TYPE_MAX_PRIMITIVE) { if(!jit_insn_push_ptr(func, args[num_args], type)) { return 0; } continue; } } if(!jit_insn_push(func, args[num_args])) { return 0; } } /* Do we need to add a structure return pointer argument? */ type = jit_type_get_return(signature); if(jit_type_return_via_pointer(type)) { value = jit_value_create(func, type); if(!value) { return 0; } *struct_return = value; value = jit_insn_address_of(func, value); if(!value) { return 0; } if(!jit_insn_push(func, value)) { return 0; } } else if((flags & JIT_CALL_NATIVE) != 0) { /* Native calls always return a return area pointer */ if(!jit_insn_push_return_area_ptr(func)) { return 0; } *struct_return = 0; } else { *struct_return = 0; } /* Do we need to add nested function scope information? */ if(is_nested) { if(!jit_insn_setup_for_nested(func, nested_level, -1)) { return 0; } } } else { /* Copy the arguments into our own parameter slots */ offset = -1; if(func->nested_parent) { offset -= 2; } type = jit_type_get_return(signature); if(jit_type_return_via_pointer(type)) { --offset; } for(arg_num = 0; arg_num < num_args; ++arg_num) { type = jit_type_get_param(signature, arg_num); value = jit_value_create(func, type); if(!value) { return 0; } if(!jit_insn_outgoing_frame_posn(func, value, offset)) { return 0; } type = jit_type_remove_tags(type); size = jit_type_get_size(type); offset -= (jit_nint)(JIT_NUM_ITEMS_IN_STRUCT(size)); if(type->kind == JIT_TYPE_STRUCT || type->kind == JIT_TYPE_UNION) { /* If the value is a pointer, then we are pushing a structure argument by pointer rather than by local variable */ vtype = jit_type_normalize(jit_value_get_type(args[arg_num])); if(vtype->kind <= JIT_TYPE_MAX_PRIMITIVE) { value = jit_insn_address_of(func, value); if(!value) { return 0; } if(!jit_insn_memcpy (func, value, args[arg_num], jit_value_create_nint_constant (func, jit_type_nint, (jit_nint)size))) { return 0; } continue; } } if(!jit_insn_store(func, value, args[arg_num])) { return 0; } } *struct_return = 0; } /* The call is ready to proceed */ return 1; }