DEADSOFTWARE

JVM: Реализованы VAR-параметры
authorDeaDDooMER <deaddoomer@deadsoftware.ru>
Sun, 6 Aug 2017 16:23:41 +0000 (19:23 +0300)
committerDeaDDooMER <deaddoomer@deadsoftware.ru>
Sun, 6 Aug 2017 16:23:41 +0000 (19:23 +0300)
src/backends/jvm/generator-jvm-abi.c [new file with mode: 0644]
src/backends/jvm/generator-jvm-abi.h [new file with mode: 0644]
src/backends/jvm/generator-jvm-asm.c [new file with mode: 0644]
src/backends/jvm/generator-jvm-asm.h [new file with mode: 0644]
src/backends/jvm/generator-jvm-basic.c
src/backends/jvm/generator-jvm.c
src/backends/jvm/generator-jvm.h
src/oberon.c
src/test.c

diff --git a/src/backends/jvm/generator-jvm-abi.c b/src/backends/jvm/generator-jvm-abi.c
new file mode 100644 (file)
index 0000000..ed4a19a
--- /dev/null
@@ -0,0 +1,196 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <stdint.h>
+#include <stdbool.h>
+#include <string.h>
+#include <assert.h>
+
+#include <gc.h>
+
+#include "../../../include/oberon.h"
+#include "../../oberon-internals.h"
+#include "generator-jvm.h"
+#include "generator-jvm-abi.h"
+#include "generator-jvm-asm.h"
+#include "generator-jvm-basic.h"
+
+/*
+ *   --- Каждый модуль является объектом.
+ *       Импортируемые модули представляются полями.
+ *       Каждая глобальная переменная представляется не статическим полем.
+ *       Каждая процедура представляется не статическим метеодом.
+ *       Процедура инициализации модуля имеет название BEGIN.
+ *       Процедура финализации модуля имеет название END.
+ *         Это позволит сделать динамическую загрузку и выгрузку.
+ *   +++ всем переменным и полям в дескриптор добавляется "["
+ *         Это позволит делать ссылки на переменные в VAR-параметрах.
+ *   --- Каждая процедура снабжается параметром-фреймом.
+ *       Это позволит реализовать локальные процедуры и средства рефлекции над стеком.
+ */ 
+
+void
+jvm_generate_ldst_prepare(gen_proc_t * p, gen_var_t * v)
+{
+       char * full_name = v -> full_name;
+       char * desc = v -> type -> desc;
+
+       switch(v -> storage)
+       {
+               case JVM_STORAGE_REGISTER:
+                       break;
+               case JVM_STORAGE_STATIC:
+                       jvm_generate(p, 0, 1, "getstatic %s [%s", full_name, desc);
+                       jvm_generate(p, 0, 1, "iconst_0");
+                       break;
+               case JVM_STORAGE_FIELD:
+                       jvm_generate(p, 1, 1, "getfield %s [%s", full_name, desc);
+                       jvm_generate(p, 0, 1, "iconst_0");
+                       break;
+               case JVM_STORAGE_LOCAL:
+                       jvm_generate(p, 0, 1, "aload %i", v -> reg);
+                       jvm_generate(p, 0, 1, "iconst_0");
+                       break;
+               case JVM_STORAGE_VARPTR:
+                       jvm_generate(p, 0, 1, "aload %i", v -> reg);
+                       jvm_generate(p, 0, 1, "iload %i", v -> reg + 1);
+                       break;
+               default:
+                       gen_error("jvm_abi_obn_generate_ldst_prepare: wat %i", v -> storage);
+       }
+}
+
+void
+jvm_generate_load(gen_proc_t * p, gen_var_t * src)
+{
+       char prefix = src -> type -> prefix;
+       int cell_size = src -> type -> cell_size;
+
+       switch(src -> storage)
+       {
+               case JVM_STORAGE_REGISTER:
+                       jvm_generate(p, 0, cell_size, "%cload %i", prefix, src -> reg);
+                       break;
+               case JVM_STORAGE_STATIC:
+               case JVM_STORAGE_FIELD:
+               case JVM_STORAGE_LOCAL:
+               case JVM_STORAGE_VARPTR:
+                       jvm_generate_ldst_prepare(p, src);
+                       jvm_generate(p, 1 + 1, cell_size, "%caload", prefix);
+                       break;
+               default:
+                       gen_error("jvm_generate_load: unknow storage type %i", src -> storage);
+                       break;
+       }
+}
+
+void
+jvm_generate_store(gen_proc_t * p, gen_var_t * dst)
+{
+       char prefix = dst -> type -> prefix;
+       int cell_size = dst -> type -> cell_size;
+
+       switch(dst -> storage)
+       {
+               case JVM_STORAGE_REGISTER:
+                       jvm_generate(p, cell_size, 0, "%cstore %i", prefix, dst -> reg);
+                       break;
+               case JVM_STORAGE_STATIC:
+               case JVM_STORAGE_FIELD:
+               case JVM_STORAGE_LOCAL:
+               case JVM_STORAGE_VARPTR:
+                       jvm_generate(p, 1 + 1 + cell_size, 0, "%castore", prefix);
+                       break;
+               default:
+                       gen_error("jvm_generate_store: unknow storage type %i", dst -> storage);
+                       break;
+       }
+}
+
+void
+jvm_generate_and_init_global_var(struct gen_class * class, gen_var_t * v, char * name, gen_type_t * t)
+{
+       assert(class -> p == NULL);
+        fprintf(class -> fp, ".field public static %s [%s\n\n", name, t -> desc);
+
+        v -> storage = JVM_STORAGE_STATIC;
+        v -> full_name = new_string("%s/%s", class -> full_name, name);
+       v -> type = t;
+}
+
+void
+jvm_generate_and_init_field(struct gen_class * class, gen_var_t * v, char * name, gen_type_t * t)
+{
+       assert(class -> p == NULL);
+        fprintf(class -> fp, ".field public %s [%s\n\n", name, t -> desc);
+
+        v -> storage = JVM_STORAGE_FIELD;
+        v -> full_name = new_string("%s/%s", class -> full_name, name);
+       v -> type = t;
+}
+
+void
+jvm_generate_and_init_local_var(gen_proc_t * p, gen_var_t * v, gen_type_t * t)
+{
+       v -> storage = JVM_STORAGE_REGISTER;
+        v -> reg = jvm_alloc_register_untyped(p -> rf, t -> wide);
+       v -> type = t;
+}
+
+void
+jvm_generate_and_init_named_local_var(gen_proc_t * p, gen_var_t * v, char * name, gen_type_t * t)
+{
+       jvm_generate_and_init_local_var(p, v, t);
+        jvm_generate(p, 0, 0, ".var %i is %s %s from start to end", v -> reg, name, t -> desc);
+}
+
+void
+jvm_generate_and_init_var_param(gen_proc_t * p, gen_var_t * v, char * name, gen_type_t * t)
+{
+       v -> storage = JVM_STORAGE_VARPTR;
+        v -> reg = jvm_alloc_register_untyped(p -> rf, true);
+       v -> type = t;
+        jvm_generate(p, 0, 0, ".var %i is %s [%s from start to end", v -> reg, name, t -> desc);
+        jvm_generate(p, 0, 0, ".var %i is __%s_offset I from start to end", v -> reg + 1, name);
+}
+
+void
+jvm_generate_variable_initialization(gen_proc_t * p, gen_var_t * v)
+{
+       if(v -> storage == JVM_STORAGE_STATIC)
+       {
+               jvm_generate(p, 0, 1, "iconst_1");
+               jvm_generate(p, 1, 1, "multianewarray [%s 1", v -> type -> desc);
+               jvm_generate(p, 1, 0, "putstatic %s [%s", v -> full_name, v -> type -> desc);
+       }
+       else if(v -> storage == JVM_STORAGE_FIELD)
+       {
+               jvm_generate(p, 0, 1, "iconst_1");
+               jvm_generate(p, 1, 1, "multianewarray [%s 1", v -> type -> desc);
+               jvm_generate(p, 1, 0, "putfield %s [%s", v -> full_name, v -> type -> desc);
+       }
+}
+
+void
+jvm_generate_param_initialization(gen_proc_t * p, gen_var_t * v)
+{
+       assert(v -> storage == JVM_STORAGE_REGISTER);
+
+       int old_reg = v -> reg;
+       bool wide = v -> type -> wide;
+       int cell_size = v -> type -> cell_size;
+       char prefix = v -> type -> prefix;
+       char * desc = v -> type -> desc;
+
+       v -> storage = JVM_STORAGE_LOCAL;
+        v -> reg = jvm_alloc_register_untyped(p -> rf, wide);
+
+       jvm_generate(p, 0, 1, "iconst_1");
+       jvm_generate(p, 1, 1, "multianewarray [%s 1", desc);
+       jvm_generate(p, 1, 2, "dup");
+       jvm_generate(p, 1, 0, "astore %i", v -> reg);
+
+       jvm_generate(p, 0, 1, "iconst_0");
+       jvm_generate(p, 0, cell_size, "%cload %i", prefix, old_reg);
+       jvm_generate(p, 1 + 1 + cell_size, 0, "%castore", prefix);
+}
diff --git a/src/backends/jvm/generator-jvm-abi.h b/src/backends/jvm/generator-jvm-abi.h
new file mode 100644 (file)
index 0000000..01bfefc
--- /dev/null
@@ -0,0 +1,29 @@
+void 
+jvm_generate_ldst_prepare(gen_proc_t * p, gen_var_t * v);
+
+void
+jvm_generate_load(gen_proc_t * p, gen_var_t * src);
+
+void
+jvm_generate_store(gen_proc_t * p, gen_var_t * dst);
+
+void
+jvm_generate_and_init_global_var(struct gen_class * class, gen_var_t * v, char * name, gen_type_t * t);
+
+void
+jvm_generate_and_init_field(struct gen_class * class, gen_var_t * v, char * name, gen_type_t * t);
+
+void
+jvm_generate_and_init_local_var(gen_proc_t * p, gen_var_t * v, gen_type_t * t);
+
+void
+jvm_generate_and_init_named_local_var(gen_proc_t * p, gen_var_t * v, char * name, gen_type_t * t);
+
+void
+jvm_generate_and_init_var_param(gen_proc_t * p, gen_var_t * v, char * name, gen_type_t * t);
+
+void
+jvm_generate_variable_initialization(gen_proc_t * p, gen_var_t * v);
+
+void
+jvm_generate_param_initialization(gen_proc_t * p, gen_var_t * v);
diff --git a/src/backends/jvm/generator-jvm-asm.c b/src/backends/jvm/generator-jvm-asm.c
new file mode 100644 (file)
index 0000000..50f3af9
--- /dev/null
@@ -0,0 +1,302 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <stdint.h>
+#include <stdbool.h>
+#include <string.h>
+#include <assert.h>
+
+#include <gc.h>
+
+#include "../../../include/oberon.h"
+#include "../../oberon-internals.h"
+#include "generator-jvm.h"
+#include "generator-jvm-abi.h"
+#include "generator-jvm-asm.h"
+#include "generator-jvm-basic.h"
+
+gen_proc_t *
+jvm_create_proc(struct gen_class * class)
+{
+       gen_proc_t * p = GC_MALLOC(sizeof *p);
+       memset(p, 0, sizeof *p);
+
+       struct gen_register_file * rf = GC_MALLOC(sizeof *rf);
+       memset(rf, 0, sizeof *rf);
+
+       struct gen_stack * stack = GC_MALLOC(sizeof *stack);
+       memset(rf, 0, sizeof *stack);
+
+       p -> rf = rf;
+       p -> stack = stack;
+       p -> class = class;
+       p -> label_id = 0;
+
+       return p;
+}
+
+void
+jvm_generate_function_header(gen_proc_t * p, char * access, char * name, char * signature)
+{
+       struct gen_class * class;
+       class = p -> class;
+
+       /* Делаем процедуру текущей в этом классе */
+       assert(class -> p == NULL);
+       class -> p = p;
+
+       fprintf(class -> fp, ".method %s %s%s\n", access, name, signature);
+       fprintf(class -> fp, "  start:\n");
+}
+
+void
+jvm_generate_function_end(gen_proc_t * p)
+{
+       struct gen_class * class;
+       class = p -> class;
+
+       assert(class -> p);
+       class -> p = NULL;
+
+       int pointer = p -> stack -> pointer;
+       int max_pointer = p -> stack -> max_pointer;
+       int locals = p -> rf -> num_used;
+       int max_locals = p -> rf -> max_used;
+
+       fprintf(class -> fp, "  .limit stack %i \t; current(%i)\n", max_pointer, pointer);
+       fprintf(class -> fp, "  .limit locals %i \t; current(%i)\n", max_locals, locals);
+       fprintf(class -> fp, "  end:\n");
+       fprintf(class -> fp, ".end method\n\n");
+}
+
+struct gen_class *
+jvm_create_class(char * full_name)
+{
+       struct gen_class * class = GC_MALLOC(sizeof *class);
+       memset(class, 0, sizeof *class);
+
+       char * fname = new_string("%s.j", full_name);
+       class -> full_name = new_string(full_name);
+       class -> fp = fopen(fname, "w");
+       assert(class -> fp);
+
+       return class;
+}
+
+void
+jvm_destroy_class(struct gen_class * class)
+{
+       assert(class -> p == NULL);
+       fclose(class -> fp);
+}
+
+void
+jvm_stack_push(gen_proc_t * p, unsigned size)
+{
+       p -> stack -> pointer += size;
+       if(p -> stack -> pointer > p -> stack -> max_pointer)
+       {
+               p -> stack -> max_pointer = p -> stack -> pointer;
+       }
+}
+
+void
+jvm_stack_pop(gen_proc_t * p, unsigned size)
+{
+       p -> stack -> pointer -= size;
+
+       if(p -> stack -> pointer < 0)
+       {
+               printf("WARING: stack pointer %i\n", p -> stack -> pointer);
+       }
+}
+
+void
+jvm_generate(gen_proc_t * p, unsigned get, unsigned push, char * format, ...)
+{
+       va_list ptr;
+       va_start(ptr, format);
+
+       jvm_stack_pop(p, get);
+       fprintf(p -> class -> fp, "  ");
+       vfprintf(p -> class -> fp, format, ptr);
+       jvm_stack_push(p, push);
+       fprintf(p -> class -> fp, " \t ;>>>> %i -- %i : current_stack(%i)\n", get, push, p -> stack -> pointer);
+
+       va_end(ptr);
+}
+
+void
+jvm_generate_comment(gen_proc_t * p, char * format, ...)
+{
+       va_list ptr;
+       va_start(ptr, format);
+
+       fprintf(p -> class -> fp, "  ;;;; ");
+       vfprintf(p -> class -> fp, format, ptr);
+       fprintf(p -> class -> fp, "\n");
+
+       va_end(ptr);
+}
+
+void
+jvm_generate_push_int(gen_proc_t * p, int64_t i)
+{
+       if(i == -1)
+       {
+               jvm_generate(p, 0, 1, "iconst_m1");
+       }
+       else if(i >= 0 && i <= 5)
+       {
+               jvm_generate(p, 0, 1, "iconst_%li", i);
+       }
+       else if(i >= -128 && i <= 127)
+       {
+               jvm_generate(p, 0, 1, "bipush %li", i);
+       }
+       else if(i >= -32768 && i <= 32767)
+       {
+               jvm_generate(p, 0, 1, "sipush %li", i);
+       }
+       else if(i >= -2147483648 && i <= 2147483647)
+       {
+               jvm_generate(p, 0, 1, "ldc %li", i);
+       }
+       else
+       {
+               jvm_generate(p, 0, 2, "ldc2_w %li", i);
+       }
+}
+
+void
+jvm_generate_push_int_size(gen_proc_t * p, int64_t i, int size)
+{
+       int pushed_cell = 1;
+
+       if(i == -1)
+       {
+               jvm_generate(p, 0, 1, "iconst_m1");
+       }
+       else if(i >= 0 && i <= 5)
+       {
+               jvm_generate(p, 0, 1, "iconst_%li", i);
+       }
+       else if(i >= -128 && i <= 127)
+       {
+               jvm_generate(p, 0, 1, "bipush %li", i);
+       }
+       else if(i >= -32768 && i <= 32767)
+       {
+               jvm_generate(p, 0, 1, "sipush %li", i);
+       }
+       else if(i >= -2147483648 && i <= 2147483647)
+       {
+               jvm_generate(p, 0, 1, "ldc %li", i);
+       }
+       else
+       {
+               pushed_cell = 2;
+               jvm_generate(p, 0, 2, "ldc2_w %li", i);
+       }
+
+       assert(size <= 8);
+       if(size > 4 && pushed_cell == 1)
+       {
+               jvm_generate(p, pushed_cell, 2, "i2l");
+       }
+       else if(size <= 4)
+       {
+               if(pushed_cell > 1)
+               {
+                       jvm_generate(p, 2, 1, "l2i");
+               }
+
+               if(size == 2)
+               {
+                       jvm_generate(p, 1, 1, "i2s");
+               }
+               else if(size == 1)
+               {
+                       jvm_generate(p, 1, 1, "i2b");
+               }
+       }
+}
+
+void
+jvm_generate_push_float(gen_proc_t * p, double f, int size)
+{
+       if(size <= 4)
+       {
+               if(f == 0.0)
+               {
+                       jvm_generate(p, 0, 1, "fconst_0");
+               }
+               if(f == 1.0)
+               {
+                       jvm_generate(p, 0, 1, "fconst_1");
+               }
+               if(f == 2.0)
+               {
+                       jvm_generate(p, 0, 1, "fconst_2");
+               }
+               else
+               {
+                       jvm_generate(p, 0, 1, "ldc %lf", f);
+               }
+       }
+       else
+       {
+               if(f == 0.0)
+               {
+                       jvm_generate(p, 0, 2, "dconst_0");
+               }
+               if(f == 1.0)
+               {
+                       jvm_generate(p, 0, 2, "dconst_1");
+               }
+               else
+               {
+                       jvm_generate(p, 0, 2, "ldc2_w %lf", f);
+               }
+       }
+}
+
+void
+jvm_generate_push_string(gen_proc_t * p, char * str, int char_size)
+{
+       assert(char_size == 1);
+       int len = strlen(str);
+
+       jvm_generate_push_int(p, len + 1);
+       jvm_generate(p, 1, 1, "newarray byte");
+
+       for(int i = 0; i < len; i++)
+       {
+               jvm_generate(p, 1, 2, "dup");
+               jvm_generate_push_int(p, i);
+               jvm_generate_push_int(p, str[i]);
+               jvm_generate(p, 3, 0, "bastore");
+       }
+}
+
+gen_var_t *
+oberon_generator_new_var()
+{
+       gen_var_t * v = GC_MALLOC(sizeof *v);
+       memset(v, 0, sizeof *v);
+       return v;       
+}
+
+int
+jvm_new_label_id(gen_proc_t * p)
+{
+       int label_id = p -> label_id;
+       p -> label_id += 1;
+       return label_id;
+}
+
+void
+jvm_generate_label(gen_proc_t * p, int label_id)
+{
+       jvm_generate(p, 0, 0, "L%i:", label_id);
+}
diff --git a/src/backends/jvm/generator-jvm-asm.h b/src/backends/jvm/generator-jvm-asm.h
new file mode 100644 (file)
index 0000000..da287a0
--- /dev/null
@@ -0,0 +1,53 @@
+struct gen_class *
+jvm_create_class(char * full_name);
+
+void
+jvm_destroy_class(struct gen_class * class);
+
+gen_proc_t *
+jvm_create_proc(struct gen_class * class);
+
+gen_var_t *
+oberon_generator_new_var();
+
+
+
+void
+jvm_generate_function_header(gen_proc_t * p, char * access, char * name, char * signature);
+
+void
+jvm_generate_function_end(gen_proc_t * p);
+
+int
+jvm_new_label_id(gen_proc_t * p);
+
+void
+jvm_generate_label(gen_proc_t * p, int label_id);
+
+
+
+void
+jvm_stack_push(gen_proc_t * p, unsigned size);
+
+void
+jvm_stack_pop(gen_proc_t * p, unsigned size);
+
+
+
+void
+jvm_generate(gen_proc_t * p, unsigned get, unsigned push, char * format, ...);
+
+void
+jvm_generate_comment(gen_proc_t * p, char * format, ...);
+
+void
+jvm_generate_push_int(gen_proc_t * p, int64_t i);
+
+void
+jvm_generate_push_int_size(gen_proc_t * p, int64_t i, int size);
+
+void
+jvm_generate_push_float(gen_proc_t * p, double f, int size);
+
+void
+jvm_generate_push_string(gen_proc_t * p, char * str, int char_size);
index bcd82a25476803cbcd4aca6e8aa0ecf9f4c24934..277940ce17b58fb18f46ee630aa162c2a250c62a 100644 (file)
@@ -126,6 +126,26 @@ jvm_get_descriptor(oberon_type_t * type)
                        desc = jvm_get_descriptor(type -> base);
                        return new_string("[%s", desc);
                        break;
+               case OBERON_TYPE_STRING:
+                       switch(type -> size)
+                       {
+                               case 1:
+                                       return new_string("[B");
+                                       break;
+                               case 2:
+                                       return new_string("[C");
+                                       break;
+                               case 4:
+                                       return new_string("[I");
+                                       break;
+                               case 8:
+                                       return new_string("[J");
+                                       break;
+                               default:
+                                       gen_error("jvm_get_descriptor: unsupported string size %i", type -> size);
+                                       break;
+                       }
+                       break;
                default:
                        gen_error("jvm_get_descriptor: unsupported type class %i", type -> class);
                        break;
@@ -173,13 +193,14 @@ jvm_get_prefix(oberon_type_t * type)
                case OBERON_TYPE_ARRAY:
                case OBERON_TYPE_RECORD:
                case OBERON_TYPE_POINTER:
+               case OBERON_TYPE_STRING:
                        return 'a';
                        break;
                case OBERON_TYPE_REAL:
                        return (size <= 4) ? ('f') : ('d');
                        break;
                default:
-                       gen_error("jvm_get_prefix: wat");
+                       gen_error("jvm_get_prefix: wat %i", type -> class);
                        return '!';
                        break;
        }
@@ -239,6 +260,7 @@ jvm_get_postfix(oberon_type_t * type)
                case OBERON_TYPE_ARRAY:
                case OBERON_TYPE_RECORD:
                case OBERON_TYPE_POINTER:
