Browse Source

automatically find and pass parent frame pointers when calling nested functions

when calling a nested function the function needs a pointer to the parent frame
to import values. With the new nested importing system the work of importing
values was taken away from the backends, so this commit takes away setting up
calls to nested functions from the backend. Instead this is done in
jit-rules.c (and architecture specific versions of jit-rule.c).
pull/15/head
Jakob Löw 7 years ago
parent
commit
25c88f5e1c
  1. 39
      jit/jit-insn.c
  2. 29
      jit/jit-rules-interp.c
  3. 103
      jit/jit-rules-x86-64.c
  4. 29
      jit/jit-rules.c
  5. 2
      jit/jit-rules.h

39
jit/jit-insn.c

@ -5330,7 +5330,7 @@ static int
create_call_setup_insns(jit_function_t func, jit_function_t callee,
jit_type_t signature,
jit_value_t *args, unsigned int num_args,
int is_nested, int nesting_level,
int is_nested, jit_value_t parent_frame,
jit_value_t *struct_return, int flags)
{
jit_value_t *new_args;
@ -5375,7 +5375,7 @@ create_call_setup_insns(jit_function_t func, jit_function_t callee,
/* Let the back end do the work */
return _jit_create_call_setup_insns(func, signature, args, num_args,
is_nested, nesting_level, struct_return,
is_nested, parent_frame, struct_return,
flags);
}
@ -5478,8 +5478,7 @@ jit_insn_call(jit_function_t func, const char *name, jit_function_t jit_func,
int flags)
{
int is_nested;
int nesting_level;
jit_function_t temp_func;
jit_value_t parent_frame;
jit_value_t return_value;
jit_label_t entry_point;
jit_label_t label_end;
@ -5515,32 +5514,18 @@ jit_insn_call(jit_function_t func, const char *name, jit_function_t jit_func,
if(jit_func->nested_parent)
{
is_nested = 1;
if(jit_func->nested_parent == func)
{
/* We are calling one of our children */
nesting_level = -1;
}
else if(jit_func->nested_parent == func->nested_parent)
{
/* We are calling one of our direct siblings */
nesting_level = 0;
}
else
parent_frame = jit_insn_get_parent_frame_pointer_of(func, jit_func);
if(!parent_frame)
{
/* Search up to find the actual nesting level */
temp_func = func->nested_parent;
nesting_level = 1;
while(temp_func != 0 && temp_func != jit_func)
{
++nesting_level;
temp_func = temp_func->nested_parent;
}
/* TODO should we return 0 instead? */
jit_exception_builtin(JIT_RESULT_CALLED_NESTED);
}
}
else
{
is_nested = 0;
nesting_level = 0;
parent_frame = 0;
}
/* Convert the arguments to the actual parameter types */
@ -5576,7 +5561,7 @@ jit_insn_call(jit_function_t func, const char *name, jit_function_t jit_func,
/* Create the instructions to push the parameters onto the stack */
if(!create_call_setup_insns(func, jit_func, signature, new_args, num_args,
is_nested, nesting_level, &return_value, flags))
is_nested, parent_frame, &return_value, flags))
{
return 0;
}
@ -6381,8 +6366,8 @@ find_frame_of(jit_function_t func, jit_function_t target,
/*@
* @deftypefun jit_value_t jit_insn_get_parent_frame_pointer_of (jit_function_t @var{func}, jit_function_t @var{target})
* Retrieve the frame pointer of the parent of @var{target}. This only works
* when @var{target} is a sibling, an ancestor, or a sibling of one of the
* Retrieve the frame pointer of the parent of @var{target}. Returns NULL when
* @var{target} is not a sibling, an ancestor, or a sibling of one of the
* ancestors of @var{func}.
* Returns NULL if out of memory.
* @end deftypefun

29
jit/jit-rules-interp.c

@ -370,7 +370,7 @@ int _jit_create_entry_insns(jit_function_t func)
}
/*@
* @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})
* @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}, jit_value_t @var{parent_frame}, 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,
@ -378,10 +378,8 @@ int _jit_create_entry_insns(jit_function_t func)
*
* 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.
* The @var{parent_frame} value will be a pointer to the start of the frame
* of the parent of the callee.
*
* 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
@ -391,7 +389,8 @@ int _jit_create_entry_insns(jit_function_t func)
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)
int is_nested, jit_value_t parent_frame,
jit_value_t *struct_return, int flags)
{
jit_type_t type;
jit_type_t vtype;
@ -429,6 +428,15 @@ int _jit_create_call_setup_insns
}
}
/* Do we need to add nested function scope information? */
if(is_nested)
{
if(!jit_insn_push(func, parent_frame))
{
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))
@ -462,15 +470,6 @@ int _jit_create_call_setup_insns
{
*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
{

103
jit/jit-rules-x86-64.c

@ -876,7 +876,7 @@ throw_builtin(unsigned char *inst, jit_function_t func, int type)
_jit_gen_fix_value(func->builder->setjmp_value);
x86_64_lea_membase_size(inst, X86_64_RDI, X86_64_RIP, 0, 8);
x86_64_mov_membase_reg_size(inst, X86_64_RBP,
x86_64_mov_membase_reg_size(inst, X86_64_RBP,
func->builder->setjmp_value->frame_offset
+ jit_jmp_catch_pc_offset, X86_64_RDI, 8);
}
@ -1925,7 +1925,7 @@ _jit_gen_load_value(jit_gencode_t gen, int reg, int other_reg, jit_value_t value
ptr = _jit_gen_alloc(gen, sizeof(jit_nfloat));
jit_memcpy(ptr, &nfloat_value, sizeof(nfloat_value));
offset = (jit_nint)ptr -
offset = (jit_nint)ptr -
((jit_nint)inst + (xmm_reg > 7 ? 9 : 8));
if((offset >= jit_min_int) && (offset <= jit_max_int))
{
@ -2952,9 +2952,9 @@ return_struct(unsigned char *inst, jit_function_t func, int ptr_reg)
return_type))
{
/* It's an error so simply return insn */
return inst;
return inst;
}
size = jit_type_get_size(return_type);
if(size <= 8)
{
@ -3072,7 +3072,7 @@ flush_return_struct(unsigned char *inst, jit_value_t value)
if(!_jit_classify_struct_return(&passing, &return_param, return_type))
{
/* It's an error so simply return insn */
return inst;
return inst;
}
return_param.value = value;
@ -3488,7 +3488,7 @@ _jit_setup_incoming_param(jit_function_t func, _jit_param_t *param,
{
if(size <= 4)
{
if(!(param->un.reg_info[1].value =
if(!(param->un.reg_info[1].value =
jit_value_create(func, jit_type_int)))
{
return 0;
@ -3597,7 +3597,7 @@ _jit_setup_return_value(jit_function_t func, jit_value_t return_value,
if(!_jit_classify_struct_return(&passing, &return_param, return_type))
{
/* It's an error so simply return insn */
return 0;
return 0;
}
if(return_param.arg_class == 1)
@ -3687,6 +3687,9 @@ _jit_create_entry_insns(jit_function_t func)
{
return 0;
}
nested_param.value = jit_value_create(func, jit_type_void_ptr);
jit_function_set_parent_frame(func, nested_param.value);
}
/* Allocate the structure return pointer */
@ -3709,7 +3712,7 @@ _jit_create_entry_insns(jit_function_t func)
param_type = jit_type_get_param(signature, current_param);
param_type = jit_type_normalize(param_type);
if(!(_jit_classify_param(&passing, &(passing.params[current_param]),
param_type)))
{
@ -3744,6 +3747,14 @@ _jit_create_entry_insns(jit_function_t func)
}
}
if(func->nested_parent)
{
if(!_jit_setup_incoming_param(func, &nested_param, jit_type_void_ptr))
{
return 0;
}
}
/* Now we flush the incoming structs passed in registers */
for(current_param = 0; current_param < num_args; current_param++)
{
@ -3766,7 +3777,8 @@ _jit_create_entry_insns(jit_function_t func)
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 nesting_level, jit_value_t *struct_return, int flags)
int is_nested, jit_value_t parent_frame,
jit_value_t *struct_return, int flags)
{
int abi = jit_type_get_abi(signature);
jit_type_t return_type;
@ -3788,19 +3800,7 @@ int _jit_create_call_setup_insns
/* Let the specific backend initialize it's part of the params */
_jit_init_args(abi, &passing);
/* Determine how many parameters are going to end up in word registers,
and compute the largest stack size needed to pass stack parameters */
if(is_nested)
{
jit_memset(&nested_param, 0, sizeof(_jit_param_t));
if(!(_jit_classify_param(&passing, &nested_param,
jit_type_void_ptr)))
{
return 0;
}
}
/* Determine if we need an extra hidden parameter for returning a
/* Determine if we need an extra hidden parameter for returning a
structure */
return_type = jit_type_get_return(signature);
if(jit_type_return_via_pointer(return_type))
@ -3830,6 +3830,20 @@ int _jit_create_call_setup_insns
return_ptr = 0;
}
/* Determine how many parameters are going to end up in word registers,
and compute the largest stack size needed to pass stack parameters */
if(is_nested)
{
jit_memset(&nested_param, 0, sizeof(_jit_param_t));
if(!(_jit_classify_param(&passing, &nested_param,
jit_type_void_ptr)))
{
return 0;
}
nested_param.value = parent_frame;
}
/* Let the backend classify the parameters */
for(current_param = 0; current_param < num_args; current_param++)
{
@ -3837,7 +3851,7 @@ int _jit_create_call_setup_insns
param_type = jit_type_get_param(signature, current_param);
param_type = jit_type_normalize(param_type);
if(!(_jit_classify_param(&passing, &(passing.params[current_param]),
param_type)))
{
@ -3887,6 +3901,19 @@ int _jit_create_call_setup_insns
}
}
/* Handle the parent's frame pointer if it's passed on the stack */
if(is_nested)
{
if(nested_param.arg_class == JIT_ARG_CLASS_STACK)
{
if(!_jit_setup_outgoing_param(func, &nested_param,
jit_type_void_ptr))
{
return 0;
}
}
}
/* Handle the structure return pointer if it's passed on the stack */
if(return_ptr)
{
@ -3918,6 +3945,19 @@ int _jit_create_call_setup_insns
}
}
/* Handle the parent's frame pointer if required */
if(is_nested)
{
if(nested_param.arg_class != JIT_ARG_CLASS_STACK)
{
if(!_jit_setup_reg_param(func, &nested_param,
jit_type_void_ptr))
{
return 0;
}
}
}
/* Handle the structure return pointer if required */
if(return_ptr)
{
@ -3949,6 +3989,19 @@ int _jit_create_call_setup_insns
}
}
/* Handle the parent's frame pointer if required */
if(is_nested)
{
if(nested_param.arg_class != JIT_ARG_CLASS_STACK)
{
if(!_jit_setup_outgoing_param(func, &nested_param,
jit_type_void_ptr))
{
return 0;
}
}
}
/* Add the structure return pointer if required */
if(return_ptr)
{
@ -4006,7 +4059,7 @@ _jit_create_call_return_insns(jit_function_t func, jit_type_t signature,
}
}
/* Determine if we need an extra hidden parameter for returning a
/* Determine if we need an extra hidden parameter for returning a
structure */
if(ptr_return)
{
@ -4025,7 +4078,7 @@ _jit_create_call_return_insns(jit_function_t func, jit_type_t signature,
param_type = jit_type_get_param(signature, current_param);
param_type = jit_type_normalize(param_type);
if(!(_jit_classify_param(&passing, &(passing.params[current_param]),
param_type)))
{

29
jit/jit-rules.c

@ -472,7 +472,7 @@ static int alloc_outgoing_word
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 nesting_level, jit_value_t *struct_return, int flags)
int is_nested, jit_value_t parent_frame, jit_value_t *struct_return, int flags)
{
jit_type_t type;
jit_value_t value;
@ -505,10 +505,6 @@ int _jit_create_call_setup_insns
/* Determine how many parameters are going to end up in word registers,
and compute the largest stack size needed to pass stack parameters */
if(is_nested)
{
need_outgoing_word(&passing);
}
type = jit_type_get_return(signature);
if(jit_type_return_via_pointer(type))
{
@ -530,6 +526,10 @@ int _jit_create_call_setup_insns
*struct_return = 0;
return_ptr = 0;
}
if(is_nested)
{
need_outgoing_word(&passing);
}
partial = 0;
for(param = 0; param < num_args; ++param)
{
@ -690,12 +690,12 @@ int _jit_create_call_setup_insns
}
}
/* Add the structure return pointer if required */
if(return_ptr)
/* Add nested scope information if required */
if(is_nested)
{
if(passing.index > 0)
{
if(!alloc_outgoing_word(func, &passing, return_ptr))
if(!alloc_outgoing_word(func, &passing, parent_frame))
{
return 0;
}
@ -703,28 +703,27 @@ int _jit_create_call_setup_insns
else
{
if(!push_param
(func, &passing, return_ptr, jit_type_void_ptr))
(func, &passing, parent_frame, jit_type_void_ptr))
{
return 0;
}
}
}
/* Add nested scope information if required */
if(is_nested)
/* Add the structure return pointer if required */
if(return_ptr)
{
if(passing.index > 0)
{
--(passing.index);
if(!jit_insn_setup_for_nested
(func, nesting_level, passing.word_regs[passing.index]))
if(!alloc_outgoing_word(func, &passing, return_ptr))
{
return 0;
}
}
else
{
if(!jit_insn_setup_for_nested(func, nesting_level, -1))
if(!push_param
(func, &passing, return_ptr, jit_type_void_ptr))
{
return 0;
}

2
jit/jit-rules.h

@ -212,7 +212,7 @@ int _jit_create_entry_insns(jit_function_t func);
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 nesting_level, jit_value_t *struct_return, int flags);
int is_nested, jit_value_t parent_frame, jit_value_t *struct_return, int flags);
int _jit_setup_indirect_pointer(jit_function_t func, jit_value_t value);
int _jit_create_call_return_insns
(jit_function_t func, jit_type_t signature,

Loading…
Cancel
Save