From: DeaDDooMER Date: Wed, 9 Aug 2017 12:34:55 +0000 (+0300) Subject: JVM: Реализован доступ к локальным переменным ровнем выше из локальных процедур X-Git-Url: http://deadsoftware.ru/gitweb?p=dsw-obn.git;a=commitdiff_plain;h=8b545fd0349be12160b9f50c1f4b6f072eac436f JVM: Реализован доступ к локальным переменным ровнем выше из локальных процедур --- diff --git a/src/backends/jvm/generator-jvm-abi.c b/src/backends/jvm/generator-jvm-abi.c index 0db2cc8..a750b92 100644 --- a/src/backends/jvm/generator-jvm-abi.c +++ b/src/backends/jvm/generator-jvm-abi.c @@ -60,18 +60,18 @@ jvm_generate_ldst_prepare(gen_proc_t * p, gen_var_t * v) break; case JVM_STORAGE_FRAME: case JVM_STORAGE_FRAME_PARAM: - jvm_generate_load(p, p -> frame_v); + jvm_generate(p, 0, 1, "aload %i", p -> reg_frame[v -> level]); break; case JVM_STORAGE_FRAME_VAR: case JVM_STORAGE_FRAME_PARAM_VAR: - jvm_generate_load(p, p -> frame_v); + jvm_generate(p, 0, 1, "aload %i", p -> reg_frame[v -> level]); jvm_generate(p, 1, 1, "getfield %s [%s", full_name, desc); jvm_generate(p, 0, 1, "iconst_0"); break; case JVM_STORAGE_FRAME_PARAM_VARPTR: - jvm_generate_load(p, p -> frame_v); + jvm_generate(p, 0, 1, "aload %i", p -> reg_frame[v -> level]); jvm_generate(p, 1, 1, "getfield %s [%s", full_name, desc); - jvm_generate_load(p, p -> frame_v); + jvm_generate(p, 0, 1, "aload %i", p -> reg_frame[v -> level]); jvm_generate(p, 1, 1, "getfield %s$offset I", full_name); break; default: @@ -203,6 +203,7 @@ jvm_create_function_var(gen_proc_t * p, enum gen_storage storage, char * name, g v -> name = new_string(name); v -> type = t; v -> p = p; + v -> level = p -> level; switch(storage) { @@ -250,6 +251,7 @@ jvm_create_function_temp_var(gen_proc_t * p, gen_type_t * t) v -> name = new_string("$TEMP_%i$", v -> reg); v -> type = t; v -> p = p; + v -> level = p -> level; return v; } @@ -357,11 +359,11 @@ jvm_generate_var_initialization(gen_proc_t * p, gen_var_t * v) } else if(v -> storage == JVM_STORAGE_FRAME_PARAM_VARPTR) { - jvm_generate_load(p, p -> frame_v); + jvm_generate(p, 0, 1, "aload %i", p -> reg_frame[v -> level]); jvm_generate(p, 0, 1, "aload %i", v -> reg); jvm_generate(p, 1, 0, "putfield %s [%s", v -> full_name, v -> type -> desc); - jvm_generate_load(p, p -> frame_v); + jvm_generate(p, 0, 1, "aload %i", p -> reg_frame[v -> level]); jvm_generate(p, 0, 1, "iload %i", v -> reg + 1); jvm_generate(p, 1, 0, "putfield %s$offset I", v -> full_name); } @@ -425,15 +427,18 @@ jvm_generate_frame_class(oberon_object_t * proc) if(v -> storage == JVM_STORAGE_FRAME || v -> storage == JVM_STORAGE_FRAME_PARAM) { + fprintf(fp, "; LEVEL %i\n", v -> level); fprintf(fp, ".field public %s %s\n\n", v -> name, v -> type -> desc); } else if(v -> storage == JVM_STORAGE_FRAME_VAR || v -> storage == JVM_STORAGE_FRAME_PARAM_VAR) { + fprintf(fp, "; LEVEL %i\n", v -> level); fprintf(fp, ".field public %s [%s\n\n", v -> name, v -> type -> desc); } else if(v -> storage == JVM_STORAGE_FRAME_PARAM_VARPTR) { + fprintf(fp, "; LEVEL %i\n", v -> level); fprintf(fp, ".field public %s [%s\n", v -> name, v -> type -> desc); fprintf(fp, ".field public %s$offset I\n\n", v -> name); } @@ -497,9 +502,9 @@ jvm_generate_procedure_frame(oberon_object_t * proc) t -> desc = new_string("L%s;", class -> full_name); v = jvm_create_function_var(p, JVM_STORAGE_REGISTER, "$FP$", t); - p -> frame_v = v; - p -> frame_t = t; + printf("jvm_generate_procedure_frame: %p level %i\n", p -> reg_frame, p -> level); + p -> reg_frame[p -> level] = v -> reg; } void @@ -507,8 +512,180 @@ jvm_generate_frame_initialization(gen_proc_t * p) { jvm_generate_var(p -> frame_v); jvm_generate_ldst_prepare(p, p -> frame_v); - jvm_generate(p, 0, 1, "new %s", p -> frame_t -> class -> full_name); + jvm_generate(p, 0, 1, "new %s", p -> frame_v -> type -> class -> full_name); jvm_generate(p, 1, 2, "dup"); - jvm_generate(p, 1, 0, "invokespecial %s/()V", p -> frame_t -> class -> full_name); + jvm_generate(p, 1, 0, "invokespecial %s/()V", p -> frame_v -> type -> class -> full_name); jvm_generate_store(p, p -> frame_v); } + +char * +jvm_get_procedure_signature(oberon_type_t * ps) +{ + char * signature; + char * desc; + int num; + oberon_object_t * arg; + + signature = new_string("("); + + num = ps -> num_decl; + arg = ps -> decl; + for(int i = 0; i < num; i++) + { + desc = jvm_get_descriptor(arg -> type); + if(arg -> class == OBERON_CLASS_VAR_PARAM) + { + signature = new_string("%s[%sI", signature, desc); + } + else + { + signature = new_string("%s%s", signature, desc); + } + arg = arg -> next; + } + + desc = jvm_get_descriptor(ps -> base); + signature = new_string("%s)%s", signature, desc); + + return signature; +} + +static char * +jvm_get_frame_descriptor(oberon_object_t * proc) +{ + char * full_name = jvm_get_field_full_name_safe(proc); + return new_string("L%s$FRAME;", full_name); +} + +static char * +jvm_get_oberon_signature_static_links(oberon_object_t * parent) +{ + if(parent == NULL) + { + return ""; + } + + char * up = jvm_get_oberon_signature_static_links(parent -> parent); + char * desc = jvm_get_frame_descriptor(parent); + return new_string("%s%s", up, desc); +} + +char * +jvm_get_local_procedure_signature(oberon_object_t * proc) +{ + char * stlinks; + char * signature; + char * desc; + int num; + oberon_object_t * arg; + oberon_type_t * ps; + + ps = proc -> type; + + signature = new_string("("); + + if(proc -> local) + { + stlinks = jvm_get_oberon_signature_static_links(proc -> parent); + signature = new_string("%s%s", signature, stlinks); + } + + num = ps -> num_decl; + arg = ps -> decl; + for(int i = 0; i < num; i++) + { + desc = jvm_get_descriptor(arg -> type); + if(arg -> class == OBERON_CLASS_VAR_PARAM) + { + signature = new_string("%s[%sI", signature, desc); + } + else + { + signature = new_string("%s%s", signature, desc); + } + arg = arg -> next; + } + + desc = jvm_get_descriptor(ps -> base); + signature = new_string("%s)%s", signature, desc); + + return signature; +} + + +static void +jvm_generate_staticlinks_recursive(gen_proc_t * p, oberon_object_t * parent, int level) +{ + if(parent == NULL) + { + return; + } + + jvm_generate_staticlinks_recursive(p, parent -> parent, level - 1); + int reg = p -> reg_frame[level]; + char * desc = jvm_get_frame_descriptor(parent); + jvm_generate(p, 0, 0, ".var %i is SL$%i %s from start to end", reg, level, desc); +} + +void +jvm_generate_staticlinks(oberon_object_t * proc) +{ + gen_proc_t * p; + + p = proc -> gen_proc; + + jvm_generate_staticlinks_recursive(p, proc -> parent, p -> level); +} + +static void +jvm_create_staticlinks_recursive(gen_proc_t * p, oberon_object_t * parent, int level) +{ + if(parent == NULL) + { + return; + } + + jvm_create_staticlinks_recursive(p, parent -> parent, level - 1); + p -> reg_frame[level] = jvm_alloc_register_untyped(p -> rf, false); +} + +void +jvm_create_static_links(oberon_object_t * proc) +{ + gen_proc_t * p; + p = proc -> gen_proc; + + int max_frames = 0; + oberon_object_t * prc = proc; + while(prc) + { + max_frames += 1; + prc = prc -> parent; + } + + p -> max_frames = max_frames; + p -> reg_frame = GC_MALLOC(sizeof *p -> reg_frame); + memset(p -> reg_frame, 0, max_frames * sizeof *p -> reg_frame); + + p -> level = max_frames - 1; + jvm_create_staticlinks_recursive(p, proc -> parent, p -> level); +} + +static void +jvm_generate_push_static_links_recursive(gen_proc_t * p, oberon_object_t * parent) +{ + if(parent == NULL) + { + return; + } + + jvm_generate_push_static_links_recursive(p, parent -> parent); + int level = parent -> gen_proc -> level; + jvm_generate(p, 0, 1, "aload %i", p -> reg_frame[level]); +} + +void +jvm_generate_push_static_links(gen_proc_t * p, oberon_object_t * proc) +{ + jvm_generate_push_static_links_recursive(p, proc -> parent); +} diff --git a/src/backends/jvm/generator-jvm-abi.h b/src/backends/jvm/generator-jvm-abi.h index 0273156..82b3d35 100644 --- a/src/backends/jvm/generator-jvm-abi.h +++ b/src/backends/jvm/generator-jvm-abi.h @@ -27,3 +27,18 @@ jvm_generate_procedure_frame(oberon_object_t * proc); void jvm_generate_frame_initialization(gen_proc_t * p); + +char * +jvm_get_procedure_signature(oberon_type_t * proc); + +char * +jvm_get_local_procedure_signature(oberon_object_t * proc); + +void +jvm_generate_staticlinks(oberon_object_t * proc); + +void +jvm_create_static_links(oberon_object_t * proc); + +void +jvm_generate_push_static_links(gen_proc_t * p, oberon_object_t * proc); diff --git a/src/backends/jvm/generator-jvm-basic.c b/src/backends/jvm/generator-jvm-basic.c index 1757cb6..fac9e0b 100644 --- a/src/backends/jvm/generator-jvm-basic.c +++ b/src/backends/jvm/generator-jvm-basic.c @@ -384,36 +384,6 @@ jvm_get_class_full_name(oberon_type_t * type) return name; } -char * -jvm_get_procedure_signature(oberon_type_t * proc) -{ - char * signature; - char * desc; - - signature = new_string("("); - - int num = proc -> num_decl; - oberon_object_t * arg = proc -> decl; - for(int i = 0; i < num; i++) - { - desc = jvm_get_descriptor(arg -> type); - if(arg -> class == OBERON_CLASS_VAR_PARAM) - { - signature = new_string("%s[%sI", signature, desc); - } - else - { - signature = new_string("%s%s", signature, desc); - } - arg = arg -> next; - } - - desc = jvm_get_descriptor(proc -> base); - signature = new_string("%s)%s", signature, desc); - - return signature; -} - int jvm_cell_size_for_type(oberon_type_t * type) { diff --git a/src/backends/jvm/generator-jvm-basic.h b/src/backends/jvm/generator-jvm-basic.h index 8d2b29c..73b4dfd 100644 --- a/src/backends/jvm/generator-jvm-basic.h +++ b/src/backends/jvm/generator-jvm-basic.h @@ -32,9 +32,6 @@ jvm_get_field_full_name_safe(oberon_object_t * x); char * jvm_get_class_full_name(oberon_type_t * type); -char * -jvm_get_procedure_signature(oberon_type_t * proc); - int diff --git a/src/backends/jvm/generator-jvm.c b/src/backends/jvm/generator-jvm.c index 4501055..1ec731f 100644 --- a/src/backends/jvm/generator-jvm.c +++ b/src/backends/jvm/generator-jvm.c @@ -678,6 +678,7 @@ oberon_generator_init_proc(oberon_context_t * ctx, oberon_object_t * proc) struct gen_class * class = proc -> module -> gen_mod -> class; proc -> gen_proc = jvm_create_proc(class); proc -> gen_proc -> full_name = jvm_get_field_full_name_safe(proc); + jvm_create_static_links(proc); } void @@ -881,15 +882,26 @@ oberon_generate_begin_proc(oberon_context_t * ctx, oberon_object_t * proc) p = proc -> gen_proc; - if(proc -> local == false) + if(proc -> local) + { + signature = jvm_get_local_procedure_signature(proc); + } + else { oberon_generate_procedure_pointer_class(proc); + signature = jvm_get_procedure_signature(proc -> type); } - signature = jvm_get_procedure_signature(proc -> type); name = jvm_get_name(proc); jvm_generate_function_header(p, "public static", name, signature); + if(proc -> local) + { + jvm_generate_staticlinks(proc); + } + + jvm_generate_procedure_frame(proc); + /* Создание парамеров и переменных */ var = proc -> scope -> list -> next; while(var) @@ -898,7 +910,6 @@ oberon_generate_begin_proc(oberon_context_t * ctx, oberon_object_t * proc) var = var -> next; } - jvm_generate_procedure_frame(proc); jvm_generate_frame_initialization(p); /* Инициализация парамеров и переменных */ @@ -1016,8 +1027,6 @@ jvm_generate_call_proc(gen_proc_t * p, oberon_item_t * desig) assert(desig -> var == NULL); assert(desig -> mode == MODE_CALL); - char * signature = NULL; - bool direct_call = false; if(desig -> parent -> mode == MODE_VAR) { @@ -1031,7 +1040,6 @@ jvm_generate_call_proc(gen_proc_t * p, oberon_item_t * desig) oberon_type_t * procsig; procsig = desig -> parent -> result; - signature = jvm_get_procedure_signature(procsig); if(direct_call == false) { @@ -1039,6 +1047,11 @@ jvm_generate_call_proc(gen_proc_t * p, oberon_item_t * desig) push_item(p, desig -> parent); } + if(direct_call) + { + jvm_generate_push_static_links(p, desig -> parent -> var); + } + int args_cells = 0; int result_cells = jvm_cell_size_for_type(procsig -> base); @@ -1064,11 +1077,13 @@ jvm_generate_call_proc(gen_proc_t * p, oberon_item_t * desig) if(direct_call) { char * full_name = jvm_get_field_full_name(desig -> parent -> var); + char * signature = jvm_get_local_procedure_signature(desig -> parent -> var); jvm_generate(p, args_cells, result_cells, "invokestatic %s%s", full_name, signature); } else { char * cname = jvm_get_class_full_name(procsig); + char * signature = jvm_get_procedure_signature(procsig); jvm_generate(p, 1 + args_cells, result_cells, "invokevirtual %s/invoke%s", cname, signature); } } diff --git a/src/backends/jvm/generator-jvm.h b/src/backends/jvm/generator-jvm.h index 6786cf4..00c3e50 100644 --- a/src/backends/jvm/generator-jvm.h +++ b/src/backends/jvm/generator-jvm.h @@ -52,11 +52,14 @@ struct gen_proc_t { char * full_name; int label_id; - gen_var_t * frame_v; - gen_type_t * frame_t; struct gen_register_file * rf; struct gen_stack * stack; struct gen_class * class; + + int level; + int max_frames; + int * reg_frame; + gen_var_t * frame_v; }; struct gen_type_t @@ -76,6 +79,7 @@ struct gen_var_t enum gen_storage storage; gen_type_t * type; int reg; + int level; char * name; char * full_name; diff --git a/src/test.c b/src/test.c index fb76fca..ad95a34 100644 --- a/src/test.c +++ b/src/test.c @@ -15,11 +15,16 @@ static char source_test[] = " VAR" " q, w, r : INTEGER;" " PROCEDURE Y;" + " VAR levY : INTEGER;" + " BEGIN" + " x := 3345;" + " q := 666;" " END Y;" "BEGIN" " x := 54646;" " q := 1;" " Y;" + " Out.String('Pos Y: q = '); Out.Int(q, 0); Out.Ln;" "END X;" "" "BEGIN;"