DEADSOFTWARE

JVM: Переписана функция для когенерации инициализации массивов
authorDeaDDooMER <deaddoomer@deadsoftware.ru>
Sat, 29 Jul 2017 13:44:38 +0000 (16:44 +0300)
committerDeaDDooMER <deaddoomer@deadsoftware.ru>
Sat, 29 Jul 2017 13:44:38 +0000 (16:44 +0300)
src/backends/jvm/generator-jvm.c
src/test.c

index 4b5b9474c0a2f006c99e15c5e4251e37763785b1..895a5ae3e524c2ef30063d1de38a316b2e3d23b1 100644 (file)
@@ -261,92 +261,151 @@ jvm_generate_label(gen_proc_t * p, int label_id)
        jvm_generate(p, 0, 0, "L%i:", label_id);
 }
 
+static void
+jvm_generate_load(gen_proc_t * p, oberon_type_t * src_type, gen_var_t * src)
+{
+       char prefix;
+       int cell_size;
+
+       cell_size = jvm_cell_size_for_type(src_type);
+
+       switch(src -> storage)
+       {
+               case JVM_STORAGE_REGISTER:
+                       prefix = jvm_get_prefix(src_type);
+                       jvm_generate(p, 0, cell_size, "%cload %i", prefix, src -> reg);
+                       break;
+               case JVM_STORAGE_STATIC:
+                       jvm_generate(p, 0, cell_size, "getstatic %s %s", src -> full_name, src -> desc);
+                       break;
+               case JVM_STORAGE_FIELD:
+                       jvm_generate(p, 1, cell_size, "getfield %s %s", src -> full_name, src -> desc);
+                       break;
+               default:
+                       gen_error("jvm_generate_load: unknow storage type %i", src -> storage);
+                       break;
+       }
+}
+
+static void
+jvm_generate_store(gen_proc_t * p, oberon_type_t * src_type, gen_var_t * dst)
+{
+       char prefix;
+       int cell_size;
+
+       cell_size = jvm_cell_size_for_type(src_type);
+
+       switch(dst -> storage)
+       {
+               case JVM_STORAGE_REGISTER:
+                       prefix = jvm_get_prefix(src_type);
+                       jvm_generate(p, cell_size, 0, "%cstore %i", prefix, dst -> reg);
+                       break;
+               case JVM_STORAGE_STATIC:
+                       jvm_generate(p, cell_size, 0, "putstatic %s %s", dst -> full_name, dst -> desc);
+                       break;
+               case JVM_STORAGE_FIELD:
+                       jvm_generate(p, 1 + cell_size, 0, "putfield %s %s", dst -> full_name, dst -> desc);
+                       break;
+               default:
+                       gen_error("jvm_generate_store: unknow storage type %i", dst -> storage);
+                       break;
+       }
+}
+
 static void
 jvm_generate_new(gen_proc_t * p, oberon_type_t * type, int num);
 
 /*
- * Функция jvm_generate_static_array_initialization генерирует код для
- * статической инициализации массива. На входе массив, на выходе тот же массив.
- * (arrayref -- arrayref)
+ * Генерирует код для инициализации массива со статическим базовым типом
+ * ( aref -- )
  */
 
 static void
