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, create_call_setup_insns(jit_function_t func, jit_function_t callee,
jit_type_t signature, jit_type_t signature,
jit_value_t *args, unsigned int num_args, 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 *struct_return, int flags)
{ {
jit_value_t *new_args; 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 */ /* Let the back end do the work */
return _jit_create_call_setup_insns(func, signature, args, num_args, return _jit_create_call_setup_insns(func, signature, args, num_args,
is_nested, nesting_level, struct_return, is_nested, parent_frame, struct_return,
flags); flags);
} }
@ -5478,8 +5478,7 @@ jit_insn_call(jit_function_t func, const char *name, jit_function_t jit_func,
int flags) int flags)
{ {
int is_nested; int is_nested;
int nesting_level; jit_value_t parent_frame;
jit_function_t temp_func;
jit_value_t return_value; jit_value_t return_value;
jit_label_t entry_point; jit_label_t entry_point;
jit_label_t label_end; 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) if(jit_func->nested_parent)
{ {
is_nested = 1; is_nested = 1;
if(jit_func->nested_parent == func) parent_frame = jit_insn_get_parent_frame_pointer_of(func, jit_func);
{
/* We are calling one of our children */ if(!parent_frame)
nesting_level = -1;
}
else if(jit_func->nested_parent == func->nested_parent)
{
/* We are calling one of our direct siblings */
nesting_level = 0;
}
else
{ {
/* Search up to find the actual nesting level */ /* TODO should we return 0 instead? */
temp_func = func->nested_parent; jit_exception_builtin(JIT_RESULT_CALLED_NESTED);
nesting_level = 1;
while(temp_func != 0 && temp_func != jit_func)
{
++nesting_level;
temp_func = temp_func->nested_parent;
}
} }
} }
else else
{ {
is_nested = 0; is_nested = 0;
nesting_level = 0; parent_frame = 0;
} }
/* Convert the arguments to the actual parameter types */ /* 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 */ /* Create the instructions to push the parameters onto the stack */
if(!create_call_setup_insns(func, jit_func, signature, new_args, num_args, 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; 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}) * @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 * Retrieve the frame pointer of the parent of @var{target}. Returns NULL when
* when @var{target} is a sibling, an ancestor, or a sibling of one of the * @var{target} is not a sibling, an ancestor, or a sibling of one of the
* ancestors of @var{func}. * ancestors of @var{func}.
* Returns NULL if out of memory. * Returns NULL if out of memory.
* @end deftypefun * @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 * Create instructions within @var{func} necessary to set up for a
* function call to a function with the specified @var{signature}. * function call to a function with the specified @var{signature}.
* Use @code{jit_insn_push} to push values onto the system stack, * 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 * 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. * 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 * The @var{parent_frame} value will be a pointer to the start of the frame
* sibling of @var{func}, 1 to call a sibling of the parent, 2 to call * of the parent of the callee.
* 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} * 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 * 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 int _jit_create_call_setup_insns
(jit_function_t func, jit_type_t signature, (jit_function_t func, jit_type_t signature,
jit_value_t *args, unsigned int num_args, 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 type;
jit_type_t vtype; 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? */ /* Do we need to add a structure return pointer argument? */
type = jit_type_get_return(signature); type = jit_type_get_return(signature);
if(jit_type_return_via_pointer(type)) if(jit_type_return_via_pointer(type))
@ -462,15 +470,6 @@ int _jit_create_call_setup_insns
{ {
*struct_return = 0; *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 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); _jit_gen_fix_value(func->builder->setjmp_value);
x86_64_lea_membase_size(inst, X86_64_RDI, X86_64_RIP, 0, 8); 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 func->builder->setjmp_value->frame_offset
+ jit_jmp_catch_pc_offset, X86_64_RDI, 8); + 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)); ptr = _jit_gen_alloc(gen, sizeof(jit_nfloat));
jit_memcpy(ptr, &nfloat_value, sizeof(nfloat_value)); jit_memcpy(ptr, &nfloat_value, sizeof(nfloat_value));
offset = (jit_nint)ptr - offset = (jit_nint)ptr -
((jit_nint)inst + (xmm_reg > 7 ? 9 : 8)); ((jit_nint)inst + (xmm_reg > 7 ? 9 : 8));
if((offset >= jit_min_int) && (offset <= jit_max_int)) 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)) return_type))
{ {
/* It's an error so simply return insn */ /* It's an error so simply return insn */
return inst; return inst;
} }
size = jit_type_get_size(return_type); size = jit_type_get_size(return_type);
if(size <= 8) 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)) if(!_jit_classify_struct_return(&passing, &return_param, return_type))
{ {
/* It's an error so simply return insn */ /* It's an error so simply return insn */
return inst; return inst;
} }
return_param.value = value; return_param.value = value;
@ -3488,7 +3488,7 @@ _jit_setup_incoming_param(jit_function_t func, _jit_param_t *param,
{ {
if(size <= 4) if(size <= 4)
{ {
if(!(param->un.reg_info[1].value = if(!(param->un.reg_info[1].value =
jit_value_create(func, jit_type_int))) jit_value_create(func, jit_type_int)))
{ {
return 0; 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)) if(!_jit_classify_struct_return(&passing, &return_param, return_type))
{ {
/* It's an error so simply return insn */ /* It's an error so simply return insn */
return 0; return 0;
} }
if(return_param.arg_class == 1) if(return_param.arg_class == 1)
@ -3687,6 +3687,9 @@ _jit_create_entry_insns(jit_function_t func)
{ {
return 0; 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 */ /* 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_get_param(signature, current_param);
param_type = jit_type_normalize(param_type); param_type = jit_type_normalize(param_type);
if(!(_jit_classify_param(&passing, &(passing.params[current_param]), if(!(_jit_classify_param(&passing, &(passing.params[current_param]),
param_type))) 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 */ /* Now we flush the incoming structs passed in registers */
for(current_param = 0; current_param < num_args; current_param++) 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 int _jit_create_call_setup_insns
(jit_function_t func, jit_type_t signature, (jit_function_t func, jit_type_t signature,
jit_value_t *args, unsigned int num_args, 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); int abi = jit_type_get_abi(signature);
jit_type_t return_type; 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 */ /* Let the specific backend initialize it's part of the params */
_jit_init_args(abi, &passing); _jit_init_args(abi, &passing);
/* Determine how many parameters are going to end up in word registers, /* Determine if we need an extra hidden parameter for returning a
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
structure */ structure */
return_type = jit_type_get_return(signature); return_type = jit_type_get_return(signature);
if(jit_type_return_via_pointer(return_type)) if(jit_type_return_via_pointer(return_type))
@ -3830,6 +3830,20 @@ int _jit_create_call_setup_insns
return_ptr = 0; 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 */ /* Let the backend classify the parameters */
for(current_param = 0; current_param < num_args; current_param++) 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_get_param(signature, current_param);
param_type = jit_type_normalize(param_type); param_type = jit_type_normalize(param_type);
if(!(_jit_classify_param(&passing, &(passing.params[current_param]), if(!(_jit_classify_param(&passing, &(passing.params[current_param]),
param_type))) 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 */ /* Handle the structure return pointer if it's passed on the stack */
if(return_ptr) 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 */ /* Handle the structure return pointer if required */
if(return_ptr) 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 */ /* Add the structure return pointer if required */
if(return_ptr) 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 */ structure */
if(ptr_return) 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_get_param(signature, current_param);
param_type = jit_type_normalize(param_type); param_type = jit_type_normalize(param_type);
if(!(_jit_classify_param(&passing, &(passing.params[current_param]), if(!(_jit_classify_param(&passing, &(passing.params[current_param]),
param_type))) param_type)))
{ {

29
jit/jit-rules.c

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

Loading…
Cancel
Save