X-Git-Url: https://deadsoftware.ru/gitweb?a=blobdiff_plain;f=src%2Fbackends%2Fjvm%2Fgenerator-jvm.c;h=ca0f88565536d1ae11ce2022c4713099fb9bcf0c;hb=99fa357db44a4c30957bd0810e14a20456c58347;hp=d986a8e4cbc9af35a1fcf9361c531238c1de3fa8;hpb=c055d16f1d6ca38c5c2171dbafd1a25305fb909c;p=dsw-obn.git diff --git a/src/backends/jvm/generator-jvm.c b/src/backends/jvm/generator-jvm.c index d986a8e..ca0f885 100644 --- a/src/backends/jvm/generator-jvm.c +++ b/src/backends/jvm/generator-jvm.c @@ -263,6 +263,24 @@ jvm_generate_push_float(gen_proc_t * p, double f, int size) } } +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() { @@ -582,7 +600,7 @@ jvm_generate_copy_array(gen_proc_t * p, oberon_type_t * arr) * Входящие параметры заграблены. * Теперь генерируем эквивалентный код: * int i = 0; - * int len = dst.length + * int len = src.length * while(i < len) * { * ... @@ -609,7 +627,7 @@ jvm_generate_copy_array(gen_proc_t * p, oberon_type_t * arr) jvm_generate(p, 0, 1, "iconst_0"); jvm_generate(p, 1, 0, "istore %i", loop[i].index -> reg); - jvm_generate_load(p, arr, dst); + jvm_generate_load(p, arr, src); jvm_generate(p, 1, 1, "arraylength"); jvm_generate(p, 1, 0, "istore %i", loop[i].length -> reg); @@ -761,7 +779,14 @@ oberon_generate_procedure_pointer_class(oberon_object_t * proc) fprintf(fp, ".method ()V\n"); fprintf(fp, " aload_0\n"); fprintf(fp, " invokespecial %s/()V\n", abscname); - fprintf(fp, " aload_0\n"); + fprintf(fp, " return\n"); + fprintf(fp, ".end method\n\n"); + + fprintf(fp, ".method static ()V\n"); + fprintf(fp, " .limit stack 2\n"); + fprintf(fp, " new %s\n", cname); + fprintf(fp, " dup\n"); + fprintf(fp, " invokespecial %s/()V\n", cname); fprintf(fp, " putstatic %s/pointer %s\n", cname, absdesc); fprintf(fp, " return\n"); fprintf(fp, ".end method\n\n"); @@ -858,6 +883,8 @@ oberon_generator_init_type(oberon_context_t * ctx, oberon_type_t * type) case OBERON_TYPE_BOOLEAN: case OBERON_TYPE_ARRAY: case OBERON_TYPE_REAL: + case OBERON_TYPE_CHAR: + case OBERON_TYPE_STRING: break; case OBERON_TYPE_RECORD: ; @@ -1009,6 +1036,26 @@ oberon_generator_init_var(oberon_context_t * ctx, oberon_object_t * var) } } +void +oberon_generator_init_temp_var(oberon_context_t * ctx, oberon_object_t * var) +{ + assert(var -> class == OBERON_CLASS_VAR); + + gen_var_t * v = oberon_generator_new_var(); + var -> gen_var = v; + + gen_module_t * m; + m = ctx -> mod -> gen_mod; + + 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); +} + void oberon_generator_init_proc(oberon_context_t * ctx, oberon_object_t * proc) { @@ -1075,12 +1122,6 @@ oberon_generate_begin_module(oberon_context_t * ctx) jvm_generate_store(p, x -> type, x -> gen_var); } } - else if(x -> class == OBERON_CLASS_PROC) - { - char * cname = jvm_get_field_full_name_safe(x); - jvm_generate(p, 0, 1, "new %s", cname); - jvm_generate(p, 1, 0, "invokespecial %s/()V", cname); - } x = x -> next; } @@ -1226,6 +1267,70 @@ oberon_generate_end_proc(oberon_context_t * ctx) jvm_generate_function_end(p); } +gen_label_t * +oberon_generator_reserve_label(oberon_context_t * ctx) +{ + gen_module_t * m; + gen_proc_t * p; + gen_label_t * l; + + m = ctx -> mod -> gen_mod; + p = m -> class -> p; + + l = GC_MALLOC(sizeof *l); + memset(l, 0, sizeof *l); + + l -> id = jvm_new_label_id(p); + return l; +} + +void +oberon_generate_label(oberon_context_t * ctx, gen_label_t * l) +{ + gen_module_t * m; + gen_proc_t * p; + + m = ctx -> mod -> gen_mod; + p = m -> class -> p; + + jvm_generate_label(p, l -> id); +} + +void +oberon_generate_goto(oberon_context_t * ctx, gen_label_t * l) +{ + gen_module_t * m; + gen_proc_t * p; + + m = ctx -> mod -> gen_mod; + p = m -> class -> p; + + jvm_generate(p, 0, 0, "goto L%i", l -> id); +} + +void +oberon_generate_branch(oberon_context_t * ctx, oberon_expr_t * cond, bool gotoif, gen_label_t * l) +{ + gen_module_t * m; + gen_proc_t * p; + + m = ctx -> mod -> gen_mod; + p = m -> class -> p; + + push_expr(p, cond); + + if(gotoif == false) + { + /* переход если false */ + jvm_generate(p, 1, 0, "ifeq L%i", l -> id); + } + else + { + /* переход если true */ + jvm_generate(p, 1, 0, "ifne L%i", l -> id); + } +} + static void jvm_generate_call_proc(gen_proc_t * p, oberon_item_t * desig) { @@ -1366,6 +1471,7 @@ push_item(gen_proc_t * p, oberon_item_t * item) } break; case MODE_INTEGER: + case MODE_CHAR: jvm_generate_push_int_size(p, item -> integer, item -> result -> size); break; case MODE_BOOLEAN: @@ -1402,6 +1508,9 @@ push_item(gen_proc_t * p, oberon_item_t * item) case MODE_REAL: jvm_generate_push_float(p, item -> real, item -> result -> size); break; + case MODE_STRING: + jvm_generate_push_string(p, item -> string, item -> result -> size); + break; default: gen_error("push_item: unk mode %i", item -> mode); break; @@ -1432,18 +1541,10 @@ jvm_generate_abs(gen_proc_t * p, char prefix) jvm_generate(p, cell_size, cell_size, "invokestatic java/lang/Math/abs(%c)%c", t, t); } -static void -jvm_generate_compare_op(gen_proc_t * p, char prefix, int op) +static char * +jvm_get_compare_postfix(int op) { - int label_true = jvm_new_label_id(p); - int label_done = jvm_new_label_id(p); - char * label_name_true = jvm_get_label_name(label_true); - char * label_name_done = jvm_get_label_name(label_done); - int cell_size = 2 * jvm_cell_size_for_postfix(prefix); - - assert(prefix == 'i' || prefix == 'a'); - - const char * cmpop = ""; + char * cmpop = ""; switch(op) { case OP_EQ: @@ -1468,17 +1569,51 @@ jvm_generate_compare_op(gen_proc_t * p, char prefix, int op) gen_error("jvm_generate_compare_op: wat"); break; } + return cmpop; +} + +static void +jvm_generate_compare_op(gen_proc_t * p, oberon_type_t * t, int op) +{ + char prefix = jvm_get_prefix(t); + int label_true = jvm_new_label_id(p); + int label_done = jvm_new_label_id(p); + int cell_size = jvm_cell_size_for_type(t); + char * cmpop = jvm_get_compare_postfix(op); + + if(prefix == 'l') + { + jvm_generate(p, 2 * cell_size, 1, "lcmp"); + jvm_generate(p, 1, 1, "if%s L%i", cmpop, label_true); + } + else if(prefix == 'f' || prefix == 'd') + { + char fop; + if(op == OP_EQ || op == OP_NEQ || op == OP_GRT || op == OP_GEQ) + { + fop = 'l'; + } + else + { + fop = 'g'; + } + jvm_generate(p, 2 * cell_size, 1, "%ccmp%c", prefix, fop); + jvm_generate(p, 1, 1, "if%s L%i", cmpop, label_true); + } + else + { + jvm_generate(p, 2 * cell_size, 0, "if_%ccmp%s L%i", prefix, cmpop, label_true); + } - jvm_generate(p, cell_size, 0, "if_%ccmp%s %s", prefix, cmpop, label_name_true); jvm_generate(p, 0, 1, "iconst_0"); - 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_true); jvm_generate(p, 0, 1, "iconst_1"); jvm_generate_label(p, label_done); } static void -jvm_generate_operator(gen_proc_t * p, char prefix, int op) +jvm_generate_operator(gen_proc_t * p, oberon_type_t * t, char prefix, int op) { int cell_size = jvm_cell_size_for_postfix(prefix); switch(op) @@ -1528,7 +1663,7 @@ jvm_generate_operator(gen_proc_t * p, char prefix, int op) case OP_LEQ: case OP_GRT: case OP_GEQ: - jvm_generate_compare_op(p, prefix, op); + jvm_generate_compare_op(p, t, op); break; default: gen_error("jvm_generate_operator: unk op %i", op); @@ -1577,6 +1712,7 @@ jvm_generate_logical_and(gen_proc_t * p, oberon_expr_t * a, oberon_expr_t * b) static void push_operator(gen_proc_t * p, oberon_oper_t * oper) { + oberon_type_t * preq = oper -> left -> result; char prefix = jvm_get_prefix(oper -> result); int op = oper -> op; switch(op) @@ -1590,7 +1726,7 @@ push_operator(gen_proc_t * p, oberon_oper_t * oper) case OP_LOGIC_NOT: case OP_ABS: push_expr(p, oper -> left); - jvm_generate_operator(p, prefix, op); + jvm_generate_operator(p, preq, prefix, op); break; case OP_ADD: @@ -1610,7 +1746,7 @@ push_operator(gen_proc_t * p, oberon_oper_t * oper) case OP_GEQ: push_expr(p, oper -> left); push_expr(p, oper -> right); - jvm_generate_operator(p, prefix, op); + jvm_generate_operator(p, preq, prefix, op); break; case OP_LOGIC_OR: