X-Git-Url: http://deadsoftware.ru/gitweb?a=blobdiff_plain;f=src%2Fbackends%2Fjvm%2Fgenerator-jvm.c;h=215f6d757b1d92fd1b1b2c67ed088333959e927d;hb=351f950548241d4c4bd799acabbcd98a39b096cc;hp=c217ccb3d6f37ebb809bf076dcd35e62636d3c5e;hpb=33dd153448f426558fede7a951be657622163e76;p=dsw-obn.git diff --git a/src/backends/jvm/generator-jvm.c b/src/backends/jvm/generator-jvm.c index c217ccb..215f6d7 100644 --- a/src/backends/jvm/generator-jvm.c +++ b/src/backends/jvm/generator-jvm.c @@ -96,6 +96,9 @@ get_descriptor(oberon_context_t * ctx, oberon_type_t * type) case OBERON_TYPE_BOOLEAN: return new_string("Z"); break; + case OBERON_TYPE_POINTER: + return get_descriptor(ctx, type -> base); + break; case OBERON_TYPE_PROCEDURE: case OBERON_TYPE_RECORD: desc = get_class_full_name(ctx, type); @@ -141,7 +144,21 @@ get_prefix(oberon_context_t * ctx, oberon_type_t * type) static char * get_field_full_name(oberon_context_t * ctx, oberon_object_t * x) { - return new_string("%s/%s", x -> module -> name, x -> name); + switch(x -> class) + { + case OBERON_CLASS_VAR: + return new_string("%s/%s", x -> module -> name, x -> name); + case OBERON_CLASS_FIELD:; + char * rec_name = get_class_full_name(ctx, x -> parent_type); + return new_string("%s/%s", rec_name, x -> name); + case OBERON_CLASS_MODULE: + return new_string(x -> module -> name); + default: + oberon_error(ctx, "get_field_full_name: wat"); + break; + } + + return NULL; } static char * @@ -170,8 +187,6 @@ get_class_full_name(oberon_context_t * ctx, oberon_type_t * type) break; case OBERON_TYPE_RECORD: - assert(type -> module); - assert(type -> module -> gen_mod); rec_id = type -> gen_type -> rec_id; name = new_string("%s$RECORD%i", type -> module -> name, rec_id); break; @@ -282,7 +297,6 @@ oberon_generator_init_type(oberon_context_t * ctx, oberon_type_t * type) oberon_generate_procedure_class(ctx, type); break; case OBERON_TYPE_POINTER: - assert(type -> base -> class == OBERON_TYPE_VOID); break; default: oberon_error(ctx, "oberon_generator_init_type: unk calss %i", type -> class); @@ -301,7 +315,10 @@ oberon_generate_object(oberon_context_t * ctx, FILE * fp, oberon_object_t * x) switch(x -> class) { case OBERON_CLASS_VAR: - fprintf(fp, ".field public static %s %s\n\n", name, desc); + if(x -> local == 0) + { + fprintf(fp, ".field public static %s %s\n\n", name, desc); + } break; case OBERON_CLASS_FIELD: fprintf(fp, ".field public %s %s\n\n", name, desc); @@ -491,7 +508,7 @@ jvm_alloc_register(struct gen_register_file * rf, oberon_type_t * type) else { assert(i <= MAX_REGISTERS); - rf -> num_used += 2; + rf -> num_used += 1; rf -> reg[i].used = true; rf -> reg[i].wide = false; } @@ -713,6 +730,44 @@ push_var(oberon_context_t * ctx, FILE * fp, oberon_object_t * var) } } +static void +jvm_generate_new_static(oberon_context_t * ctx, FILE * fp, oberon_type_t * type, int num, oberon_expr_t * arg) +{ + //char * desc; + char * cname; + //desc = get_descriptor(ctx, type); + cname = get_class_full_name(ctx, type); + + switch(type -> class) + { + case OBERON_TYPE_INTEGER: + case OBERON_TYPE_BOOLEAN: + case OBERON_TYPE_PROCEDURE: + case OBERON_TYPE_REAL: + case OBERON_TYPE_POINTER: + /* ничего не генерируем */ + break; + case OBERON_TYPE_RECORD: + fprintf(fp, "new %s\n", cname); + fprintf(fp, "dup\n"); + fprintf(fp, "invokespecial %s/()V\n", cname); + break; + case OBERON_TYPE_ARRAY: + oberon_error(ctx, "jvm_generate_new_static: TODO array"); + break; + default: + oberon_error(ctx, "jvm_generate_new_static: unk type class %i", type -> class); + break; + } +} + +static void +jvm_generate_new_pointer(oberon_context_t * ctx, FILE * fp, oberon_type_t * type, int num, oberon_expr_t * arg) +{ + assert(type -> class == OBERON_TYPE_POINTER); + jvm_generate_new_static(ctx, fp, type -> base, num, arg); +} + static void push_item(oberon_context_t * ctx, FILE * fp, oberon_item_t * item) { @@ -734,16 +789,20 @@ push_item(oberon_context_t * ctx, FILE * fp, oberon_item_t * item) oberon_error(ctx, "push_item: TODO index"); break; case MODE_FIELD: - oberon_error(ctx, "push_item: TODO field"); + push_item(ctx, fp, item -> parent); + char * field = get_field_full_name(ctx, item -> var); + char * desc = get_descriptor(ctx, item -> var -> type); + fprintf(fp, "getfield %s %s\n", field, desc); break; case MODE_DEREF: - oberon_error(ctx, "push_item: TODO deref"); + /* Все объекты представляются как увказатели */ + push_item(ctx, fp, item -> parent); break; case MODE_NIL: fprintf(fp, "aconst_null\n"); break; case MODE_NEW: - oberon_error(ctx, "push_item: TODO new"); + jvm_generate_new_pointer(ctx, fp, item -> result, item -> num_args, item -> args); break; case MODE_REAL: push_float(fp, item -> real, item -> result -> size); @@ -754,60 +813,155 @@ push_item(oberon_context_t * ctx, FILE * fp, oberon_item_t * item) } } +static int +jvm_new_label_id(oberon_context_t * ctx) +{ + gen_context_t * c = ctx -> gen_context; + int label_id = c -> label_id; + c -> 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(FILE * fp, int label_id) +{ + fprintf(fp, "L%i:\n", label_id); +} + +static void +jvm_generate_logical_not(oberon_context_t * ctx, FILE * fp) +{ + int label_true = jvm_new_label_id(ctx); + int label_false = jvm_new_label_id(ctx); + char * label_name_true = jvm_get_label_name(label_true); + char * label_name_false = jvm_get_label_name(label_false); + + fprintf(fp, "ifne %s\n", label_name_false); + fprintf(fp, "iconst_1\n"); + fprintf(fp, "goto %s\n", label_name_true); + jvm_generate_label(fp, label_false); + fprintf(fp, "iconst_0\n"); + jvm_generate_label(fp, label_true); +} + +static char +jvm_get_type_of_prefix(char prefix) +{ + switch(prefix) + { + case 'b': + return 'B'; + case 'c': + return 'C'; + case 'd': + return 'D'; + case 'f': + return 'F'; + case 'i': + return 'I'; + case 'l': + return 'J'; + } + + assert(0); +} + static void -push_operator(oberon_context_t * ctx, FILE * fp, oberon_oper_t * oper) +jvm_generate_abs(FILE * fp, char prefix) { - char prefix = get_prefix(ctx, oper -> result); - switch(oper -> op) + char t = jvm_get_type_of_prefix(prefix); + fprintf(fp, "invokestatic java/lang/Math/abs(%c)%c\n", t, t); +} + +static void +jvm_generate_compare_op(oberon_context_t * ctx, FILE *fp, char prefix, int op) +{ + int label_true = jvm_new_label_id(ctx); + int label_false = jvm_new_label_id(ctx); + char * label_name_true = jvm_get_label_name(label_true); + char * label_name_false = jvm_get_label_name(label_false); + + assert(prefix == 'i' || prefix == 'a'); + + switch(op) + { + case OP_EQ: + fprintf(fp, "if_%ccmpeq %s\n", prefix, label_name_true); + break; + case OP_NEQ: + fprintf(fp, "if_%ccmpne %s\n", prefix, label_name_true); + break; + case OP_LSS: + fprintf(fp, "if_icmplt %s\n", label_name_true); + break; + case OP_LEQ: + fprintf(fp, "if_icmple %s\n", label_name_true); + break; + case OP_GRT: + fprintf(fp, "if_icmpgt %s\n", label_name_true); + break; + case OP_GEQ: + fprintf(fp, "if_icmpge %s\n", label_name_true); + break; + default: + oberon_error(ctx, "jvm_generate_compare_op: wat"); + break; + } + + fprintf(fp, "iconst_0\n"); + fprintf(fp, "goto %s\n", label_name_false); + jvm_generate_label(fp, label_true); + fprintf(fp, "iconst_1\n"); + jvm_generate_label(fp, label_false); +} + +static void +jvm_generate_operator(oberon_context_t * ctx, FILE *fp, char prefix, int op) +{ + switch(op) { case OP_UNARY_MINUS: - push_expr(ctx, fp, oper -> left); fprintf(fp, "%cneg\n", prefix); break; case OP_BITWISE_NOT: - push_expr(ctx, fp, oper -> left); push_int(fp, -1); fprintf(fp, "%cxor\n", prefix); break; + case OP_LOGIC_NOT: + jvm_generate_logical_not(ctx, fp); + break; + case OP_ABS: + jvm_generate_abs(fp, prefix); + break; case OP_ADD: - push_expr(ctx, fp, oper -> left); - push_expr(ctx, fp, oper -> right); fprintf(fp, "%cadd\n", prefix); break; case OP_SUB: - push_expr(ctx, fp, oper -> left); - push_expr(ctx, fp, oper -> right); fprintf(fp, "%csub\n", prefix); break; case OP_MUL: - push_expr(ctx, fp, oper -> left); - push_expr(ctx, fp, oper -> right); fprintf(fp, "%cmul\n", prefix); break; case OP_DIV: - push_expr(ctx, fp, oper -> left); - push_expr(ctx, fp, oper -> right); fprintf(fp, "%cdiv\n", prefix); break; case OP_MOD: - push_expr(ctx, fp, oper -> left); - push_expr(ctx, fp, oper -> right); fprintf(fp, "%crem\n", prefix); break; case OP_BITWISE_AND: - push_expr(ctx, fp, oper -> left); - push_expr(ctx, fp, oper -> right); fprintf(fp, "%cand\n", prefix); break; case OP_BITWISE_XOR: - push_expr(ctx, fp, oper -> left); - push_expr(ctx, fp, oper -> right); fprintf(fp, "%cxor\n", prefix); break; case OP_BITWISE_OR: - push_expr(ctx, fp, oper -> left); - push_expr(ctx, fp, oper -> right); fprintf(fp, "%cor\n", prefix); break; @@ -817,12 +971,95 @@ push_operator(oberon_context_t * ctx, FILE * fp, oberon_oper_t * oper) case OP_LEQ: case OP_GRT: case OP_GEQ: + jvm_generate_compare_op(ctx, fp, prefix, op); + break; + default: + oberon_error(ctx, "jvm_generate_operator: unk op %i", op); + break; + } +} + +static void +jvm_generate_logical_or(oberon_context_t * ctx, FILE * fp, oberon_expr_t * p, oberon_expr_t * q) +{ + int label_calc_q = jvm_new_label_id(ctx); + int label_done = jvm_new_label_id(ctx); + char * label_name_calc_q = jvm_get_label_name(label_calc_q); + char * label_name_done = jvm_get_label_name(label_done); + + /* p OR q -- если p, то TRUE, иначе q */ + + push_expr(ctx, fp, p); + fprintf(fp, "ifne %s\n", label_name_calc_q); + fprintf(fp, "iconst_1\n"); + fprintf(fp, "goto %s\n", label_name_done); + jvm_generate_label(fp, label_calc_q); + push_expr(ctx, fp, q); + jvm_generate_label(fp, label_done); +} + +static void +jvm_generate_logical_and(oberon_context_t * ctx, FILE * fp, oberon_expr_t * p, oberon_expr_t * q) +{ + int label_false = jvm_new_label_id(ctx); + int label_done = jvm_new_label_id(ctx); + char * label_name_false = jvm_get_label_name(label_false); + char * label_name_done = jvm_get_label_name(label_done); + + /* p AND q -- если p, то q, иначе FALSE */ + + push_expr(ctx, fp, p); + fprintf(fp, "ifne %s\n", label_name_false); + push_expr(ctx, fp, q); + fprintf(fp, "goto %s\n", label_name_done); + jvm_generate_label(fp, label_false); + fprintf(fp, "iconst_0\n"); + jvm_generate_label(fp, label_done); +} + +static void +push_operator(oberon_context_t * ctx, FILE * fp, oberon_oper_t * oper) +{ + char prefix = get_prefix(ctx, oper -> result); + int op = oper -> op; + switch(op) + { + case OP_UNARY_MINUS: + case OP_BITWISE_NOT: case OP_LOGIC_NOT: case OP_ABS: - oberon_error(ctx, "push_oper: TODO op %i", oper -> op); + push_expr(ctx, fp, oper -> left); + jvm_generate_operator(ctx, fp, prefix, op); + break; + + case OP_ADD: + case OP_SUB: + case OP_MUL: + case OP_DIV: + case OP_MOD: + case OP_BITWISE_AND: + case OP_BITWISE_XOR: + case OP_BITWISE_OR: + + case OP_EQ: + case OP_NEQ: + case OP_LSS: + case OP_LEQ: + case OP_GRT: + case OP_GEQ: + push_expr(ctx, fp, oper -> left); + push_expr(ctx, fp, oper -> right); + jvm_generate_operator(ctx, fp, prefix, op); + break; + + case OP_LOGIC_OR: + jvm_generate_logical_or(ctx, fp, oper -> left, oper -> right); + break; + case OP_LOGIC_AND: + jvm_generate_logical_and(ctx, fp, oper -> left, oper -> right); break; default: - oberon_error(ctx, "push_oper: unk op %i", oper -> op); + oberon_error(ctx, "push_oper: unk op %i", op); break; } } @@ -841,15 +1078,16 @@ push_expr(oberon_context_t * ctx, FILE * fp, oberon_expr_t * expr) } static void -store_expr(oberon_context_t * ctx, FILE * fp, oberon_expr_t * expr) +store_expr(oberon_context_t * ctx, FILE * fp, oberon_expr_t * dst, oberon_expr_t * src) { - assert(expr -> is_item); - oberon_item_t * item = (oberon_item_t *) expr; + assert(dst -> is_item); + oberon_item_t * item = (oberon_item_t *) dst; char prefix; switch(item -> mode) { case MODE_VAR: + push_expr(ctx, fp, src); if(item -> var -> local) { int reg = item -> var -> gen_var -> reg; @@ -863,6 +1101,21 @@ store_expr(oberon_context_t * ctx, FILE * fp, oberon_expr_t * expr) fprintf(fp, "putstatic %s %s\n", fullname, desc); } break; + case MODE_INDEX: + oberon_error(ctx, "store_expr: TODO index"); + break; + case MODE_FIELD: + { + char * fullname = get_field_full_name(ctx, item -> var); + char * desc = get_descriptor(ctx, item -> result); + printf("push parent\n"); + push_item(ctx, fp, item -> parent); + printf("push expr\n"); + push_expr(ctx, fp, src); + printf("store to field %s:%s\n", fullname, desc); + fprintf(fp, "putfield %s %s ; store field\n", fullname, desc); + } + break; default: oberon_error(ctx, "store_expr: unk mode %i", item -> mode); break; @@ -875,8 +1128,7 @@ oberon_generate_assign(oberon_context_t * ctx, oberon_expr_t * src, oberon_expr_ gen_module_t * m; m = ctx -> mod -> gen_mod; - push_expr(ctx, m -> fp, src); - store_expr(ctx, m -> fp, dst); + store_expr(ctx, m -> fp, dst, src); } void