-jvm_generate_static_array_initialization(gen_proc_t * p, oberon_type_t * type)
+jvm_generate_array_initialization(gen_proc_t * p, oberon_type_t * arr)
 {
-       /* for(int i = 0; i < a.length; i++) */
-       /*   a[i] := new(base); */
-       /*   init(a[i]) */
-
-       /* a := pop(array) */
-       gen_var_t * va = oberon_generator_new_var();
-       jvm_generate_and_init_local_var(va, p, false);
-       int reg_a = va -> reg;
-       /* ссылка уже на стеке */
-       jvm_generate(p, 1, 0, "astore %i", reg_a);
-
-       /* int i = 0; */
-       gen_var_t * vi = oberon_generator_new_var();
-       jvm_generate_and_init_local_var(vi, p, false);
-       int reg_i = vi -> reg;
-       jvm_generate(p, 0, 1, "iconst_0");
-       jvm_generate(p, 1, 0, "istore %i", reg_i);
-
-       /* int l := a.length */
-       gen_var_t * vl = oberon_generator_new_var();
-       jvm_generate_and_init_local_var(vl, p, false);
-       int reg_l = vl -> reg;
-       jvm_generate(p, 0, 1, "aload %i", reg_a);
-       jvm_generate(p, 1, 1, "arraylength");
-       jvm_generate(p, 1, 0, "istore %i", reg_l);
-
-       int label_start = jvm_new_label_id(p);
-       int label_end = jvm_new_label_id(p);
-
-       /* start: */
-       /* if (i >= l) goto end; */
-       /*   body*/
-       /*   i += 1;*/
-       /*   goto start;*/
-       /* end: */
-       /* push a */
-
-       jvm_generate_label(p, label_start);
-       jvm_generate(p, 0, 1, "iload %i", reg_i);
-       jvm_generate(p, 0, 1, "iload %i", reg_l);
-       jvm_generate(p, 2, 0, "if_icmpge L%i", label_end);
-
-       if(type -> base -> class == OBERON_TYPE_ARRAY)
+       int dim = 0;
+       oberon_type_t * base = arr;
+       while(base -> class == OBERON_TYPE_ARRAY)
        {
-               /* Инициализируем следующую размерность */
-               jvm_generate(p, 0, 1, "aload %i", reg_a);
-               jvm_generate(p, 0, 1, "iload %i", reg_i);
-               jvm_generate(p, 0, 1, "aaload");                
-               jvm_generate_static_array_initialization(p, type -> base);
-               jvm_generate(p, 1, 0, "pop");
+               dim += 1;
+               base = base -> base;
        }
-       else if(type -> base -> class == OBERON_TYPE_RECORD)
+
+       if(base -> class != OBERON_TYPE_RECORD)
        {
-               jvm_generate(p, 0, 1, "aload %i", reg_a);
-               jvm_generate(p, 0, 1, "iload %i", reg_i);
-               jvm_generate_new(p, type -> base, 0);
-               jvm_generate(p, 3, 0, "aastore");
+               jvm_generate(p, 1, 0, "pop");
+               return;
        }
-       else
+
+       struct {
+               gen_var_t * index;
+               gen_var_t * length;
+               int start;
+               int end;
+       } loop[dim];
+
+       gen_var_t * dst = oberon_generator_new_var();
+       jvm_generate_and_init_local_var(dst, p, false);
+       jvm_generate_store(p, arr, dst);
+
+       /* Входящие параметры заграблены.
+        * Теперь генерируем эквивалентный код:
+        *   int i = 0;
+        *   int len = dst.length
+        *   while(i < len)
+        *   {
+        *     ...
+        *     {
+        *       dst[i, ...] = new record;
+        *     }
+        *     ...
+        *     i += 1;
+        *   }
+        * Где "..." такой же код (начало и конец) для следующей размерности.
+        */
+
+       for(int i = 0; i < dim; i++)
        {
-               assert(0);
-       }
+               loop[i].index = oberon_generator_new_var();
+               loop[i].length = oberon_generator_new_var();
+               loop[i].start = jvm_new_label_id(p);
+               loop[i].end = jvm_new_label_id(p);
+               jvm_generate_and_init_local_var(loop[i].index, p, false);
+               jvm_generate_and_init_local_var(loop[i].length, p, false);
+
+               /* TODO преределать через jvm_generate_load{{store}} */
+
+               jvm_generate(p, 0, 1, "iconst_0");
+               jvm_generate(p, 1, 0, "istore %i", loop[i].index -> reg);
 
-       /* i += 1; */
-       /* goto start */
+               jvm_generate_load(p, arr, dst);
+               jvm_generate(p, 1, 1, "arraylength");
+               jvm_generate(p, 1, 0, "istore %i", loop[i].length -> reg);
 
-       jvm_generate(p, 0, 0, "iinc %i %i", reg_i, 1);
-       jvm_generate(p, 0, 0, "goto L%i", label_start); 
-       jvm_generate_label(p, label_end);
+               /* if(i >= len) goto end; */
+               jvm_generate_label(p, loop[i].start);
+               jvm_generate(p, 0, 1, "iload %i", loop[i].index -> reg);
+               jvm_generate(p, 0, 1, "iload %i", loop[i].length -> reg);
+               jvm_generate(p, 2, 0, "if_icmpge L%i", loop[i].end);
+       }
 
-       /* push(a) */
-       jvm_generate(p, 0, 1, "aload %i", reg_a);
+       jvm_generate_load(p, arr, dst);
+       jvm_generate(p, 0, 1, "iload %i", loop[0].index -> reg);
+       for(int i = 1; i < dim; i++)
+       {
+               jvm_generate(p, 2, 1, "aaload");
+               jvm_generate(p, 0, 1, "iload %i", loop[i].index -> reg);
+       }
+       jvm_generate_new(p, base, 0);
+       jvm_generate(p, 3, 0, "aastore");
 
