DEADSOFTWARE

JVM: Добавлено копирование массивов
authorDeaDDooMER <deaddoomer@deadsoftware.ru>
Sat, 29 Jul 2017 13:11:58 +0000 (16:11 +0300)
committerDeaDDooMER <deaddoomer@deadsoftware.ru>
Sat, 29 Jul 2017 13:11:58 +0000 (16:11 +0300)
src/backends/jvm/generator-jvm.c
src/test.c

index b46b27de1eedfd7066d64cd55f42f96b65128a77..4b5b9474c0a2f006c99e15c5e4251e37763785b1 100644 (file)
@@ -473,6 +473,140 @@ jvm_generate_copy_record(gen_proc_t * p, oberon_type_t * rec)
        jvm_generate(p, 1 + 1, 0, "invokestatic %s/$COPY$(%s%s)V", cname, desc, desc);
 }
 
+/*
+ * Генерирует кода для копирования массивов.
+ * ( aref_dst aref_src -- )
+ * dst := src;
+ */
+
+static void
+jvm_generate_copy_array(gen_proc_t * p, oberon_type_t * arr)
+{
+       int dim = 0;
+       oberon_type_t * base = arr;
+       while(base -> class == OBERON_TYPE_ARRAY)
+       {
+               dim += 1;
+               base = base -> base;
+       }
+
+       struct {
+               gen_var_t * index;
+               gen_var_t * length;
+               int start;
+               int end;
+       } loop[dim];
+
+       gen_var_t * dst = oberon_generator_new_var();
+       gen_var_t * src = oberon_generator_new_var();
+       jvm_generate_and_init_local_var(dst, p, false);
+       jvm_generate_and_init_local_var(src, p, false);
+
+       jvm_generate_store(p, arr, src);
+       jvm_generate_store(p, arr, dst);
+
+       /* Входящие параметры заграблены
+        * Теперь генерируем эквивалентный код:
+        *   int i = 0;
+        *   int len = dst.length
+        *   while(i < len)
+        *   {
+        *     ...
+        *     {
+        *       copy from src[i, ...] to dst[i, ...];
+        *     }
+        *     ...
+        *     i += 1;
+        *   }
+        * Где "..." такой же код (начало и конец) для следующей размерности.
+        */
+
+       for(int i = 0; i < dim; i++)
+       {
+               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);
+
+               jvm_generate_load(p, arr, dst);
+               jvm_generate(p, 1, 1, "arraylength");
+               jvm_generate(p, 1, 0, "istore %i", loop[i].length -> reg);
+
+               /* 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);
+       }
+
+       if(base -> class == OBERON_TYPE_ARRAY)
+       {
+               // Вся эта шляпа уже должна знать о всех размерностях
+               gen_error("jvm_generate_copy_array: wat");
+       }
+       else if(base -> class == OBERON_TYPE_RECORD)
+       {
+               /* Получаем записи по индексам ( -- dst src ) */
+
+               jvm_generate_load(p, arr, dst);
+               for(int i = 0; i < dim; i++)
+               {
+                       jvm_generate(p, 0, 1, "iload %i", loop[i].index -> reg);
+                       jvm_generate(p, 2, 1, "aaload");
+               }
+
+               jvm_generate_load(p, arr, src);
+               for(int i = 0; i < dim; i++)
+               {
+                       jvm_generate(p, 0, 1, "iload %i", loop[i].index -> reg);
+                       jvm_generate(p, 2, 1, "aaload");
+               }
+
+               /* Копируем записи ( dst src -- ) */
+               jvm_generate_copy_record(p, base);
+       }
+       else
+       {
+               char postfix = jvm_get_postfix(base);
+               int cell_size = jvm_cell_size_for_postfix(postfix);
+
+               /* Получаем массивы и индексы ( -- dst i src i ) */
+
+               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_load(p, arr, src);
+               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);
+               }
+
+               /* Копируем значения ( dst i src i -- ) */
+               jvm_generate(p, 2, cell_size, "%caload", postfix);
+               jvm_generate(p, 2 + cell_size, 0, "%castore", postfix);
+       }
+
+       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);
+       }
+}
 
 // ==========================================
 // ==========================================
