From: DeaDDooMER Date: Thu, 27 Jul 2017 20:49:48 +0000 (+0300) Subject: JVM: Добавлена инициализация статических полей записи при и использовании NEW X-Git-Url: http://deadsoftware.ru/gitweb?a=commitdiff_plain;h=3c5fc198fb0f72bd8ec70aef8f2b4987bb702f79;p=dsw-obn.git JVM: Добавлена инициализация статических полей записи при и использовании NEW --- diff --git a/src/backends/jvm/generator-jvm.c b/src/backends/jvm/generator-jvm.c index 7c426d5..99a4673 100644 --- a/src/backends/jvm/generator-jvm.c +++ b/src/backends/jvm/generator-jvm.c @@ -71,6 +71,7 @@ jvm_create_class(char * full_name) 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); @@ -84,13 +85,6 @@ jvm_destroy_class(struct gen_class * class) fclose(class -> fp); } -static void -jvm_generate_field(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); -} - static void jvm_stack_push(gen_proc_t * p, unsigned size) { @@ -211,6 +205,106 @@ jvm_generate_label(gen_proc_t * p, int label_id) jvm_generate(p, 0, 0, "L%i:", label_id); } +static void +jvm_generate_new_static(gen_proc_t * p, oberon_type_t * type) +{ + char * cname; + + switch(type -> class) + { + case OBERON_TYPE_INTEGER: + case OBERON_TYPE_BOOLEAN: + case OBERON_TYPE_PROCEDURE: + case OBERON_TYPE_REAL: + case OBERON_TYPE_POINTER: + /* ничего не надо делать при статической инициализации */ + break; + case OBERON_TYPE_RECORD: + cname = jvm_get_class_full_name(type); + jvm_generate(p, 0, 1, "new %s", cname); + jvm_generate(p, 1, 2, "dup"); + jvm_generate(p, 1, 0, "invokespecial %s/()V", cname); + break; + case OBERON_TYPE_ARRAY: + gen_error("jvm_generate_new_static: TODO array"); + break; + default: + gen_error("jvm_generate_new_static: unk type class %i", type -> class); + 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 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); +} + // ========================================== // ========================================== // ========================================== @@ -311,35 +405,6 @@ oberon_generator_init_type(oberon_context_t * ctx, oberon_type_t * type) } } -static void -jvm_generate_object(struct gen_class * class, oberon_object_t * x) -{ - char * name; - char * desc; - - name = x -> name; - desc = jvm_get_descriptor(x -> type); - switch(x -> class) - { - case OBERON_CLASS_VAR: - if(x -> local == 0) - { - jvm_generate_field(class, "public static", name, desc); - } - else - { - gen_error("jvm_generate_object: local variable as class field? wat"); - } - break; - case OBERON_CLASS_FIELD: - jvm_generate_field(class, "public", name, desc); - break; - default: - gen_error("jvm_generate_object: unk class %i", x -> class); - break; - } -} - void oberon_generator_init_record(oberon_context_t * ctx, oberon_type_t * rec) { @@ -350,15 +415,36 @@ 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++) { - jvm_generate_object(class, field); + 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); field = field -> next; } - fprintf(class -> fp, ".method public ()V\n"); - fprintf(class -> fp, " aload_0\n"); - fprintf(class -> fp, " invokespecial java/lang/Object/()V\n"); - fprintf(class -> fp, " return\n"); - fprintf(class -> fp, ".end method\n"); + gen_proc_t * p = jvm_create_proc(class); + + jvm_generate_function_header(p, "public", "", "()V"); + jvm_alloc_register_untyped(p -> rf, false); + jvm_generate(p, 0, 1, "aload_0"); + jvm_generate(p, 1, 0, "invokespecial java/lang/Object/()V"); + + num = rec -> num_decl; + field = rec -> decl; + for(int i = 0; i < num; i++) + { + if(field -> type -> class == OBERON_TYPE_RECORD + || field -> type -> class == OBERON_TYPE_ARRAY) + { + jvm_generate(p, 0, 1, "aload_0"); + jvm_generate_new_static(p, field -> type); + jvm_generate_store(p, field -> type, field -> gen_var); + } + field = field -> next; + } + + jvm_generate(p, 0, 0, "return"); + jvm_generate_function_end(p); jvm_destroy_class(class); } @@ -366,8 +452,7 @@ oberon_generator_init_record(oberon_context_t * ctx, oberon_type_t * rec) void oberon_generator_init_var(oberon_context_t * ctx, oberon_object_t * var) { - gen_var_t * v = GC_MALLOC(sizeof *v); - memset(v, 0, sizeof *v); + gen_var_t * v = oberon_generator_new_var(); var -> gen_var = v; gen_module_t * m; @@ -376,16 +461,28 @@ 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() */ + break; case OBERON_CLASS_FIELD: + /* Заполняются при инициализации структуры */ + /* смотри oberon_generator_init_record() */ break; case OBERON_CLASS_VAR: - jvm_generate_object(class, var); + /* Локальные заполняются при генерации функции */ + /* смотри jvm_init_local_object() */ + if(var -> local == 0) + { + desc = jvm_get_descriptor(var -> type); + jvm_generate_and_init_global_var(v, class, "public", var -> name, desc); + } break; default: gen_error("oberon_generator_init_var: unk var class %i", var -> class); @@ -459,11 +556,13 @@ 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); // Убеждаемся что сейчас находимся в функции @@ -474,8 +573,7 @@ jvm_init_local_object(gen_proc_t * p, oberon_object_t * x) { case OBERON_CLASS_VAR: case OBERON_CLASS_PARAM: - v -> reg = jvm_alloc_register(p -> rf, x -> type); - fprintf(class -> fp, ".var %i is %s %s from start to end\n", v -> reg, x -> name, desc); + jvm_generate_and_init_named_local_var(v, p, wide, x -> name, desc); break; default: gen_error("jvm_init_local_object: wat"); @@ -594,41 +692,17 @@ jvm_push_var(gen_proc_t * p, oberon_object_t * var) } static void -jvm_generate_new_static(gen_proc_t * p, oberon_type_t * type, int num, oberon_expr_t * arg) +jvm_generate_expr_new_static(gen_proc_t * p, oberon_type_t * type, int num, oberon_expr_t * arg) { - //char * desc; - char * cname; - //desc = jvm_get_descriptor(type); - cname = jvm_get_class_full_name(type); - - switch(type -> class) - { - case OBERON_TYPE_INTEGER: - case OBERON_TYPE_BOOLEAN: - case OBERON_TYPE_PROCEDURE: - case OBERON_TYPE_REAL: - case OBERON_TYPE_POINTER: - /* ничего не надо делать при статической инициализации */ - break; - case OBERON_TYPE_RECORD: - jvm_generate(p, 0, 1, "new %s", cname); - jvm_generate(p, 1, 2, "dup"); - jvm_generate(p, 1, 0, "invokespecial %s/()V", cname); - break; - case OBERON_TYPE_ARRAY: - gen_error("jvm_generate_new_static: TODO array"); - break; - default: - gen_error("jvm_generate_new_static: unk type class %i", type -> class); - break; - } + assert(num == 0); + jvm_generate_new_static(p, type); } static void -jvm_generate_new_pointer(gen_proc_t * p, oberon_type_t * type, int num, oberon_expr_t * arg) +jvm_generate_expr_new_pointer(gen_proc_t * p, oberon_type_t * type, int num, oberon_expr_t * arg) { assert(type -> class == OBERON_TYPE_POINTER); - jvm_generate_new_static(p, type -> base, num, arg); + jvm_generate_expr_new_static(p, type -> base, num, arg); } static void @@ -665,7 +739,7 @@ push_item(gen_proc_t * p, oberon_item_t * item) jvm_generate(p, 0, 1, "aconst_null"); break; case MODE_NEW: - jvm_generate_new_pointer(p, item -> result, item -> num_args, item -> args); + jvm_generate_expr_new_pointer(p, item -> result, item -> num_args, item -> args); break; case MODE_REAL: jvm_generate_push_float(p, item -> real, item -> result -> size); @@ -902,6 +976,33 @@ push_expr(gen_proc_t * p, oberon_expr_t * expr) } } +static void +store_expr(gen_proc_t * p, oberon_expr_t * dst, oberon_expr_t * src) +{ + assert(dst -> is_item); + oberon_item_t * item = (oberon_item_t *) dst; + + switch(item -> mode) + { + case MODE_VAR: + push_expr(p, src); + jvm_generate_store(p, src -> result, item -> var -> gen_var); + break; + case MODE_INDEX: + gen_error("store_expr: TODO index"); + break; + case MODE_FIELD: + push_item(p, item -> parent); + push_expr(p, src); + jvm_generate_store(p, src -> result, item -> var -> gen_var); + break; + default: + gen_error("store_expr: unk mode %i", item -> mode); + break; + } +} + +/* static void store_expr(gen_proc_t * p, oberon_expr_t * dst, oberon_expr_t * src) { @@ -945,6 +1046,7 @@ store_expr(gen_proc_t * p, oberon_expr_t * dst, oberon_expr_t * src) break; } } +*/ void oberon_generate_assign(oberon_context_t * ctx, oberon_expr_t * src, oberon_expr_t * dst) diff --git a/src/backends/jvm/generator-jvm.h b/src/backends/jvm/generator-jvm.h index d5abe38..ad1b982 100644 --- a/src/backends/jvm/generator-jvm.h +++ b/src/backends/jvm/generator-jvm.h @@ -19,11 +19,18 @@ struct gen_stack struct gen_class { + char * full_name; FILE * fp; gen_proc_t * p; }; - +enum gen_storage +{ + JVM_STORAGE_UNKNOWN, + JVM_STORAGE_REGISTER, + JVM_STORAGE_STATIC, + JVM_STORAGE_FIELD +}; struct gen_proc_t @@ -42,12 +49,10 @@ struct gen_type_t struct gen_var_t { + enum gen_storage storage; int reg; -}; - -struct gen_block_t -{ - + char * full_name; + char * desc; }; struct gen_context_t diff --git a/src/test.c b/src/test.c index bbf6b39..0edbdf4 100644 --- a/src/test.c +++ b/src/test.c @@ -9,7 +9,10 @@ static char source_test[] = "MODULE Test;" "TYPE" " Rec = POINTER TO RecDesc;" - " RecDesc = RECORD x, y, z : INTEGER END;" + " RecDesc = RECORD" + " x, y, z : INTEGER;" + " r : RECORD xxx : INTEGER; END;" + " END;" "VAR" " a : INTEGER;" " r : Rec;" @@ -20,6 +23,7 @@ static char source_test[] = " r.x := a;" " r.y := r.x;" " r.z := r.y * 3;" + " r.r.xxx := 666;" "END Test." ;