DEADSOFTWARE

JVM: Реализован доступ к локальным переменным ровнем выше из локальных процедур
authorDeaDDooMER <deaddoomer@deadsoftware.ru>
Wed, 9 Aug 2017 12:34:55 +0000 (15:34 +0300)
committerDeaDDooMER <deaddoomer@deadsoftware.ru>
Wed, 9 Aug 2017 12:34:55 +0000 (15:34 +0300)
src/backends/jvm/generator-jvm-abi.c
src/backends/jvm/generator-jvm-abi.h
src/backends/jvm/generator-jvm-basic.c
src/backends/jvm/generator-jvm-basic.h
src/backends/jvm/generator-jvm.c
src/backends/jvm/generator-jvm.h
src/test.c

index 0db2cc88b29bf3454d99b390ea5ff4bc151e0804..a750b927fb170a568a27f0f5bc29fe1ab6bdf038 100644 (file)
@@ -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/<init>()V", p -> frame_t -> class -> full_name);
+       jvm_generate(p, 1, 0, "invokespecial %s/<init>()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);
+}
index 027315628b179a053d332a7d6cdfbeeb08c87179..82b3d35cb75595487d81129d0008d8cdd650d153 100644 (file)
@@ -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);
index 1757cb6221fe49317bb5336c9ff136ed7572ffde..fac9e0bc0def269786de76b60734d24cceb2fc6e 100644 (file)
@@ -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)
 {
index 8d2b29c930c8687da3ceda4ca261388ab4c5cb8f..73b4dfd2a21296a5eaf3a09377c4653017a1dfa2 100644 (file)
@@ -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
index 450105525a0aa9b290fd7e0c3f7c91e5904dfdd9..1ec731f8eb37d275a3114ed050bbd262fd2a9615 100644 (file)
@@ -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);
        }
 }
index 6786cf44dc05d467128d15ff2c8efb018bcc9e0d..00c3e50757a2d58a1628dc49110182193c11b899 100644 (file)
@@ -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;
index fb76fca317b3174656c7c48fb9483dfa175e2a91..ad95a34cf1f36fc78a7ed440cff0f1cbfccdd7ea 100644 (file)
@@ -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;"