@@ -638,7 +772,11 @@ oberon_generator_init_record(oberon_context_t * ctx, oberon_type_t * rec)
                }
                else if(field -> type -> class == OBERON_TYPE_ARRAY)
                {
-                       gen_error("copy array not implemented");
+                       jvm_generate_load(p, rec, copy_dst);
+                       jvm_generate_load(p, field -> type, field -> gen_var);
+                       jvm_generate_load(p, rec, copy_src);
+                       jvm_generate_load(p, field -> type, field -> gen_var);
+                       jvm_generate_copy_array(p, field -> type);
                }
                else
                {
@@ -894,25 +1032,6 @@ oberon_generate_return(oberon_context_t * ctx, oberon_expr_t * expr)
        }
 }
 
-static void
-jvm_push_var(gen_proc_t * p, oberon_object_t * var)
-{
-       int cell_size = jvm_cell_size_for_type(var -> type);
-
-       if(var -> local)
-       {
-               int reg = var -> gen_var -> reg;
-               char prefix = jvm_get_prefix(var -> type);
-               jvm_generate(p, 0, cell_size, "%cload %i", prefix, reg);
-       }
-       else
-       {
-               char * fullname = jvm_get_field_full_name(var);
-               char * desc = jvm_get_descriptor(var -> type);
-               jvm_generate(p, 0, cell_size, "getstatic %s %s", fullname, desc);
-       }
-}
-
 static void
 jvm_generate_expr_new_pointer(gen_proc_t * p, oberon_type_t * type, int num, oberon_expr_t * arg)
 {
@@ -933,7 +1052,7 @@ push_item(gen_proc_t * p, oberon_item_t * item)
        switch(item -> mode)
        {
                case MODE_VAR:
-                       jvm_push_var(p, item -> var);
+                       jvm_generate_load(p, item -> result, item -> var -> gen_var);
                        break;
                case MODE_INTEGER:
                        jvm_generate_push_int(p, item -> integer);
@@ -954,12 +1073,10 @@ push_item(gen_proc_t * p, oberon_item_t * item)
                        break;
                case MODE_FIELD:
                        push_item(p, item -> parent);
-                       char * field = jvm_get_field_full_name(item -> var);
-                       char * desc = jvm_get_descriptor(item -> var -> type);
-                       jvm_generate(p, 1, 1, "getfield %s %s", field, desc);
+                       jvm_generate_load(p, item -> result, item -> var -> gen_var);
                        break;
                case MODE_DEREF:
-                       /* Ð\92Ñ\81е Ð¾Ð±Ñ\8aекÑ\82Ñ\8b Ð¿Ñ\80едÑ\81Ñ\82авлÑ\8fÑ\8eÑ\82Ñ\81Ñ\8f ÐºÐ°Ðº Ñ\83вказатели */
+                       /* Ð\92Ñ\81е Ð¾Ð±Ñ\8aекÑ\82Ñ\8b Ð² jvm Ð¿Ñ\80едÑ\81Ñ\82авлÑ\8fÑ\8eÑ\82Ñ\81Ñ\8f ÐºÐ°Ðº Ñ\83казатели */
                        push_item(p, item -> parent);
                        break;
                case MODE_NIL:
@@ -1212,7 +1329,9 @@ store_expr(gen_proc_t * p, oberon_expr_t * dst, oberon_expr_t * src)
        if(dst -> result -> class == OBERON_TYPE_ARRAY
                || src -> result -> class == OBERON_TYPE_ARRAY)
        {
-               gen_error("array copy not implemented");
+               push_expr(p, dst);
+               push_expr(p, src);
+               jvm_generate_copy_array(p, dst -> result);
        }
        else if(dst -> result -> class == OBERON_TYPE_RECORD
                || src -> result -> class == OBERON_TYPE_RECORD)
index b0e9bdafe6527405ecb9d9b0b9cb8bf02aae8dc2..df0ff8041e00d95bae0f2b1827ac74da2fa4d8e3 100644 (file)
@@ -8,24 +8,13 @@ static char source_test[] =
        "(* Main module *)"
        "MODULE Test;"
        "TYPE"
-       "  RecA = RECORD"
-       "    i, j, k : INTEGER;"
-       "  END;"
-       ""
-       "  Rec = POINTER TO RecDesc;"
-       "  RecDesc = RECORD"
-       "    x, y, z : INTEGER;"
-       "    r, q, s : RecA;"
-       "    p, c, g : Rec;"
-       "  END;"
+       "  RecDesc = RECORD a : ARRAY 3, 5 OF INTEGER; END;"
        ""
        "VAR"
-       "  a, b : Rec;"
+       "  a, b : ARRAY 3, 6 OF RecDesc;"
        ""
        "BEGIN"
-       "  NEW(a);"
-       "  NEW(b);"
-       "  a^ := b^;"
+       "  a := b;"
        "END Test."
 ;