From 34f546027fa5f3761e7c343f55a2aaa63184671c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Kochma=C5=84ski?= Date: Wed, 30 Apr 2025 15:14:26 +0200 Subject: [PATCH] compiler: factor the local entry index into a function c_lcl_idx computes the location of the entry in the locals env. It does traverse the list again, so it adds a little overhead, but this will allow us to customize it later to compute a location from the bottom. --- src/c/compiler.d | 84 +++++++++++++++++++++++------------------------- 1 file changed, 40 insertions(+), 44 deletions(-) diff --git a/src/c/compiler.d b/src/c/compiler.d index a30ca3e82..95b0e53d3 100644 --- a/src/c/compiler.d +++ b/src/c/compiler.d @@ -725,25 +725,51 @@ c_mac_ref(cl_env_ptr env, cl_object name) } end_loop_for_on_unsafe(l); } +/* Computes the local index from the function boundary. */ +static cl_fixnum +c_lcl_idx(cl_env_ptr env, cl_object entry) +{ + cl_fixnum n = 0, i = -1; + const cl_compiler_ptr c_env = env->c_env; + cl_object l = c_env->variables; + loop_for_on_unsafe(l) { + cl_object record = ECL_CONS_CAR(l), type; + if (record == @'si::function-boundary') { + break; + } + if(ECL_ATOM(record)) + continue; + if(record == entry) { + i = n; + continue; + } + type = pop(&record); + if (type == @':block' || type == @':function' || type == @':tag' + /* type == @'variable' && Null(specialp) */ + || Null(pop(&record))) { + n++; + } + } end_loop_for_on_unsafe(l); + if (i<0) ecl_miscompilation_error(); + return i; + /* return n-i; */ +} + /* This function is called after we compile lambda in the parent's environment. Its responsibility is to propagate closures. */ static struct cl_compiler_ref c_any_ref(cl_env_ptr env, cl_object entry) { - cl_fixnum n = 0; int function_boundary_crossed = 0; struct cl_compiler_ref output = { ECL_CMPREF_UNDEFINED }; const cl_compiler_ptr c_env = env->c_env; cl_object l = c_env->variables; loop_for_on_unsafe(l) { - cl_object record = ECL_CONS_CAR(l), reg, type, other; + cl_object record = ECL_CONS_CAR(l); if (record == @'si::function-boundary') function_boundary_crossed++; if(ECL_ATOM(record)) continue; - reg = record; - type = pop(®); - other = pop(®); if(record == entry) { if (function_boundary_crossed) { c_env->function_boundary_crossed = 1; @@ -751,15 +777,11 @@ c_any_ref(cl_env_ptr env, cl_object entry) output.index = c_register_captured(env, record); } else { output.place = ECL_CMPREF_LOCAL; - output.index = n; + output.index = c_lcl_idx(env, record); } output.entry = record; return output; } - if (type == @':block' || type == @':function'|| type == @':tag' - || Null(other)) { - n++; - } } end_loop_for_on_unsafe(l); return output; } @@ -767,7 +789,6 @@ c_any_ref(cl_env_ptr env, cl_object entry) static struct cl_compiler_ref c_tag_ref(cl_env_ptr env, cl_object the_tag) { - cl_fixnum n = 0; cl_object l, reg; int function_boundary_crossed = 0; struct cl_compiler_ref output = { ECL_CMPREF_UNDEFINED }; @@ -792,18 +813,12 @@ c_tag_ref(cl_env_ptr env, cl_object the_tag) output.index = c_register_captured(env, record); } else { output.place = ECL_CMPREF_LOCAL; - output.index = n; + output.index = c_lcl_idx(env, record); } output.entry = record; output.label = ecl_fixnum(ECL_CONS_CDR(label)); return output; } - n++; - } else if (type == @':block' || type == @':function' || Null(all_tags)) { - /* INV Null(all_tags) implies lexical variable -- Null(specialp). */ - n++; - } else { - /* We are counting only locals and ignore specials, declarations, etc. */ } } return output; @@ -812,7 +827,6 @@ c_tag_ref(cl_env_ptr env, cl_object the_tag) static struct cl_compiler_ref c_blk_ref(cl_env_ptr env, cl_object the_tag) { - cl_fixnum n = 0; cl_object l, reg; int function_boundary_crossed = 0; struct cl_compiler_ref output = { ECL_CMPREF_UNDEFINED }; @@ -836,17 +850,11 @@ c_blk_ref(cl_env_ptr env, cl_object the_tag) output.index = c_register_captured(env, record); } else { output.place = ECL_CMPREF_LOCAL; - output.index = n; + output.index = c_lcl_idx(env, record); } output.entry = record; return output; } - n++; - } else if (type == @':tag' || type == @':function' || Null(name)) { - /* INV Null(name) implies lexical variable -- Null(specialp). */ - n++; - } else { - /* We are counting only locals and ignore specials, declarations, etc. */ } } return output; @@ -855,7 +863,6 @@ c_blk_ref(cl_env_ptr env, cl_object the_tag) static struct cl_compiler_ref c_fun_ref(cl_env_ptr env, cl_object the_tag) { - cl_fixnum n = 0; cl_object l, reg; int function_boundary_crossed = 0; struct cl_compiler_ref output = { ECL_CMPREF_UNDEFINED }; @@ -880,17 +887,11 @@ c_fun_ref(cl_env_ptr env, cl_object the_tag) output.index = c_register_captured(env, record); } else { output.place = ECL_CMPREF_LOCAL; - output.index = n; + output.index = c_lcl_idx(env, record); } output.entry = record; return output; } - n++; - } else if (type == @':tag' || type == @':block' || Null(name)) { - /* INV Null(name) implies lexical variable -- Null(specialp). */ - n++; - } else { - /* We are counting only locals and ignore specials, declarations, etc. */ } } return output; @@ -903,7 +904,6 @@ ecl_def_ct_base_string(undefined_variable, static struct cl_compiler_ref c_var_ref(cl_env_ptr env, cl_object var, bool allow_sym_mac, bool ensure_def) { - cl_fixnum n = 0; cl_object l, reg; int function_boundary_crossed = 0; struct cl_compiler_ref output; @@ -919,13 +919,9 @@ c_var_ref(cl_env_ptr env, cl_object var, bool allow_sym_mac, bool ensure_def) reg = record; type = pop(®); special = pop(®); - if (type == @':block' || type == @':tag' || type == @':function') { - n++; - } else if (type == @':declare') { - /* Ignored */ - } else if (type != var) { - /* Symbol not yet found. Only count locals. */ - if (Null(special)) n++; + if (type == @':block' || type == @':tag' || type == @':function' + || type == @':declare' || type != var) { + continue; } else if (Null(special)) { if (function_boundary_crossed) { c_env->function_boundary_crossed = 1; @@ -933,7 +929,7 @@ c_var_ref(cl_env_ptr env, cl_object var, bool allow_sym_mac, bool ensure_def) output.index = c_register_captured(env, record); } else { output.place = ECL_CMPREF_LOCAL; - output.index = n; + output.index = c_lcl_idx(env, record); } output.entry = record; output.label = ECL_CMPVAR_LEXICAL; @@ -3618,7 +3614,7 @@ ecl_make_lambda(cl_env_ptr env, cl_object name, cl_object lambda) { if (new_c_env->function_boundary_crossed) { cl_object p = new_c_env->captured, flex, entry, macro_entry; struct cl_compiler_ref ref; - int i, n, index; + int i, n; n = p->vector.fillp; flex = si_make_vector(ECL_T, ecl_make_fixnum(n), ECL_NIL, ECL_NIL, ECL_NIL, ECL_NIL);