From: DeaDDooMER Date: Sat, 29 Jul 2017 15:27:09 +0000 (+0300) Subject: JVM: Добавлено копирование массивов и записей переданных в процедуры со статическими... X-Git-Url: http://deadsoftware.ru/gitweb?a=commitdiff_plain;h=961fbb99dcba21ccb737db16c0cdb28d757a2de7;p=dsw-obn.git JVM: Добавлено копирование массивов и записей переданных в процедуры со статическими типами параметров (в том числе и копирование открытых массивов) --- diff --git a/src/backends/jvm/generator-jvm-basic.c b/src/backends/jvm/generator-jvm-basic.c index 5fabc31..d092f8e 100644 --- a/src/backends/jvm/generator-jvm-basic.c +++ b/src/backends/jvm/generator-jvm-basic.c @@ -190,6 +190,7 @@ jvm_get_field_full_name(oberon_object_t * x) switch(x -> class) { case OBERON_CLASS_VAR: + case OBERON_CLASS_PROC: return new_string("%s/%s", x -> module -> name, x -> name); case OBERON_CLASS_FIELD:; char * rec_name = jvm_get_class_full_name(x -> parent_type); diff --git a/src/backends/jvm/generator-jvm.c b/src/backends/jvm/generator-jvm.c index 895a5ae..dc79ea1 100644 --- a/src/backends/jvm/generator-jvm.c +++ b/src/backends/jvm/generator-jvm.c @@ -349,7 +349,8 @@ jvm_generate_array_initialization(gen_proc_t * p, oberon_type_t * arr) jvm_generate_and_init_local_var(dst, p, false); jvm_generate_store(p, arr, dst); - /* Входящие параметры заграблены. + /* + * Входящие параметры заграблены. * Теперь генерируем эквивалентный код: * int i = 0; * int len = dst.length @@ -510,7 +511,8 @@ jvm_generate_copy_array(gen_proc_t * p, oberon_type_t * arr) jvm_generate_store(p, arr, src); jvm_generate_store(p, arr, dst); - /* Входящие параметры заграблены. + /* + * Входящие параметры заграблены. * Теперь генерируем эквивалентный код: * int i = 0; * int len = dst.length @@ -551,12 +553,7 @@ jvm_generate_copy_array(gen_proc_t * p, oberon_type_t * arr) jvm_generate(p, 2, 0, "if_icmpge L%i", loop[i].end); } - if(base -> class == OBERON_TYPE_ARRAY) - { - // Вся эта шляпа уже должна знать о всех размерностях - gen_error("jvm_generate_copy_array: wat"); - } - else if(base -> class == OBERON_TYPE_RECORD) + if(base -> class == OBERON_TYPE_RECORD) { /* Получаем записи по индексам ( -- dst src ) */ @@ -825,7 +822,7 @@ oberon_generator_init_var(oberon_context_t * ctx, oberon_object_t * var) /* смотри oberon_generator_init_record() */ break; case OBERON_CLASS_VAR: - /* Локальные заполняются при генерации функции */ + /* Локальные заполняются при генерации функции */ /* смотри jvm_init_local_object() */ if(var -> local == 0) { @@ -946,6 +943,57 @@ jvm_init_local_object(gen_proc_t * p, oberon_object_t * x) } } +/* + * Генерирует код для получения размера измерения массива + * Аналог Обероновского LEN(v, n); где n = 0 - первое измерение. + * ( aref -- int ) + */ + +static void +jvm_generate_array_len(gen_proc_t * p, int dim) +{ + while(dim > 0) + { + jvm_generate(p, 0, 1, "iconst_0"); + jvm_generate(p, 2, 1, "aaload"); + dim -= 1; + } + jvm_generate(p, 1, 1, "arraylength"); +} + +static void +jvm_generate_array_duplicate_and_replace(gen_proc_t * p, gen_var_t * v, oberon_type_t * arr) +{ + 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_array_len(p, dim); + dim += 1; + } + base = base -> base; + } + + jvm_generate_new(p, arr, dim); + jvm_generate(p, 1, 2, "dup"); + jvm_generate_load(p, arr, v); + jvm_generate_copy_array(p, arr); + jvm_generate_store(p, arr, v); +} + +static void +jvm_generate_record_duplicate_and_replace(gen_proc_t * p, gen_var_t * v, oberon_type_t * rec) +{ + jvm_generate_new(p, rec, 0); + jvm_generate(p, 1, 2, "dup"); + jvm_generate_load(p, rec, v); + jvm_generate_copy_record(p, rec); + jvm_generate_store(p, rec, v); +} + void oberon_generate_begin_proc(oberon_context_t * ctx, oberon_object_t * proc) { @@ -955,15 +1003,33 @@ oberon_generate_begin_proc(oberon_context_t * ctx, oberon_object_t * proc) p = proc -> gen_proc; signature = jvm_get_procedure_signature(proc -> type); - jvm_generate_function_header(p, "public static", proc -> name, signature); + /* Выделение регистров под параметры и переменные */ oberon_object_t * var = proc -> type -> decl; while(var) { jvm_init_local_object(p, var); var = var -> next; } + + /* Копирование статических/открытых массивов и записей */ + var = proc -> type -> decl; + while(var) + { + if(var -> class == OBERON_CLASS_PARAM || var -> class == OBERON_CLASS_VAR_PARAM) + { + if(var -> type -> class == OBERON_TYPE_ARRAY) + { + jvm_generate_array_duplicate_and_replace(p, var -> gen_var, var -> type); + } + else if(var -> type -> class == OBERON_TYPE_RECORD) + { + jvm_generate_record_duplicate_and_replace(p, var -> gen_var, var -> type); + } + } + var = var -> next; + } } void diff --git a/src/test.c b/src/test.c index 6282321..2b9fd06 100644 --- a/src/test.c +++ b/src/test.c @@ -8,11 +8,26 @@ static char source_test[] = "(* Main module *)" "MODULE Test;" "TYPE" - " RecDesc = RECORD a : ARRAY 3, 5 OF INTEGER; END;" + " Arr = ARRAY 32, 768 OF INTEGER;" + " RecDesc = RECORD x, y, z : INTEGER; END;" + "" "VAR" - " a, b : ARRAY 3, 6 OF RecDesc;" - "BEGIN" - " a := b;" + " z : Arr;" + " r : RecDesc;" + "" + "PROCEDURE TestRecordCopy(rrr : RecDesc);" + "END TestRecordCopy;" + "" + "PROCEDURE TestArrayCopy(aaa : Arr);" + "END TestArrayCopy;" + "" + "PROCEDURE TestOpenArrayCopy(ppp : ARRAY OF ARRAY OF INTEGER);" + "END TestOpenArrayCopy;" + "" + "BEGIN;" + " TestRecordCopy(r);" + " TestArrayCopy(z);" + " TestOpenArrayCopy(z);" "END Test." ;