@@ -857,17 +857,6 @@ static jit_value_t irgen_get_arg(jit_irgen_t *g, int op, int arg)
857857 return irgen_get_value (g , vcode_get_arg (op , arg ));
858858}
859859
860- static jit_reg_t irgen_as_reg (jit_irgen_t * g , jit_value_t value )
861- {
862- if (value .kind == JIT_VALUE_REG )
863- return value .reg ;
864- else {
865- jit_reg_t r = irgen_alloc_reg (g );
866- j_mov (g , r , value );
867- return r ;
868- }
869- }
870-
871860static jit_value_t irgen_lea (jit_irgen_t * g , jit_value_t addr )
872861{
873862 switch (addr .kind ) {
@@ -887,6 +876,24 @@ static jit_value_t irgen_lea(jit_irgen_t *g, jit_value_t addr)
887876 }
888877}
889878
879+ static jit_reg_t irgen_as_reg (jit_irgen_t * g , jit_value_t value )
880+ {
881+ switch (value .kind ) {
882+ case JIT_VALUE_REG :
883+ return value .reg ;
884+ case JIT_ADDR_REG :
885+ case JIT_ADDR_CPOOL :
886+ case JIT_ADDR_ABS :
887+ return jit_value_as_reg (irgen_lea (g , value ));
888+ default :
889+ {
890+ jit_reg_t r = irgen_alloc_reg (g );
891+ j_mov (g , r , value );
892+ return r ;
893+ }
894+ }
895+ }
896+
890897static jit_value_t irgen_is_scalar (jit_irgen_t * g , int op , int arg )
891898{
892899 const vtype_kind_t kind = vcode_reg_kind (vcode_get_arg (op , arg ));
@@ -1189,12 +1196,33 @@ static void irgen_send_args(jit_irgen_t *g, int op, int first)
11891196{
11901197 const int nargs = vcode_count_args (op );
11911198
1199+ jit_value_t spill = { .kind = JIT_VALUE_INVALID };
1200+ int32_t spilloff = 0 ;
1201+
11921202 for (int i = 0 , pslot = first ; i < nargs ; i ++ ) {
11931203 vcode_reg_t vreg = vcode_get_arg (op , i );
11941204 int slots = irgen_slots_for_type (vcode_reg_type (vreg ));
1195- if (unlikely (pslot + slots >= JIT_MAX_ARGS ))
1196- fatal ("call to %s requires more than the maximum supported "
1197- "%d arguments" , istr (vcode_get_func (op )), JIT_MAX_ARGS );
1205+
1206+ if (pslot + slots >= JIT_MAX_ARGS - 1 ) {
1207+ // Large number of arguments spill to the heap
1208+ if (spill .kind == JIT_VALUE_INVALID ) {
1209+ size_t size = slots * sizeof (jit_scalar_t );
1210+ for (int j = i + 1 ; j < nargs ; j ++ ) {
1211+ vcode_type_t vtype = vcode_reg_type (vcode_get_arg (op , j ));
1212+ size += irgen_slots_for_type (vtype ) * sizeof (jit_scalar_t );
1213+ }
1214+
1215+ spill = macro_lalloc (g , jit_value_from_int64 (size ));
1216+ j_send (g , JIT_MAX_ARGS - 1 , spill );
1217+ pslot = JIT_MAX_ARGS ;
1218+ }
1219+
1220+ jit_reg_t base = irgen_as_reg (g , irgen_get_value (g , vreg ));
1221+ for (int j = 0 ; j < slots ; j ++ , spilloff += sizeof (jit_scalar_t )) {
1222+ jit_value_t ptr = jit_addr_from_value (spill , spilloff );
1223+ j_store (g , JIT_SZ_64 , jit_value_from_reg (base + j ), ptr );
1224+ }
1225+ }
11981226 else if (slots > 1 ) {
11991227 jit_reg_t base = jit_value_as_reg (irgen_get_value (g , vreg ));
12001228 for (int j = 0 ; j < slots ; j ++ )
@@ -3480,6 +3508,11 @@ static void irgen_op_bind_foreign(jit_irgen_t *g, int op)
34803508 const int nparams = vcode_count_params ();
34813509 for (int i = 0 ; i < nparams ; i ++ ) {
34823510 const int slots = irgen_slots_for_type (vcode_param_type (i ));
3511+ if (unlikely (pslot + slots >= JIT_MAX_ARGS ))
3512+ fatal ("foreign subprogram %s requires more than the maximum supported "
3513+ "%d arguments" , istr (vcode_unit_name (g -> func -> unit )),
3514+ JIT_MAX_ARGS );
3515+
34833516 jit_value_t p = irgen_get_value (g , vcode_param_reg (i ));
34843517 j_send (g , pslot ++ , p );
34853518 for (int j = 1 ; j < slots ; j ++ )
@@ -4007,19 +4040,36 @@ static void irgen_params(jit_irgen_t *g, int first)
40074040 types [first ] = FFI_POINTER ;
40084041 types [0 ] = FFI_VOID ;
40094042
4043+ jit_value_t spill = { .kind = JIT_VALUE_INVALID };
4044+ int32_t spilloff = 0 ;
4045+
40104046 const int nparams = vcode_count_params ();
40114047 for (int i = 0 , pslot = first ; i < nparams ; i ++ ) {
40124048 vcode_reg_t preg = vcode_param_reg (i );
40134049 vcode_type_t vtype = vcode_param_type (i );
40144050 int slots = irgen_slots_for_type (vtype );
40154051
4016- if (unlikely (pslot + slots >= JIT_MAX_ARGS ))
4017- fatal ("%s requires more than the maximum supported %d arguments" ,
4018- istr (g -> func -> name ), JIT_MAX_ARGS );
4052+ if (pslot + slots >= JIT_MAX_ARGS - 1 ) {
4053+ // Large number of arguments spill to the heap
4054+ if (spill .kind == JIT_VALUE_INVALID ) {
4055+ spill = j_recv (g , JIT_MAX_ARGS - 1 );
4056+ pslot = JIT_MAX_ARGS ;
4057+ }
40194058
4020- g -> map [preg ] = j_recv (g , pslot ++ );
4021- for (int i = 1 ; i < slots ; i ++ )
4022- j_recv (g , pslot ++ ); // Must be contiguous registers
4059+ jit_value_t ptr = jit_addr_from_value (spill , spilloff );
4060+ g -> map [preg ] = j_load (g , JIT_SZ_64 , ptr );
4061+ spilloff += sizeof (jit_scalar_t );
4062+
4063+ for (int i = 1 ; i < slots ; i ++ , spilloff += sizeof (jit_scalar_t )) {
4064+ jit_value_t ptr = jit_addr_from_value (spill , spilloff );
4065+ j_load (g , JIT_SZ_64 , ptr ); // Must be contiguous registers
4066+ }
4067+ }
4068+ else {
4069+ g -> map [preg ] = j_recv (g , pslot ++ );
4070+ for (int i = 1 ; i < slots ; i ++ )
4071+ j_recv (g , pslot ++ ); // Must be contiguous registers
4072+ }
40234073
40244074 if (i + first + 1 < ARRAY_LEN (types ))
40254075 types [i + first + 1 ] = irgen_ffi_type (vtype );
@@ -4180,10 +4230,7 @@ void jit_irgen(jit_func_t *f)
41804230 irgen_bind_label (g , cont );
41814231 }
41824232
4183- const int first_param = irgen_is_procedure (g ) || has_jump_table ? 1 : 0 ;
4184- if (has_params )
4185- irgen_params (g , first_param );
4186- else if (kind == VCODE_UNIT_PROCESS ) {
4233+ if (kind == VCODE_UNIT_PROCESS ) {
41874234 const ffi_type_t types [] = { FFI_POINTER , FFI_POINTER , FFI_POINTER };
41884235 g -> func -> spec = ffi_spec_new (types , ARRAY_LEN (types ));
41894236 }
@@ -4208,6 +4255,10 @@ void jit_irgen(jit_func_t *f)
42084255 if (has_jump_table )
42094256 irgen_jump_table (g );
42104257
4258+ const int first_param = irgen_is_procedure (g ) || has_jump_table ? 1 : 0 ;
4259+ if (has_params )
4260+ irgen_params (g , first_param );
4261+
42114262 irgen_locals (g );
42124263
42134264 if (g -> stateless ) {
0 commit comments