+               case OBERON_TYPE_STRING:
                        return 'a';
                        break;
                case OBERON_TYPE_REAL:
@@ -347,7 +369,14 @@ jvm_get_procedure_signature(oberon_type_t * proc)
        for(int i = 0; i < num; i++)
        {
                desc = jvm_get_descriptor(arg -> type);
-               signature = new_string("%s%s", signature, desc);
+               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;
        }
 
index a107efc119eca8a22afc620cbc912e8e284f86fa..da8b06b29f5142a7ea9b25cdd2e6c8ed18a00bb8 100644 (file)
 #include "../../../include/oberon.h"
 #include "../../oberon-internals.h"
 #include "generator-jvm.h"
+#include "generator-jvm-abi.h"
+#include "generator-jvm-asm.h"
 #include "generator-jvm-basic.h"
 
-// ==========================================
-// ==========================================
-// ==========================================
-
-gen_proc_t *
-jvm_create_proc(struct gen_class * class)
-{
-       gen_proc_t * p = GC_MALLOC(sizeof *p);
-       memset(p, 0, sizeof *p);
-
-       struct gen_register_file * rf = GC_MALLOC(sizeof *rf);
-       memset(rf, 0, sizeof *rf);
-
-       struct gen_stack * stack = GC_MALLOC(sizeof *stack);
-       memset(rf, 0, sizeof *stack);
-
-       p -> rf = rf;
-       p -> stack = stack;
-       p -> class = class;
-       p -> label_id = 0;
-
-       return p;
-}
-
-void
-jvm_generate_function_header(gen_proc_t * p, char * access, char * name, char * signature)
-{
-       struct gen_class * class;
-       class = p -> class;
-
-       /* Делаем процедуру текущей в этом классе */
-       assert(class -> p == NULL);
-       class -> p = p;
-
-       fprintf(class -> fp, ".method %s %s%s\n", access, name, signature);
-       fprintf(class -> fp, "  start:\n");
-}
-
-void
-jvm_generate_function_end(gen_proc_t * p)
-{
-       struct gen_class * class;
-       class = p -> class;
-
-       assert(class -> p);
-       class -> p = NULL;
-
-       int pointer = p -> stack -> pointer;
-       int max_pointer = p -> stack -> max_pointer;
-       int locals = p -> rf -> num_used;
-       int max_locals = p -> rf -> max_used;
-
-       fprintf(class -> fp, "  .limit stack %i \t; current(%i)\n", max_pointer, pointer);
-       fprintf(class -> fp, "  .limit locals %i \t; current(%i)\n", max_locals, locals);
-       fprintf(class -> fp, "  end:\n");
-       fprintf(class -> fp, ".end method\n\n");
-}
-
-struct gen_class *
-jvm_create_class(char * full_name)
-{
-       struct gen_class * class = GC_MALLOC(sizeof *class);
-       memset(class, 0, sizeof *class);
-
-       char * fname = new_string("%s.j", full_name);
-       class -> full_name = new_string(full_name);
-       class -> fp = fopen(fname, "w");
-       assert(class -> fp);
-
-       return class;
-}
-
-static void
-jvm_destroy_class(struct gen_class * class)
-{
-       assert(class -> p == NULL);
-       fclose(class -> fp);
-}
-
-static void
-jvm_stack_push(gen_proc_t * p, unsigned size)
-{
-       p -> stack -> pointer += size;
-       if(p -> stack -> pointer > p -> stack -> max_pointer)
-       {
-               p -> stack -> max_pointer = p -> stack -> pointer;
-       }
-}
-
-static void
-jvm_stack_pop(gen_proc_t * p, unsigned size)
-{
-       p -> stack -> pointer -= size;
-
-       if(p -> stack -> pointer < 0)
-       {
-               printf("WARING: stack pointer %i\n", p -> stack -> pointer);
-       }
-}
-
-static void
-jvm_generate(gen_proc_t * p, unsigned get, unsigned push, char * format, ...)
-{
-       va_list ptr;
-       va_start(ptr, format);
-
-       jvm_stack_pop(p, get);
-       fprintf(p -> class -> fp, "  ");
-       vfprintf(p -> class -> fp, format, ptr);
-       jvm_stack_push(p, push);
-       fprintf(p -> class -> fp, " \t ;>>>> %i -- %i : current_stack(%i)\n", get, push, p -> stack -> pointer);
-
-       va_end(ptr);
-}
-
-static void
-jvm_generate_comment(gen_proc_t * p, char * format, ...)
-{
-       va_list ptr;
-       va_start(ptr, format);
-
-       fprintf(p -> class -> fp, "  ;;;; ");
-       vfprintf(p -> class -> fp, format, ptr);
-       fprintf(p -> class -> fp, "\n");
-
-       va_end(ptr);
-}
-
-static void
-jvm_generate_push_int(gen_proc_t * p, int64_t i)
-{
-       if(i == -1)
-       {
-               jvm_generate(p, 0, 1, "iconst_m1");
-       }
-       else if(i >= 0 && i <= 5)
-       {
-               jvm_generate(p, 0, 1, "iconst_%li", i);
-       }
-       else if(i >= -128 && i <= 127)
-       {
-               jvm_generate(p, 0, 1, "bipush %li", i);
-       }
-       else if(i >= -32768 && i <= 32767)
-       {
-               jvm_generate(p, 0, 1, "sipush %li", i);
-       }
-       else if(i >= -2147483648 && i <= 2147483647)
-       {
-               jvm_generate(p, 0, 1, "ldc %li", i);
-       }
-       else
-       {
-               jvm_generate(p, 0, 2, "ldc2_w %li", i);
-       }
-}
-
-static void
-jvm_generate_push_int_size(gen_proc_t * p, int64_t i, int size)
-{
-       int pushed_cell = 1;
-
-       if(i == -1)
-       {
-               jvm_generate(p, 0, 1, "iconst_m1");
-       }
-       else if(i >= 0 && i <= 5)
-       {
-               jvm_generate(p, 0, 1, "iconst_%li", i);
-       }
-       else if(i >= -128 && i <= 127)
-       {
-               jvm_generate(p, 0, 1, "bipush %li", i);
-       }
-       else if(i >= -32768 && i <= 32767)
-       {
-               jvm_generate(p, 0, 1, "sipush %li", i);
-       }
-       else if(i >= -2147483648 && i <= 2147483647)
-       {
-               jvm_generate(p, 0, 1, "ldc %li", i);
-       }
-       else
-       {
-               pushed_cell = 2;
-               jvm_generate(p, 0, 2, "ldc2_w %li", i);
-       }
-
-       assert(size <= 8);
-       if(size > 4 && pushed_cell == 1)
-       {
-               jvm_generate(p, pushed_cell, 2, "i2l");
-       }
-       else if(size <= 4)
-       {
-               if(pushed_cell > 1)
-               {
-                       jvm_generate(p, 2, 1, "l2i");
-               }
-
-               if(size == 2)
-               {
-                       jvm_generate(p, 1, 1, "i2s");
-               }
-               else if(size == 1)
-               {
-                       jvm_generate(p, 1, 1, "i2b");
-               }
-       }
-}
-
-static void
-jvm_generate_push_float(gen_proc_t * p, double f, int size)
-{
-       if(size <= 4)
-       {
-               if(f == 0.0)
-               {
-                       jvm_generate(p, 0, 1, "fconst_0");
-               }
-               if(f == 1.0)
-               {
-                       jvm_generate(p, 0, 1, "fconst_1");
-               }
-               if(f == 2.0)
-               {
-                       jvm_generate(p, 0, 1, "fconst_2");
-               }
-               else
-               {
-                       jvm_generate(p, 0, 1, "ldc %lf", f);
-               }
-       }
-       else
-       {
-               if(f == 0.0)
-               {
-                       jvm_generate(p, 0, 2, "dconst_0");
-               }
-               if(f == 1.0)
-               {
-                       jvm_generate(p, 0, 2, "dconst_1");
-               }
-               else
-               {
-                       jvm_generate(p, 0, 2, "ldc2_w %lf", f);
-               }
-       }
-}
-
-static void
-jvm_generate_push_string(gen_proc_t * p, char * str, int char_size)
-{
-       assert(char_size == 1);
-       int len = strlen(str);
-
-       jvm_generate_push_int(p, len + 1);
-       jvm_generate(p, 1, 1, "newarray byte");
-
-       for(int i = 0; i < len; i++)
-       {
-               jvm_generate(p, 1, 2, "dup");
-               jvm_generate_push_int(p, i);
-               jvm_generate_push_int(p, str[i]);
-               jvm_generate(p, 3, 0, "bastore");
-       }
-}
-
-static gen_var_t *
-oberon_generator_new_var()
-{
-       gen_var_t * v = GC_MALLOC(sizeof *v);
-       memset(v, 0, sizeof *v);
-       return v;       
-}
-
-static void
-jvm_generate_and_init_global_var(gen_var_t * v, struct gen_class * class, char * access, char * name, char * desc)
-{
-       assert(class -> p == NULL);
-       fprintf(class -> fp, ".field %s static %s %s\n\n", access, name, desc);
-
-       v -> storage = JVM_STORAGE_STATIC;
-       v -> full_name = new_string("%s/%s", class -> full_name, name);
-       v -> desc = new_string(desc);
-}
-
-static void
-jvm_generate_and_init_field(gen_var_t * v, struct gen_class * class, char * access, char * name, char * desc)
-{
-       assert(class -> p == NULL);
-       fprintf(class -> fp, ".field %s %s %s\n\n", access, name, desc);
-
-       v -> storage = JVM_STORAGE_FIELD;
-       v -> full_name = new_string("%s/%s", class -> full_name, name);
-       v -> desc = new_string(desc);
-}
-
-static void
-jvm_generate_and_init_local_var(gen_var_t * v, gen_proc_t * p, bool wide)
-{
-       v -> storage = JVM_STORAGE_REGISTER;
-       v -> reg = jvm_alloc_register_untyped(p -> rf, wide);
-}
-
-static void
-jvm_generate_and_init_named_local_var(gen_var_t * v, gen_proc_t * p, bool wide, char * name, char * desc)
-{
-       jvm_generate_and_init_local_var(v, p, wide);
-       v -> desc = new_string(desc);
-       jvm_generate(p, 0, 0, ".var %i is %s %s from start to end", v -> reg, name, desc);
-}
-
-static int
-jvm_new_label_id(gen_proc_t * p)
-{
-       int label_id = p -> label_id;
-       p -> label_id += 1;
-       return label_id;
-}
-
-static char *
-jvm_get_label_name(int label_id)
-{
-       return new_string("L%i", label_id);
-}
-
-static void
-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;
-       }
-}
+push_item(gen_proc_t * p, oberon_item_t * item);
 
 static void
 jvm_generate_new(gen_proc_t * p, oberon_type_t * type, int num);
