X-Git-Url: https://deadsoftware.ru/gitweb?p=dsw-obn.git;a=blobdiff_plain;f=src%2Fbackends%2Fjvm%2Fgenerator-jvm.c;h=da8b06b29f5142a7ea9b25cdd2e6c8ed18a00bb8;hp=a107efc119eca8a22afc620cbc912e8e284f86fa;hb=55d9ee92b95dd306ac80fb643ed21d3b733395d7;hpb=3edc4e955c943735543e2c94ecd28f94d75b32fb diff --git a/src/backends/jvm/generator-jvm.c b/src/backends/jvm/generator-jvm.c index a107efc..da8b06b 100644 --- a/src/backends/jvm/generator-jvm.c +++ b/src/backends/jvm/generator-jvm.c @@ -11,392 +11,12 @@ #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);