X-Git-Url: https://deadsoftware.ru/gitweb?a=blobdiff_plain;f=src%2Fbackends%2Fjvm%2Fgenerator-jvm.c;h=4f49cfb86ca94df0b220be27f0d5fad68ac99a3b;hb=0b724e12457f2507d398c51dc35200d833ce9362;hp=be8c9292dd0444f3f50c0ce116baee2ad660f254;hpb=1128fa8566c932e3996abd427fc75bc4c946e656;p=dsw-obn.git diff --git a/src/backends/jvm/generator-jvm.c b/src/backends/jvm/generator-jvm.c index be8c929..4f49cfb 100644 --- a/src/backends/jvm/generator-jvm.c +++ b/src/backends/jvm/generator-jvm.c @@ -9,6 +9,7 @@ #include #include "../../oberon-internals.h" +#include "../../generator.h" #include "generator-jvm.h" #include "generator-jvm-abi.h" #include "generator-jvm-asm.h" @@ -20,6 +21,88 @@ 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); +static void +jvm_generate_cast_prefix(gen_proc_t * p, char prefix, char postfix) +{ + if((prefix == 'b' || prefix == 's') && (postfix = 'l' || postfix == 'd')) + { + prefix = 'i'; + } + + if(prefix == postfix) + { + return; + } + + if((prefix == 'l' || prefix == 'd') && (postfix == 'b' || postfix == 's')) + { + jvm_generate(p, 2, 1, "%c2i", prefix); + prefix = 'i'; + } + + int from_cell_size = jvm_cell_size_for_postfix(prefix); + int to_cell_size = jvm_cell_size_for_postfix(postfix); + jvm_generate(p, from_cell_size, to_cell_size, "%c2%c", prefix, postfix); +} + +static void +jvm_generate_cast_type(gen_proc_t * p, oberon_type_t * from, oberon_type_t * to) +{ + if(to -> class == OBERON_TYPE_RECORD || to -> class == OBERON_TYPE_POINTER) + { + if(to -> class == OBERON_TYPE_POINTER && to -> base -> class == OBERON_TYPE_RECORD) + { + char * full_name = jvm_get_class_full_name(to); + jvm_generate(p, 1, 1, "checkcast %s", full_name); + } + } + else + { + char prefix = jvm_get_prefix(from); + char postfix = jvm_get_postfix(to); + jvm_generate_cast_prefix(p, prefix, postfix); + } +} + +static void +jvm_generate_hard_cast_type(gen_proc_t * p, oberon_type_t * from, oberon_type_t * to) +{ + if(from -> class == OBERON_TYPE_REAL + && (to -> class == OBERON_TYPE_INTEGER || to -> class == OBERON_TYPE_SYSTEM_BYTE)) + { + char postfix = jvm_get_postfix(to); + if(from -> size <= 4) + { + jvm_generate(p, 1, 1, "invokestatic java/lang/Float/floatToRawIntBits(F)I"); + jvm_generate_cast_prefix(p, 'i', postfix); + } + else + { + jvm_generate(p, 2, 2, "invokestatic java/lang/Double/doubleToRawIntBits(D)J"); + jvm_generate_cast_prefix(p, 'l', postfix); + } + } + else if((from -> class == OBERON_TYPE_INTEGER || from -> class == OBERON_TYPE_SYSTEM_BYTE) + && to -> class == OBERON_TYPE_REAL) + { + char prefix = jvm_get_prefix(from); + if(to -> size <= 4) + { + jvm_generate_cast_prefix(p, prefix, 'i'); + jvm_generate(p, 1, 1, "invokestatic java/lang/Float/intBitsToFloat(I)F"); + } + else + { + jvm_generate_cast_prefix(p, prefix, 'l'); + jvm_generate(p, 2, 2, "invokestatic java/lang/Double/longBitsToDouble(J)D"); + } + } + else + { + jvm_generate_cast_type(p, from, to); + } +} + /* * Генерирует код для инициализации массива со статическим базовым типом * ( aref -- ) @@ -582,6 +665,13 @@ oberon_generator_init_record(oberon_context_t * ctx, oberon_type_t * rec) jvm_generate_var_initialization(p, copy_dst); jvm_generate_var_initialization(p, copy_src); + if(rec -> base) + { + jvm_generate_load(p, copy_dst); + jvm_generate_load(p, copy_src); + jvm_generate_copy_record(p, rec -> base); + } + num = rec -> num_decl; field = rec -> decl; for(int i = 0; i < num; i++) @@ -731,6 +821,18 @@ oberon_generator_fini_module(oberon_module_t * mod) static void push_expr(gen_proc_t * p, oberon_expr_t * expr); +static void +oberon_generate_static_initialization(gen_proc_t * p, oberon_object_t * x) +{ + 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 -> gen_var); + } +} + void oberon_generate_begin_module(oberon_context_t * ctx) { @@ -766,13 +868,7 @@ oberon_generate_begin_module(oberon_context_t * ctx) else if(x -> class == OBERON_CLASS_VAR) { jvm_generate_var_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 -> gen_var); - } + oberon_generate_static_initialization(p, x); } x = x -> next; @@ -871,10 +967,12 @@ jvm_generate_local_object(gen_proc_t * p, oberon_object_t * x) case OBERON_CLASS_VAR: jvm_generate_var(v); break; + case OBERON_CLASS_CONST: + case OBERON_CLASS_TYPE: case OBERON_CLASS_PROC: break; default: - gen_error("jvm_generate_local_initialization: wat"); + gen_error("jvm_generate_local_initialization: wat class %i", x -> class); break; } } @@ -895,28 +993,31 @@ jvm_generate_local_initialization(gen_proc_t * p, oberon_object_t * x) switch(x -> class) { case OBERON_CLASS_VAR_PARAM: + jvm_generate_var_initialization(p, v); + break; case OBERON_CLASS_PARAM: + jvm_generate_var_initialization(p, v); + if(x -> type -> class == OBERON_TYPE_ARRAY) + { + jvm_generate_array_duplicate_and_replace(p, v, x -> type); + } + else if(x -> type -> class == OBERON_TYPE_RECORD) + { + jvm_generate_record_duplicate_and_replace(p, v, x -> type); + } + break; case OBERON_CLASS_VAR: jvm_generate_var_initialization(p, v); + oberon_generate_static_initialization(p, x); break; + case OBERON_CLASS_CONST: + case OBERON_CLASS_TYPE: case OBERON_CLASS_PROC: break; default: - gen_error("jvm_generate_local_initialization: wat"); + gen_error("jvm_generate_local_initialization: wat class %i", x -> class); break; } - - if(x -> class == OBERON_CLASS_PARAM) - { - if(x -> type -> class == OBERON_TYPE_ARRAY) - { - jvm_generate_array_duplicate_and_replace(p, v, x -> type); - } - else if(x -> type -> class == OBERON_TYPE_RECORD) - { - jvm_generate_record_duplicate_and_replace(p, v, x -> type); - } - } } void @@ -977,6 +1078,7 @@ oberon_generate_end_proc(oberon_context_t * ctx) m = ctx -> mod -> gen_mod; p = m -> class -> p; + oberon_generate_trap(ctx, -4); jvm_generate_function_end(p); } @@ -1044,6 +1146,14 @@ oberon_generate_branch(oberon_context_t * ctx, oberon_expr_t * cond, bool gotoif } } +static void +check_index(gen_proc_t * p, oberon_type_t * index_type) +{ + // TODO проверка валидности границ + char prefix = jvm_get_prefix(index_type); + jvm_generate_cast_prefix(p, prefix, 'i'); +} + static void push_varptr(gen_proc_t * p, oberon_expr_t * expr) { @@ -1057,6 +1167,7 @@ push_varptr(gen_proc_t * p, oberon_expr_t * expr) case MODE_INDEX: push_item(p, expr -> item.parent); push_expr(p, expr -> item.args); + check_index(p, expr -> item.args -> result); break; case MODE_FIELD: push_item(p, expr -> item.parent); @@ -1181,77 +1292,6 @@ jvm_generate_expr_new_pointer(gen_proc_t * p, oberon_type_t * type, int num, obe jvm_generate_new(p, type -> base, num); } -static void -jvm_generate_cast_prefix(gen_proc_t * p, char prefix, char postfix) -{ - if(prefix == postfix) - { - return; - } - - int from_cell_size = jvm_cell_size_for_postfix(prefix); - int to_cell_size = jvm_cell_size_for_postfix(postfix); - jvm_generate(p, from_cell_size, to_cell_size, "%c2%c", prefix, postfix); -} - -static void -jvm_generate_cast_type(gen_proc_t * p, oberon_type_t * from, oberon_type_t * to) -{ - if(to -> class == OBERON_TYPE_RECORD || to -> class == OBERON_TYPE_POINTER) - { - if(to -> class == OBERON_TYPE_POINTER && to -> base -> class == OBERON_TYPE_RECORD) - { - char * full_name = jvm_get_class_full_name(to); - jvm_generate(p, 1, 1, "checkcast %s", full_name); - } - } - else - { - char prefix = jvm_get_prefix(from); - char postfix = jvm_get_postfix(to); - jvm_generate_cast_prefix(p, prefix, postfix); - } -} - -static void -jvm_generate_hard_cast_type(gen_proc_t * p, oberon_type_t * from, oberon_type_t * to) -{ - if(from -> class == OBERON_TYPE_REAL - && (to -> class == OBERON_TYPE_INTEGER || to -> class == OBERON_TYPE_SYSTEM_BYTE)) - { - char postfix = jvm_get_postfix(to); - if(from -> size <= 4) - { - jvm_generate(p, 1, 1, "invokestatic java/lang/Float/floatToIntBits(F)I"); - jvm_generate_cast_prefix(p, 'i', postfix); - } - else - { - jvm_generate(p, 2, 2, "invokestatic java/lang/Double/doubleToIntBits(D)J"); - jvm_generate_cast_prefix(p, 'l', postfix); - } - } - else if((from -> class == OBERON_TYPE_INTEGER || from -> class == OBERON_TYPE_SYSTEM_BYTE) - && to -> class == OBERON_TYPE_REAL) - { - char prefix = jvm_get_prefix(from); - if(to -> size <= 4) - { - jvm_generate_cast_prefix(p, prefix, 'i'); - jvm_generate(p, 1, 1, "invokestatic java/lang/Float/intBitsToFloat(I)F"); - } - else - { - jvm_generate_cast_prefix(p, prefix, 'l'); - jvm_generate(p, 2, 2, "invokestatic java/lang/Double/longBitsToDouble(J)D"); - } - } - else - { - jvm_generate_cast_type(p, from, to); - } -} - static void push_item(gen_proc_t * p, oberon_item_t * item) { @@ -1282,6 +1322,7 @@ push_item(gen_proc_t * p, oberon_item_t * item) int cell_size = jvm_cell_size_for_postfix(postfix); push_item(p, item -> parent); push_expr(p, item -> args); + check_index(p, item -> args -> result); jvm_generate(p, 1 + 1, cell_size, "%caload", postfix); break; case MODE_FIELD: @@ -1785,6 +1826,7 @@ store_expr(gen_proc_t * p, oberon_expr_t * dst, oberon_expr_t * src) assert(item -> parent -> is_item); push_item(p, (oberon_item_t *) item -> parent); push_expr(p, item -> args); + check_index(p, item -> args -> result); push_expr(p, src); jvm_generate(p, 1 + 1 + cell_size, 0, "%castore", postfix); break;