DEADSOFTWARE

JVM: Реализованы локальные переменные
authorDeaDDooMER <deaddoomer@deadsoftware.ru>
Wed, 26 Jul 2017 17:06:00 +0000 (20:06 +0300)
committerDeaDDooMER <deaddoomer@deadsoftware.ru>
Wed, 26 Jul 2017 17:06:00 +0000 (20:06 +0300)
jvm_test.sh
notes
src/backends/jvm/generator-jvm.c
src/backends/jvm/generator-jvm.h
src/test.c

index 9dce8722b3cfff3f7a533926091805ebdb711f1b..2d8ee55d56865d7d8cce4c567d556fc3d2ac0876 100755 (executable)
@@ -4,12 +4,17 @@ set -e
 
 ./make.sh jvm
 ./run.sh
-jasmin *.j
-proguard -injars . \
+
+rm -rf classes
+mkdir -p classes
+javac -d classes Launcher.java
+jasmin -d classes *.j
+
+proguard -injars classes \
        -libraryjars /usr/lib/jvm/java-8-openjdk/jre/lib/rt.jar \
-       -dontshrink -dontobfuscate -keep class Test
+       -dontshrink -dontobfuscate -keep class Test -keep class Launcher
 
-java -cp . Launcher Test
+java -cp classes Launcher Test
 
 echo Everythin ok! Wheee...
 
diff --git a/notes b/notes
index 60b17bda4932bb27322d9bae00b186974f032d5f..c6cd9028f324eca3c13506037b9ce54e4544ba9d 100644 (file)
--- a/notes
+++ b/notes
@@ -1,3 +1,5 @@
+- унарный минус имеет не правильный приоритет
+
 - нет символов и строк
 - нужен автокаст int -> real для DIV. Да и вообще каст типов.
 
index dc04ffe3423a03433323e677b23f82cd1e1513a0..c217ccb3d6f37ebb809bf076dcd35e62636d3c5e 100644 (file)
@@ -369,6 +369,10 @@ oberon_generator_init_proc(oberon_context_t * ctx, oberon_object_t * proc)
        memset(p, 0, sizeof *p);
        proc -> gen_proc = p;
 
+       struct gen_register_file * rf = GC_MALLOC(sizeof *rf);
+       memset(rf, 0, sizeof *rf);
+       p -> rf = rf;
+
        if(proc -> local)
        {
                oberon_error(ctx, "generator: local procedures not implemented");
@@ -424,16 +428,157 @@ oberon_generate_end_module(oberon_context_t * ctx)
        fprintf(m -> fp, ".end method\n");
 }
 