@@ -424,15 +44,15 @@ jvm_generate_array_initialization(gen_proc_t * p, oberon_type_t * arr)
        }
 
        struct {
-               gen_var_t * index;
-               gen_var_t * length;
+               int reg_index;
+               int reg_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 reg_dst;
+       reg_dst = jvm_alloc_register_untyped(p -> rf, false);
+       jvm_generate(p, 1, 0, "astore %i", reg_dst);
 
        /*
         * Входящие параметры заграблены.
@@ -453,42 +73,38 @@ jvm_generate_array_initialization(gen_proc_t * p, oberon_type_t * arr)
 
        for(int i = 0; i < dim; i++)
        {
-               loop[i].index = oberon_generator_new_var();
-               loop[i].length = oberon_generator_new_var();
+               loop[i].reg_index = jvm_alloc_register_untyped(p -> rf, false);
+               loop[i].reg_length = jvm_alloc_register_untyped(p -> rf, false);
                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(p, 1, 0, "istore %i", loop[i].reg_index);
 
-               jvm_generate_load(p, arr, dst);
+               jvm_generate(p, 0, 1, "aload %i", reg_dst);
                jvm_generate(p, 1, 1, "arraylength");
-               jvm_generate(p, 1, 0, "istore %i", loop[i].length -> reg);
+               jvm_generate(p, 1, 0, "istore %i", loop[i].reg_length);
 
                /* 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, 0, 1, "iload %i", loop[i].reg_index);
+               jvm_generate(p, 0, 1, "iload %i", loop[i].reg_length);
                jvm_generate(p, 2, 0, "if_icmpge L%i", loop[i].end);
        }
 
-       jvm_generate_load(p, arr, dst);
-       jvm_generate(p, 0, 1, "iload %i", loop[0].index -> reg);
+       jvm_generate(p, 0, 1, "aload %i", reg_dst);
+       jvm_generate(p, 0, 1, "iload %i", loop[0].reg_index);
        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(p, 0, 1, "iload %i", loop[i].reg_index);
        }
        jvm_generate_new(p, base, 0);
        jvm_generate(p, 3, 0, "aastore");
 
        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, "iinc %i 1", loop[i].reg_index);
                jvm_generate(p, 0, 0, "goto L%i", loop[i].start);
                jvm_generate_label(p, loop[i].end);
        }
@@ -582,19 +198,16 @@ jvm_generate_copy_array(gen_proc_t * p, oberon_type_t * arr)
        }
 
        struct {
-               gen_var_t * index;
-               gen_var_t * length;
+               int reg_index;
+               int reg_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 reg_dst = jvm_alloc_register_untyped(p -> rf, false);
+       int reg_src = jvm_alloc_register_untyped(p -> rf, false);
+       jvm_generate(p, 1, 0, "astore %i", reg_src);
+       jvm_generate(p, 1, 0, "astore %i", reg_dst);
 
        /*
         * Входящие параметры заграблены.
@@ -615,26 +228,22 @@ jvm_generate_copy_array(gen_proc_t * p, oberon_type_t * arr)
 
        for(int i = 0; i < dim; i++)
        {
-               loop[i].index = oberon_generator_new_var();
-               loop[i].length = oberon_generator_new_var();
+               loop[i].reg_index = jvm_alloc_register_untyped(p -> rf, false);
+               loop[i].reg_length = jvm_alloc_register_untyped(p -> rf, false);
                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(p, 1, 0, "istore %i", loop[i].reg_index);
 
-               jvm_generate_load(p, arr, src);
+               jvm_generate(p, 0, 1, "aload %i", reg_src);
                jvm_generate(p, 1, 1, "arraylength");
-               jvm_generate(p, 1, 0, "istore %i", loop[i].length -> reg);
+               jvm_generate(p, 1, 0, "istore %i", loop[i].reg_length);
 
                /* 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, 0, 1, "iload %i", loop[i].reg_index);
+               jvm_generate(p, 0, 1, "iload %i", loop[i].reg_length);
                jvm_generate(p, 2, 0, "if_icmpge L%i", loop[i].end);
        }
 
@@ -642,17 +251,17 @@ jvm_generate_copy_array(gen_proc_t * p, oberon_type_t * arr)
        {
                /* Получаем записи по индексам ( -- dst src ) */
 
-               jvm_generate_load(p, arr, dst);
+               jvm_generate(p, 0, 1, "aload %i", reg_dst);
                for(int i = 0; i < dim; i++)
                {
-                       jvm_generate(p, 0, 1, "iload %i", loop[i].index -> reg);
+                       jvm_generate(p, 0, 1, "iload %i", loop[i].reg_index);
                        jvm_generate(p, 2, 1, "aaload");
                }
 
-               jvm_generate_load(p, arr, src);
+               jvm_generate(p, 0, 1, "aload %i", reg_src);
                for(int i = 0; i < dim; i++)
                {
-                       jvm_generate(p, 0, 1, "iload %i", loop[i].index -> reg);
+                       jvm_generate(p, 0, 1, "iload %i", loop[i].reg_index);
                        jvm_generate(p, 2, 1, "aaload");
                }
 
@@ -666,20 +275,20 @@ jvm_generate_copy_array(gen_proc_t * p, oberon_type_t * arr)
 
                /* Получаем массивы и индексы ( -- dst i src i ) */
 
-               jvm_generate_load(p, arr, dst);
-               jvm_generate(p, 0, 1, "iload %i", loop[0].index -> reg);
+               jvm_generate(p, 0, 1, "aload %i", reg_dst);
+               jvm_generate(p, 0, 1, "iload %i", loop[0].reg_index);
                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(p, 0, 1, "iload %i", loop[i].reg_index);
                }
 
