X-Git-Url: http://deadsoftware.ru/gitweb?p=dsw-obn.git;a=blobdiff_plain;f=src%2Fbackends%2Fjvm%2Fgenerator-jvm.c;h=dc79ea11cd0cbb656036a37d67d9a512c46517ae;hp=895a5ae3e524c2ef30063d1de38a316b2e3d23b1;hb=961fbb99dcba21ccb737db16c0cdb28d757a2de7;hpb=31b71df908daa914198e78a0f43cf0a3965878dd 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