+static int
+jvm_cell_size_for_type(oberon_type_t * type)
+{
+       if(type -> class == OBERON_TYPE_INTEGER
+               || type -> class == OBERON_TYPE_REAL)
+       {
+               if(type -> size > 4)
+               {
+                       return 2;
+               }
+       }
+
+       return 1;
+}
+
+static bool
+jvm_is_wide_type(oberon_type_t * type)
+{
+       int cell;
+       cell = jvm_cell_size_for_type(type);
+       assert(cell <= 2);
+       return (cell == 2);
+}
+
+static bool
+jvm_is_free_register(struct gen_register_file * rf, int i, bool wide)
+{
+       if(wide)
+       {
+               assert(i + 1 < MAX_REGISTERS);
+               return !(rf -> reg[i].used || rf -> reg[i + 1].used);
+       }
+       else
+       {
+               assert(i < MAX_REGISTERS);
+               return !(rf -> reg[i].used);
+       }
+}
+
+static int
+jvm_alloc_register(struct gen_register_file * rf, oberon_type_t * type)
+{
+       bool wide;
+       wide = jvm_is_wide_type(type);
+
+       int i = 0;
+       while(i < MAX_REGISTERS && !jvm_is_free_register(rf, i, wide))
+       {
+               i += 1;
+       }
+
+       if(wide)
+       {
+               assert(i + 1 <= MAX_REGISTERS);
+               rf -> num_used += 2;
+               rf -> reg[i].used = true;
+               rf -> reg[i + 1].used = true;
+               rf -> reg[i].used = true;
+               rf -> reg[i + 1].wide = false;
+       }
+       else
+       {
+               assert(i <= MAX_REGISTERS);
+               rf -> num_used += 2;
+               rf -> reg[i].used = true;
+               rf -> reg[i].wide = false;
+       }
+
+       if(rf -> num_used > rf -> max_used)
+       {
+               rf -> max_used = rf -> num_used;
+       }
+
+       return i;
+}
+
+static void
+jvm_init_local_object(oberon_context_t * ctx, FILE * fp, oberon_object_t * x)
+{
+       int reg;
+       gen_context_t * c;
+       gen_var_t * v;
+       char * desc;
+
+       c = ctx -> gen_context;
+       v = x -> gen_var;
+       desc = get_descriptor(ctx, x -> type);
+
+       reg = -1;
+       switch(x -> class)
+       {
+               case OBERON_CLASS_VAR:
+               case OBERON_CLASS_PARAM:
+                       if(x -> local)
+                       {
+                               reg = jvm_alloc_register(c -> rf, x -> type);
+                       }
+                       v -> reg = reg;
+                       fprintf(fp, ".var %i is %s %s from start to end\n", reg, x -> name, desc);
+                       break;
+               default:
+                       oberon_error(ctx, "jvm_init_local_object: wat");
+                       break;
+       }
+}
+
 void
 oberon_generate_begin_proc(oberon_context_t * ctx, oberon_object_t * proc)
 {
+       gen_context_t * c;
        gen_module_t * m;
+       gen_proc_t * p;
        char * signature;
 
+       c = ctx -> gen_context;
        m = ctx -> mod -> gen_mod;
-       signature = get_procedure_signature(ctx, proc -> type);
+       p = proc -> gen_proc;
 
+       signature = get_procedure_signature(ctx, proc -> type);
        fprintf(m -> fp, ".method public static %s%s\n", proc -> name, signature);
+
+       /* Сохраняем регистровый файл в стеке */
+       p -> rf -> up = c -> rf;
+       c -> rf = p -> rf;
+
+       oberon_object_t * var = proc -> type -> decl;
+       while(var)
+       {
+               jvm_init_local_object(ctx, m -> fp, var);
+               var = var -> next;
+       }
+
+       fprintf(m -> fp, "start:\n");
+}
+
+void
+oberon_generate_end_proc(oberon_context_t * ctx)
+{
+       gen_context_t * c;
+       gen_module_t * m;
+
+       c = ctx -> gen_context;
+       m = ctx -> mod -> gen_mod;
+
+       fprintf(m -> fp, "end:\n");
+       fprintf(m -> fp, "  .limit stack 32\n");
+       fprintf(m -> fp, "  .limit locals %i\n", c -> rf -> max_used);
+       fprintf(m -> fp, ".end method\n\n");
+
+       /* Возвращаем исходный регистровый файл */
+       c -> rf = c -> rf -> up;
 }
 
 void
@@ -463,17 +608,6 @@ oberon_generate_call_proc(oberon_context_t * ctx, oberon_expr_t * desig)
        fprintf(m -> fp, "invokestatic %s%s\n", fullname, signature);
 }
 
-void
-oberon_generate_end_proc(oberon_context_t * ctx)
-{
-       gen_module_t * m;
-       m = ctx -> mod -> gen_mod;
-
-       fprintf(m -> fp, "  .limit stack 32\n");
-       fprintf(m -> fp, "  .limit locals 32\n");
-       fprintf(m -> fp, ".end method\n\n");
-}
-
 void
 oberon_generate_return(oberon_context_t * ctx, oberon_expr_t * expr)
 {
index 93575198278151531a4ac860f23c4ddb746df43b..01c29ee481785830c6e0e0999be79b179f63f44c 100644 (file)
@@ -4,13 +4,16 @@ struct gen_register_file {
        struct
        {
                bool used;
+               bool wide;
        } reg[MAX_REGISTERS];
+       int num_used;
        int max_used;
+       struct gen_register_file * up;
 };
 
 struct gen_proc_t
 {
-
+       struct gen_register_file * rf;
 };
 
 struct gen_type_t
@@ -32,6 +35,7 @@ struct gen_block_t
 struct gen_context_t
 {
        gen_module_t * m;
+       struct gen_register_file * rf;
 };
 
 struct gen_module_t
index e042f242afaaf997b8244fff25c06bb5c068c181..eb1008c986bb52159572b33fe4f80bd205ab6b91 100644 (file)
@@ -11,8 +11,11 @@ static char source_test[] =
        "  x : INTEGER;"
        ""
        "PROCEDURE Tier(x : INTEGER) : INTEGER;"
+       "VAR"
+       "  y, z, w : INTEGER;"
        "BEGIN"
-       "  RETURN x * x;"
+       "  y := 7777;"
+       "  RETURN x * x + y;"
        "END Tier;"
        ""
        "BEGIN;"