-               jvm_generate_load(p, arr, src);
-               jvm_generate(p, 0, 1, "iload %i", loop[0].index -> reg);
+               jvm_generate(p, 0, 1, "aload %i", reg_src);
+               jvm_generate(p, 0, 1, "iload %i", loop[0].reg_index);
                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(p, 0, 1, "iload %i", loop[i].reg_index);
                }
 
                /* Копируем значения ( dst i src i -- ) */
@@ -689,7 +298,7 @@ jvm_generate_copy_array(gen_proc_t * p, oberon_type_t * arr)
 
        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, "iinc %i 1", loop[i].reg_index);
                jvm_generate(p, 0, 0, "goto L%i", loop[i].start);
                jvm_generate_label(p, loop[i].end);
        }
@@ -703,13 +312,6 @@ jvm_generate_push_procedure_pointer(gen_proc_t * p, oberon_object_t * proc)
        jvm_generate(p, 0, 1, "getstatic %s/pointer %s", full_name, desc);
 }
 
-// ==========================================
-// ==========================================
-// ==========================================
-
-static void
-push_item(gen_proc_t * p, oberon_item_t * item);
-
 void
 oberon_generator_init_context(oberon_context_t * ctx)
 {
@@ -793,36 +395,34 @@ oberon_generate_procedure_pointer_class(oberon_object_t * proc)
 
        signature = jvm_get_procedure_signature(proc -> type);
 
-       gen_proc_t * p;
-       gen_var_t * this_v;
-
-       p = jvm_create_proc(class);
+       gen_proc_t * p = jvm_create_proc(class);
        jvm_generate_function_header(p, "public", "invoke", signature);
+       jvm_alloc_register_untyped(p -> rf, false);
 
-       this_v = oberon_generator_new_var();
-       jvm_generate_and_init_local_var(this_v, p, false);
-
-       gen_var_t * v;
        int use_size = 0;
        int num = proc -> type -> num_decl;
-       oberon_object_t * arg = proc -> type -> decl;
+       oberon_object_t * param = proc -> type -> decl;
        for(int i = 0; i < num; i++)
        {
-               v = oberon_generator_new_var();
-               bool wide = jvm_is_wide_type(arg -> type);
-               char * desc = jvm_get_descriptor(arg -> type);
-               jvm_generate_and_init_named_local_var(v, p, wide, arg -> name, desc);
-
-               jvm_generate_load(p, arg -> type, v);
-
-               use_size += (wide) ? (2) : (1);
-
-               arg = arg -> next;
+               gen_var_t * v = oberon_generator_new_var();
+               gen_type_t * t = param -> type -> gen_type;
+               use_size += t -> cell_size;
+               if(param -> class == OBERON_CLASS_VAR_PARAM)
+               {
+                       jvm_generate_and_init_var_param(p, v, param -> name, t);
+                       jvm_generate_ldst_prepare(p, v);
+               }
+               else
+               {
+                       jvm_generate_and_init_named_local_var(p, v, param -> name, t);
+                       jvm_generate_load(p, v);
+               }
+               param = param -> next;
        }
 
+       
        char * full_name = jvm_get_field_full_name(proc);
        int cell_size = jvm_cell_size_for_type(proc -> type -> base);
-
        jvm_generate(p, use_size, cell_size, "invokestatic %s%s", full_name, signature);
 
        if(proc -> type -> base -> class == OBERON_TYPE_VOID)
@@ -876,12 +476,22 @@ oberon_generator_init_type(oberon_context_t * ctx, oberon_type_t * type)
        memset(t, 0, sizeof *t);
        type -> gen_type = t;
 
+       if(type -> class != OBERON_TYPE_VOID)
+       {
+               t -> wide = jvm_is_wide_type(type);
+               t -> prefix = jvm_get_prefix(type);
+               t -> postfix = jvm_get_postfix(type);
+       }
+       t -> cell_size = jvm_cell_size_for_type(type);
+       t -> desc = jvm_get_descriptor(type);
+
        switch(type -> class)
        {
                case OBERON_TYPE_VOID:
                case OBERON_TYPE_INTEGER:
                case OBERON_TYPE_BOOLEAN:
                case OBERON_TYPE_ARRAY:
+               case OBERON_TYPE_POINTER:
                case OBERON_TYPE_REAL:
                case OBERON_TYPE_CHAR:
                case OBERON_TYPE_STRING:
@@ -896,8 +506,6 @@ oberon_generator_init_type(oberon_context_t * ctx, oberon_type_t * type)
                case OBERON_TYPE_PROCEDURE:
                        oberon_generate_procedure_class(type);
                        break;
-               case OBERON_TYPE_POINTER:
-                       break;
                default:
                        gen_error("oberon_generator_init_type: unk calss %i", type -> class);
                        break;
@@ -914,10 +522,10 @@ oberon_generator_init_record(oberon_context_t * ctx, oberon_type_t * rec)
        oberon_object_t * field = rec -> decl;
        for(int i = 0; i < num; i++)
        {
-               gen_var_t * v = field -> gen_var;
                char * name = field -> name;
-               char * desc = jvm_get_descriptor(field -> type);
-               jvm_generate_and_init_field(v, class, "public", name, desc);
+               gen_var_t * v = field -> gen_var;
+               gen_type_t * t = field -> type -> gen_type;
+               jvm_generate_and_init_field(class, v, name, t);
                field = field -> next;
        }
 
@@ -939,12 +547,16 @@ oberon_generator_init_record(oberon_context_t * ctx, oberon_type_t * rec)
        field = rec -> decl;
        for(int i = 0; i < num; i++)
        {
+               jvm_generate(p, 0, 1, "aload_0");
+               jvm_generate_variable_initialization(p, field -> gen_var);
+
                if(field -> type -> class == OBERON_TYPE_RECORD
                        || field -> type -> class == OBERON_TYPE_ARRAY)
                {
                        jvm_generate(p, 0, 1, "aload_0");
+                       jvm_generate_ldst_prepare(p, field -> gen_var);
                        jvm_generate_new(p, field -> type, 0);
-                       jvm_generate_store(p, field -> type, field -> gen_var);
+                       jvm_generate_store(p, field -> gen_var);
                }
                field = field -> next;
        }
@@ -956,37 +568,37 @@ oberon_generator_init_record(oberon_context_t * ctx, oberon_type_t * rec)
        p = jvm_create_proc(class);
        gen_var_t * copy_dst = oberon_generator_new_var();
        gen_var_t * copy_src = oberon_generator_new_var();
-       char * desc = jvm_get_descriptor(rec);
-       char * signature = new_string("(%s%s)V", desc, desc);
+       char * signature = new_string("(%s%s)V", rec -> gen_type -> desc, rec -> gen_type -> desc);
        jvm_generate_function_header(p, "public static", "$COPY$", signature);
-       jvm_generate_and_init_named_local_var(copy_dst, p, false, "dst", desc);
-       jvm_generate_and_init_named_local_var(copy_src, p, false, "src", desc);
+       jvm_generate_and_init_named_local_var(p, copy_dst, "dst", rec -> gen_type);
+       jvm_generate_and_init_named_local_var(p, copy_src, "src", rec -> gen_type);
        num = rec -> num_decl;
        field = rec -> decl;
        for(int i = 0; i < num; i++)
        {
                if(field -> type -> class == OBERON_TYPE_RECORD)
                {
-                       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_load(p, copy_dst);
+                       jvm_generate_load(p, field -> gen_var);
+                       jvm_generate_load(p, copy_src);
+                       jvm_generate_load(p, field -> gen_var);
                        jvm_generate_copy_record(p, field -> type);
                }
                else if(field -> type -> class == OBERON_TYPE_ARRAY)
                {
-                       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_load(p, copy_dst);
+                       jvm_generate_load(p, field -> gen_var);
+                       jvm_generate_load(p, copy_src);
+                       jvm_generate_load(p, field -> gen_var);
                        jvm_generate_copy_array(p, field -> type);
                }
                else
                {
-                       jvm_generate_load(p, rec, copy_dst);
-                       jvm_generate_load(p, rec, copy_src);
-                       jvm_generate_load(p, field -> type, field -> gen_var);
-                       jvm_generate_store(p, field -> type, field -> gen_var);
+                       jvm_generate_load(p, copy_dst);
+                       jvm_generate_ldst_prepare(p, field -> gen_var);
+                       jvm_generate_load(p, copy_src);
+                       jvm_generate_load(p, field -> gen_var);
+                       jvm_generate_store(p, field -> gen_var);
                }
                field = field -> next;
        }
@@ -1008,12 +620,9 @@ oberon_generator_init_var(oberon_context_t * ctx, oberon_object_t * var)
        struct gen_class * class;
        class = m -> class;
 
-       char * desc;
        switch(var -> class)
        {
                case OBERON_CLASS_VAR_PARAM:
-                       gen_error("generator: VAR-parameters not implemented");
-                       break;
                case OBERON_CLASS_PARAM:
                        /* Заполняется при генерации функции */
                        /* смотри jvm_init_local_object() */
@@ -1025,10 +634,9 @@ oberon_generator_init_var(oberon_context_t * ctx, oberon_object_t * var)
                case OBERON_CLASS_VAR:
                        /* Локальные заполняются при генерации функции */
                        /* смотри jvm_init_local_object() */
-                       if(var -> local == 0)
+                       if(var -> local == false)
                        {
-                               desc = jvm_get_descriptor(var -> type);
-                               jvm_generate_and_init_global_var(v, class, "public", var -> name, desc);
+                               jvm_generate_and_init_global_var(class, v, var -> name, var -> type -> gen_type);
                        }
                        break;
                default:
@@ -1051,10 +659,7 @@ oberon_generator_init_temp_var(oberon_context_t * ctx, oberon_object_t * var)
        gen_proc_t * p;
        p = m -> class -> p;
 
-       bool wide;
-       wide = jvm_is_wide_type(var -> type);
-
-       jvm_generate_and_init_local_var(v, p, wide);
+       jvm_generate_and_init_local_var(p, v, var -> type -> gen_type);
 }
 
 void
@@ -1067,8 +672,10 @@ oberon_generator_init_proc(oberon_context_t * ctx, oberon_object_t * proc)
        {
                gen_error("generator: local procedures not implemented");
        }
-
-       oberon_generate_procedure_pointer_class(proc);
+       else
+       {
+               oberon_generate_procedure_pointer_class(proc);
+       }
 }
 
 void
@@ -1116,11 +723,13 @@ oberon_generate_begin_module(oberon_context_t * ctx)
        {
                if(x -> class == OBERON_CLASS_VAR)
                {
+                       jvm_generate_variable_initialization(p, x -> gen_var);
                        if(x -> type -> class == OBERON_TYPE_ARRAY
                                || x -> type -> class == OBERON_TYPE_RECORD)
                        {
+                               jvm_generate_ldst_prepare(p, x -> gen_var);
                                jvm_generate_new(p, x -> type, 0);
-                               jvm_generate_store(p, x -> type, x -> gen_var);
+                               jvm_generate_store(p, x -> gen_var);
                        }
                }
 
@@ -1138,35 +747,6 @@ oberon_generate_end_module(oberon_context_t * ctx)
        jvm_generate_function_end(class -> p);
 }
 
-static void
-jvm_init_local_object(gen_proc_t * p, oberon_object_t * x)
-{
-       gen_var_t * v;
-       bool wide;
-       char * desc;
-       struct gen_class * class;
-
-       v = x -> gen_var;
-       class = p -> class;
-       wide = jvm_is_wide_type(x -> type);
-       desc = jvm_get_descriptor(x -> type);
-
-       // Убеждаемся что сейчас находимся в функции
-       assert(class -> p);
-       assert(x -> local);
-
-       switch(x -> class)
-       {
-               case OBERON_CLASS_VAR:
-               case OBERON_CLASS_PARAM:
-                       jvm_generate_and_init_named_local_var(v, p, wide, x -> name, desc);
-                       break;
-               default:
-                       gen_error("jvm_init_local_object: wat");
-                       break;
-       }
-}
-
 /*
  * Генерирует код для получения размера измерения массива
  * Аналог Обероновского LEN(v, n); где n = 0 - первое измерение.
@@ -1188,13 +768,15 @@ jvm_generate_array_len(gen_proc_t * p, int dim)
 static void
 jvm_generate_array_duplicate_and_replace(gen_proc_t * p, gen_var_t * v, oberon_type_t * arr)
 {
+       jvm_generate_ldst_prepare(p, v);
+
        int dim = 0;
        oberon_type_t * base = arr;
        while(base -> class == OBERON_TYPE_ARRAY)
        {
                if(base -> size == 0)
                {
-                       jvm_generate_load(p, arr, v);
+                       jvm_generate_load(p, v);
                        jvm_generate_array_len(p, dim);
                        dim += 1;
                }
@@ -1203,19 +785,77 @@ jvm_generate_array_duplicate_and_replace(gen_proc_t * p, gen_var_t * v, oberon_t
 
        jvm_generate_new(p, arr, dim);
        jvm_generate(p, 1, 2, "dup");
-       jvm_generate_load(p, arr, v);
+       jvm_generate_load(p, v);
        jvm_generate_copy_array(p, arr);
-       jvm_generate_store(p, arr, v);
+       jvm_generate_store(p, v);
 }
 
 static void
 jvm_generate_record_duplicate_and_replace(gen_proc_t * p, gen_var_t * v, oberon_type_t * rec)
 {
+       jvm_generate_ldst_prepare(p, v);
        jvm_generate_new(p, rec, 0);
        jvm_generate(p, 1, 2, "dup");
-       jvm_generate_load(p, rec, v);
+       jvm_generate_load(p, v);
        jvm_generate_copy_record(p, rec);
-       jvm_generate_store(p, rec, v);
+       jvm_generate_store(p, v);
+}
+
+static void
+jvm_init_local_object(gen_proc_t * p, oberon_object_t * x)
+{
+       gen_var_t * v;
+       struct gen_class * class;
+
+       v = x -> gen_var;
+       class = p -> class;
+
+       // Убеждаемся что сейчас находимся в функции
+       assert(class -> p);
+       assert(x -> local);
+
+       switch(x -> class)
+       {
+               case OBERON_CLASS_VAR_PARAM:
+                       jvm_generate_and_init_var_param(p, v, x -> name, x -> type -> gen_type);
+                       break;
+               case OBERON_CLASS_VAR:
+               case OBERON_CLASS_PARAM:
+                       jvm_generate_and_init_named_local_var(p, v, x -> name, x -> type -> gen_type);
+                       break;
+               default:
+                       gen_error("jvm_init_local_object: wat");
+                       break;
+       }
+}
+
+static void
+jvm_generate_local_initialization(gen_proc_t * p, oberon_object_t * x)
+{
+       gen_var_t * v;
+       struct gen_class * class;
+
+       v = x -> gen_var;
+       class = p -> class;
+
+       // Убеждаемся что сейчас находимся в функции
+       assert(class -> p);
+       assert(x -> local);
+
+       switch(x -> class)
+       {
+               case OBERON_CLASS_VAR_PARAM:
+                       break;
+               case OBERON_CLASS_VAR:
+                       jvm_generate_variable_initialization(p, v);
+                       break;
+               case OBERON_CLASS_PARAM:
+                       jvm_generate_param_initialization(p, v);
+                       break;
+               default:
+                       gen_error("jvm_generate_local_initialization: wat");
+                       break;
+       }
 }
 
 void
@@ -1230,13 +870,21 @@ oberon_generate_begin_proc(oberon_context_t * ctx, oberon_object_t * proc)
        jvm_generate_function_header(p, "public static", proc -> name, signature);
 
        /* Выделение регистров под параметры и переменные */
-       oberon_object_t * var = proc -> type -> decl;
+       oberon_object_t * var = proc -> scope -> list -> next;
        while(var)
        {
                jvm_init_local_object(p, var);
                var = var -> next;
        }
 
+       /* Инициализация */
+       var = proc -> scope -> list -> next;
+       while(var)
+       {
+               jvm_generate_local_initialization(p, var);
+               var = var -> next;
+       }
+
        /* Копирование статических/открытых массивов и записей */
        var = proc -> type -> decl;
        while(var)
@@ -1332,6 +980,30 @@ oberon_generate_branch(oberon_context_t * ctx, oberon_expr_t * cond, bool gotoif
        }
 }
 