-       /* TODO освобождение регистров */
+       for(int i = dim - 1; i >= 0; i--)
+       {
+               jvm_generate(p, 0, 0, "iinc %i 1", loop[i].index -> reg);
+               jvm_generate(p, 0, 0, "goto L%i", loop[i].start);
+               jvm_generate_label(p, loop[i].end);
+       }
 }
 
 static void
@@ -367,6 +426,7 @@ jvm_generate_new(gen_proc_t * p, oberon_type_t * type, int num)
                        gen_error("jvm_generate_new_static: static alocation not allowed");
                        break;
                case OBERON_TYPE_RECORD:
+                       assert(num == 0);
                        cname = jvm_get_class_full_name(type);
                        jvm_generate(p, 0, 1, "new %s", cname);
                        jvm_generate(p, 1, 2, "dup");
@@ -394,11 +454,8 @@ jvm_generate_new(gen_proc_t * p, oberon_type_t * type, int num)
 
                        assert(num == 0);
                        jvm_generate(p, dim, 1, "multianewarray %s %i", desc, dim);
-
-                       if(base -> class == OBERON_TYPE_RECORD)
-                       {
-                               jvm_generate_static_array_initialization(p, type);
-                       }
+                       jvm_generate(p, 1, 2, "dup");
+                       jvm_generate_array_initialization(p, type);
                        break;
                default:
                        gen_error("jvm_generate_new_static: unk type class %i", type -> class);
@@ -406,58 +463,6 @@ jvm_generate_new(gen_proc_t * p, oberon_type_t * type, int num)
        }
 }
 
-static void
-jvm_generate_load(gen_proc_t * p, oberon_type_t * src_type, gen_var_t * src)
-{
-       char prefix;
-       int cell_size;
-
-       cell_size = jvm_cell_size_for_type(src_type);
-
-       switch(src -> storage)
-       {
-               case JVM_STORAGE_REGISTER:
-                       prefix = jvm_get_prefix(src_type);
-                       jvm_generate(p, 0, cell_size, "%cload %i", prefix, src -> reg);
-                       break;
-               case JVM_STORAGE_STATIC:
-                       jvm_generate(p, 0, cell_size, "getstatic %s %s", src -> full_name, src -> desc);
-                       break;
-               case JVM_STORAGE_FIELD:
-                       jvm_generate(p, 1, cell_size, "getfield %s %s", src -> full_name, src -> desc);
-                       break;
-               default:
-                       gen_error("jvm_generate_load: unknow storage type %i", src -> storage);
-                       break;
-       }
-}
-
-static void
-jvm_generate_store(gen_proc_t * p, oberon_type_t * src_type, gen_var_t * dst)
-{
-       char prefix;
-       int cell_size;
-
-       cell_size = jvm_cell_size_for_type(src_type);
-
-       switch(dst -> storage)
-       {
-               case JVM_STORAGE_REGISTER:
-                       prefix = jvm_get_prefix(src_type);
-                       jvm_generate(p, cell_size, 0, "%cstore %i", prefix, dst -> reg);
-                       break;
-               case JVM_STORAGE_STATIC:
-                       jvm_generate(p, cell_size, 0, "putstatic %s %s", dst -> full_name, dst -> desc);
-                       break;
-               case JVM_STORAGE_FIELD:
-                       jvm_generate(p, 1 + cell_size, 0, "putfield %s %s", dst -> full_name, dst -> desc);
-                       break;
-               default:
-                       gen_error("jvm_generate_store: unknow storage type %i", dst -> storage);
-                       break;
-       }
-}
-
 /*
  * Генерирует код для копирования полей из первой записи во вторую.
  *  ( aref_dst aref_src -- )
@@ -505,7 +510,7 @@ jvm_generate_copy_array(gen_proc_t * p, oberon_type_t * arr)
        jvm_generate_store(p, arr, src);
        jvm_generate_store(p, arr, dst);
 
-       /* Входящие параметры заграблены
+       /* Входящие параметры заграблены.
         * Теперь генерируем эквивалентный код:
         *   int i = 0;
         *   int len = dst.length
index df0ff8041e00d95bae0f2b1827ac74da2fa4d8e3..6282321069c7d32b23e1a5139fe71985762c8e80 100644 (file)
@@ -9,10 +9,8 @@ static char source_test[] =
        "MODULE Test;"
        "TYPE"
        "  RecDesc = RECORD a : ARRAY 3, 5 OF INTEGER; END;"
-       ""
        "VAR"
        "  a, b : ARRAY 3, 6 OF RecDesc;"
-       ""
        "BEGIN"
        "  a := b;"
        "END Test."