+static void
+push_varptr(gen_proc_t * p, oberon_expr_t * expr)
+{
+       assert(expr -> is_item);
+
+       switch(expr -> item.mode)
+       {
+               case MODE_VAR:
+                       jvm_generate_ldst_prepare(p, expr -> item.var -> gen_var);
+                       break;
+               case MODE_INDEX:
+                       push_item(p, (oberon_item_t *) expr -> item.parent);
+                       push_expr(p, expr -> item.args);
+                       break;
+               case MODE_FIELD:
+                       push_item(p, (oberon_item_t *) expr -> item.parent);
+                       jvm_generate_ldst_prepare(p, expr -> item.var -> gen_var);
+                       break;
+               default:
+                       gen_error("push_varptr: wat %i", expr -> item.mode);
+                       break;
+       }
+}
+
 static void
 jvm_generate_call_proc(gen_proc_t * p, oberon_item_t * desig)
 {
@@ -1366,11 +1038,21 @@ jvm_generate_call_proc(gen_proc_t * p, oberon_item_t * desig)
 
        int num = desig -> num_args;
        oberon_expr_t * arg = desig -> args;
+       oberon_object_t * param = procsig -> decl;
        for(int i = 0; i < num; i++)
        {
-               args_cells += jvm_cell_size_for_type(arg -> result);
-               push_expr(p, arg);
+               if(param -> class == OBERON_CLASS_VAR_PARAM)
+               {
+                       args_cells += 2;
+                       push_varptr(p, arg);
+               }
+               else
+               {
+                       args_cells += jvm_cell_size_for_type(arg -> result);
+                       push_expr(p, arg);
+               }
                arg = arg -> next;
+               param = param -> next;
        }
 
        if(direct_call)
@@ -1468,7 +1150,7 @@ push_item(gen_proc_t * p, oberon_item_t * item)
                        }
                        else
                        {
-                               jvm_generate_load(p, item -> result, item -> var -> gen_var);
+                               jvm_generate_load(p, item -> var -> gen_var);
                        }
                        break;
                case MODE_INTEGER:
@@ -1494,7 +1176,7 @@ push_item(gen_proc_t * p, oberon_item_t * item)
                case MODE_FIELD:
                        assert(item -> parent -> is_item);
                        push_item(p, (oberon_item_t *) item -> parent);
-                       jvm_generate_load(p, item -> result, item -> var -> gen_var);
+                       jvm_generate_load(p, item -> var -> gen_var);
                        break;
                case MODE_DEREF:
                        /* Все объекты в jvm представляются как указатели */
@@ -1524,12 +1206,10 @@ jvm_generate_logical_not(gen_proc_t * p)
 {
        int label_done = jvm_new_label_id(p);
        int label_false = jvm_new_label_id(p);
-       char * label_name_done = jvm_get_label_name(label_done);
-       char * label_name_false = jvm_get_label_name(label_false);
 
-       jvm_generate(p, 1, 0, "ifne %s", label_name_false);
+       jvm_generate(p, 1, 0, "ifne L%i", label_false);
        jvm_generate(p, 0, 1, "iconst_1");
-       jvm_generate(p, 0, 0, "goto %s", label_name_done);
+       jvm_generate(p, 0, 0, "goto L%i", label_done);
        jvm_generate_label(p, label_false);
        jvm_generate(p, 0, 1, "iconst_0");
        jvm_generate_label(p, label_done);
@@ -1684,15 +1364,13 @@ jvm_generate_logical_or(gen_proc_t * p, oberon_expr_t * a, oberon_expr_t * b)
 {
        int label_calc_b = jvm_new_label_id(p);
        int label_done = jvm_new_label_id(p);
-       char * label_name_calc_b = jvm_get_label_name(label_calc_b);
-       char * label_name_done = jvm_get_label_name(label_done);
 
        /* a OR b -- если a, то TRUE, иначе b */
 
        push_expr(p, a);
-       jvm_generate(p, 1, 0, "ifeq %s", label_name_calc_b);
+       jvm_generate(p, 1, 0, "ifeq L%i", label_calc_b);
        jvm_generate(p, 0, 1, "iconst_1");
-       jvm_generate(p, 0, 0, "goto %s", label_name_done);
+       jvm_generate(p, 0, 0, "goto L%i", label_done);
        jvm_generate_label(p, label_calc_b);
        push_expr(p, b);
        jvm_generate_label(p, label_done);
@@ -1703,15 +1381,13 @@ jvm_generate_logical_and(gen_proc_t * p, oberon_expr_t * a, oberon_expr_t * b)
 {
        int label_false = jvm_new_label_id(p);
        int label_done = jvm_new_label_id(p);
-       char * label_name_false = jvm_get_label_name(label_false);
-       char * label_name_done = jvm_get_label_name(label_done);
 
        /* a AND b -- если a, то b, иначе FALSE */
 
        push_expr(p, a);
-       jvm_generate(p, 1, 0, "ifeq %s", label_name_false);
+       jvm_generate(p, 1, 0, "ifeq L%i", label_false);
        push_expr(p, b);
-       jvm_generate(p, 0, 0, "goto %s", label_name_done);
+       jvm_generate(p, 0, 0, "goto L%i", label_done);
        jvm_generate_label(p, label_false);
        jvm_generate(p, 0, 1, "iconst_0");
        jvm_generate_label(p, label_done);
@@ -1725,53 +1401,51 @@ jvm_generate_range(gen_proc_t * p, oberon_expr_t * a, oberon_expr_t * b)
 
        char prefix;
        int cell_size;
-       oberon_type_t * t;
+       oberon_type_t * type;
        gen_var_t * ra;
        gen_var_t * rb;
        int label_else;
        int label_end;
-       bool wide;
 
-       t = a -> result;
-       cell_size = jvm_cell_size_for_type(t);
-       prefix = jvm_get_prefix(t);
+       type = a -> result;
+       cell_size = jvm_cell_size_for_type(type);
+       prefix = jvm_get_prefix(type);
 
        if(b == NULL)
        {
-               jvm_generate_push_int_size(p, 1, t -> size);
+               jvm_generate_push_int_size(p, 1, type -> size);
                push_expr(p, a);
                jvm_generate(p, 2 * cell_size, cell_size, "%cshl", prefix);
        }
        else
        {
-               wide = jvm_is_wide_type(t);
                ra = oberon_generator_new_var();
                rb = oberon_generator_new_var();
-               jvm_generate_and_init_local_var(ra, p, wide);
-               jvm_generate_and_init_local_var(rb, p, wide);
+               jvm_generate_and_init_local_var(p, ra, type -> gen_type);
+               jvm_generate_and_init_local_var(p, rb, type -> gen_type);
                label_else = jvm_new_label_id(p);
                label_end = jvm_new_label_id(p);
 
                push_expr(p, a);
-               jvm_generate_store(p, t, ra);
+               jvm_generate_store(p, ra);
                push_expr(p, b);
-               jvm_generate_store(p, t, rb);
+               jvm_generate_store(p, rb);
 
-               jvm_generate_load(p, t, ra);
-               jvm_generate_load(p, t, rb);
+               jvm_generate_load(p, ra);
+               jvm_generate_load(p, rb);
                jvm_generate(p, 2 * cell_size, 0, "if_%ccmpgt L%i", prefix, label_else);
 
-               jvm_generate_push_int_size(p, 2, t -> size);
-               jvm_generate_load(p, t, rb);
+               jvm_generate_push_int_size(p, 2, type -> size);
+               jvm_generate_load(p, rb);
                jvm_generate(p, 2 * cell_size, cell_size, "%cshl", prefix);
-               jvm_generate_push_int_size(p, 2, t -> size);
-               jvm_generate_load(p, t, ra);
+               jvm_generate_push_int_size(p, 2, type -> size);
+               jvm_generate_load(p, ra);
                jvm_generate(p, 2 * cell_size, cell_size, "%cshl", prefix);
                jvm_generate(p, 2 * cell_size, cell_size, "%csub", prefix);
                jvm_generate(p, 0, 0, "goto L%i", label_end);
 
                jvm_generate_label(p, label_else);
-               jvm_generate_push_int_size(p, 0, t -> size);
+               jvm_generate_push_int_size(p, 0, type -> size);
                jvm_generate_label(p, label_end);
        }
 
@@ -1908,8 +1582,9 @@ store_expr(gen_proc_t * p, oberon_expr_t * dst, oberon_expr_t * src)
        else switch(item -> mode)
        {
                case MODE_VAR:
+                       jvm_generate_ldst_prepare(p, item -> var -> gen_var);
                        push_expr(p, src);
-                       jvm_generate_store(p, src -> result, item -> var -> gen_var);
+                       jvm_generate_store(p, item -> var -> gen_var);
                        break;
                case MODE_INDEX:
                        ;
@@ -1924,8 +1599,9 @@ store_expr(gen_proc_t * p, oberon_expr_t * dst, oberon_expr_t * src)
                case MODE_FIELD:
                        assert(item -> parent -> is_item);
                        push_item(p, (oberon_item_t *) item -> parent);
+                       jvm_generate_ldst_prepare(p, item -> var -> gen_var);
                        push_expr(p, src);
-                       jvm_generate_store(p, src -> result, item -> var -> gen_var);
+                       jvm_generate_store(p, item -> var -> gen_var);
                        break;
                default:
                        gen_error("store_expr: unk mode %i", item -> mode);
index 3095a49070d204df2acb0fb2fa7a89ddfc9abc2a..242aa70b10f8f2b17b21926b06de0e9192b7021c 100644 (file)
@@ -30,7 +30,9 @@ enum gen_storage
        JVM_STORAGE_UNKNOWN,
        JVM_STORAGE_REGISTER,
        JVM_STORAGE_STATIC,
-       JVM_STORAGE_FIELD
+       JVM_STORAGE_FIELD,
+       JVM_STORAGE_LOCAL,
+       JVM_STORAGE_VARPTR
 };
 
 
@@ -46,14 +48,20 @@ struct gen_type_t
 {
        int rec_id;
        struct gen_class * class;
+
+       bool wide;
+       char prefix;
+       char postfix;
+       char * desc;
+       int cell_size;
 };
 
 struct gen_var_t
 {
        enum gen_storage storage;
+       gen_type_t * type;
        int reg;
        char * full_name;
-       char * desc;
 };
 
 struct gen_context_t
index e4b9157d151cafa6075c86bbc1a07ebf2e845bef..58eb67c3eb72562294074f972fde2e15f68b5fec 100644 (file)
@@ -1223,13 +1223,21 @@ oberon_autocast_call(oberon_context_t * ctx, oberon_item_t * desig)
        {
                if(param -> class == OBERON_CLASS_VAR_PARAM)
                {
+                       if(arg -> result != param -> type)
+                       {
+                               oberon_error(ctx, "incompatible type");
+                       }
                        if(arg -> read_only)
                        {
                                oberon_error(ctx, "assign to read-only var");
                        }
+                       casted[i] = arg;
+               }
+               else
+               {
+                       casted[i] = oberon_autocast_to(ctx, arg, param -> type);
                }
 
-               casted[i] = oberon_autocast_to(ctx, arg, param -> type);
                arg = arg -> next;
                param = param -> next;
        }
index dab2914ca12507682c8a29122dd5498aebb221b1..cd28a2109e803224afb6a10ca56baaf18184be64 100644 (file)
@@ -8,34 +8,24 @@ static char source_test[] =
        "(* Main module *)"
        "MODULE Test;"
        "IMPORT Out;"
+       ""
        "TYPE"
-       "  R1 = POINTER TO R1Desc;"
-       "  R1Desc = RECORD a : INTEGER; END;"
-       "  R2 = POINTER TO R2Desc;"
-       "  R2Desc = RECORD (R1Desc) b : INTEGER; END;"
-       "  Y1 = POINTER TO Y1Desc;"
-       "  Y1Desc = RECORD END;"
+       "  R = RECORD iii : INTEGER; END;"
        ""
        "VAR"
-       "  r1 : R1;"
-       "  r2 : R2;"
-       "  y1 : Y1;"
+       "  i : INTEGER;"
+       "  a : ARRAY 3 OF INTEGER;"
+       "  r : R;"
        ""
+       "PROCEDURE X(VAR x : INTEGER);"
        "BEGIN"
-       "  NEW(r1);"
-       "  NEW(r2);"
-       "  NEW(y1);"
-       "  r1 := r2;"
-       "  Out.Open;"
-       "  WITH r1 : R2 DO"
-       "    r1.b := 666;"
-       "    Out.String('R2 branch');"
-       "  | y1 : Y1 DO"
-       "    Out.String('Y1 branch');"
-       "  ELSE"
-       "    Out.String('Something else');"
-       "  END;"
-       "  Out.Ln;"
+       "  x := x * 666;"
+       "END X;"
+       ""
+       "BEGIN;"
+       "  r.iii := 2;"
+       "  X(r.iii);"
+       "  Out.Int(r.iii, 0); Out.Ln;"
        "END Test."
 ;