#include #include #include #include #include #include #include #include #include "../../../include/oberon.h" #include "../../oberon-internals.h" #include "generator-jvm.h" #include "generator-jvm-basic.h" // ========================================== // ========================================== // ========================================== gen_proc_t * jvm_create_proc(struct gen_class * class) { gen_proc_t * p = GC_MALLOC(sizeof *p); memset(p, 0, sizeof *p); struct gen_register_file * rf = GC_MALLOC(sizeof *rf); memset(rf, 0, sizeof *rf); struct gen_stack * stack = GC_MALLOC(sizeof *stack); memset(rf, 0, sizeof *stack); p -> rf = rf; p -> stack = stack; p -> class = class; p -> label_id = 0; return p; } void jvm_generate_function_header(gen_proc_t * p, char * access, char * name, char * signature) { struct gen_class * class; class = p -> class; /* Делаем процедуру текущей в этом классе */ assert(class -> p == NULL); class -> p = p; fprintf(class -> fp, ".method %s %s%s\n", access, name, signature); } void jvm_generate_function_end(gen_proc_t * p) { struct gen_class * class; class = p -> class; assert(class -> p); class -> p = NULL; fprintf(class -> fp, " .limit stack %i\n", p -> stack -> max_pointer); fprintf(class -> fp, " .limit locals %i\n", p -> rf -> max_used); fprintf(class -> fp, ".end method\n\n"); } struct gen_class * jvm_create_class(char * full_name) { struct gen_class * class = GC_MALLOC(sizeof *class); memset(class, 0, sizeof *class); char * fname = new_string("%s.j", full_name); class -> full_name = new_string(full_name); class -> fp = fopen(fname, "w"); assert(class -> fp); return class; } static void jvm_destroy_class(struct gen_class * class) { assert(class -> p == NULL); fclose(class -> fp); } static void jvm_stack_push(gen_proc_t * p, unsigned size) { p -> stack -> pointer += size; if(p -> stack -> pointer > p -> stack -> max_pointer) { p -> stack -> max_pointer = p -> stack -> pointer; } } static void jvm_stack_pop(gen_proc_t * p, unsigned size) { p -> stack -> pointer -= size; assert(p -> stack -> pointer >= 0); } static void jvm_generate(gen_proc_t * p, unsigned get, unsigned push, char * format, ...) { va_list ptr; va_start(ptr, format); jvm_stack_pop(p, get); fprintf(p -> class -> fp, " "); vfprintf(p -> class -> fp, format, ptr); fprintf(p -> class -> fp, "\n"); jvm_stack_push(p, push); va_end(ptr); } static void jvm_generate_push_int(gen_proc_t * p, int64_t i) { if(i == -1) { jvm_generate(p, 0, 1, "iconst_m1"); } else if(i >= 0 && i <= 5) { jvm_generate(p, 0, 1, "iconst_%li", i); } else if(i >= -128 && i <= 127) { jvm_generate(p, 0, 1, "bipush %li", i); } else if(i >= -32768 && i <= 32767) { jvm_generate(p, 0, 1, "sipush %li", i); } else if(i >= -2147483648 && i <= 2147483647) { jvm_generate(p, 0, 1, "ldc %li", i); } else { jvm_generate(p, 0, 2, "ldc2 %li", i); } } static void jvm_generate_push_float(gen_proc_t * p, double f, int size) { if(size <= 4) { if(f == 0.0) { jvm_generate(p, 0, 1, "fconst_0"); } if(f == 1.0) { jvm_generate(p, 0, 1, "fconst_1"); } if(f == 2.0) { jvm_generate(p, 0, 1, "fconst_2"); } else { jvm_generate(p, 0, 1, "ldc %lf", f); } } else { if(f == 0.0) { jvm_generate(p, 0, 2, "dconst_0"); } if(f == 1.0) { jvm_generate(p, 0, 2, "dconst_1"); } else { jvm_generate(p, 0, 2, "ldc2 %lf", f); } } } static int jvm_new_label_id(gen_proc_t * p) { int label_id = p -> label_id; p -> 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(gen_proc_t * p, int label_id) { jvm_generate(p, 0, 0, "L%i:", label_id); } static void jvm_generate_new_static(gen_proc_t * p, oberon_type_t * type) { char * cname; 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: cname = jvm_get_class_full_name(type); jvm_generate(p, 0, 1, "new %s", cname); jvm_generate(p, 1, 2, "dup"); jvm_generate(p, 1, 0, "invokespecial %s/()V", cname); break; case OBERON_TYPE_ARRAY: gen_error("jvm_generate_new_static: TODO array"); break; default: gen_error("jvm_generate_new_static: unk type class %i", type -> class); break; } } static void jvm_generate_store(gen_proc_t * p, oberon_type_t * src_type, gen_var_t * dst) { char prefix; int cell_size; cell_size = jvm_cell_size_for_type(src_type); switch(dst -> storage) { case JVM_STORAGE_REGISTER: prefix = jvm_get_prefix(src_type); jvm_generate(p, cell_size, 0, "%cstore %i", prefix, dst -> reg); break; case JVM_STORAGE_STATIC: jvm_generate(p, cell_size, 0, "putstatic %s %s", dst -> full_name, dst -> desc); break; case JVM_STORAGE_FIELD: jvm_generate(p, 1 + cell_size, 0, "putfield %s %s", dst -> full_name, dst -> desc); break; default: gen_error("jvm_generate_store: unknow storage type %i", dst -> storage); break; } } static gen_var_t * oberon_generator_new_var() { gen_var_t * v = GC_MALLOC(sizeof *v); memset(v, 0, sizeof *v); return v; } static void jvm_generate_and_init_global_var(gen_var_t * v, struct gen_class * class, char * access, char * name, char * desc) { assert(class -> p == NULL); fprintf(class -> fp, ".field %s static %s %s\n\n", access, name, desc); v -> storage = JVM_STORAGE_STATIC; v -> full_name = new_string("%s/%s", class -> full_name, name); v -> desc = new_string(desc); } static void jvm_generate_and_init_field(gen_var_t * v, struct gen_class * class, char * access, char * name, char * desc) { assert(class -> p == NULL); fprintf(class -> fp, ".field %s %s %s\n\n", access, name, desc); v -> storage = JVM_STORAGE_FIELD; v -> full_name = new_string("%s/%s", class -> full_name, name); v -> desc = new_string(desc); } static void jvm_generate_and_init_local_var(gen_var_t * v, gen_proc_t * p, bool wide) { v -> storage = JVM_STORAGE_REGISTER; v -> reg = jvm_alloc_register_untyped(p -> rf, wide); } static void jvm_generate_and_init_named_local_var(gen_var_t * v, gen_proc_t * p, bool wide, char * name, char * desc) { jvm_generate_and_init_local_var(v, p, wide); v -> desc = new_string(desc); jvm_generate(p, 0, 0, ".var %i is %s %s from start to end", v -> reg, name, desc); } // ========================================== // ========================================== // ========================================== void oberon_generator_init_context(oberon_context_t * ctx) { gen_context_t * gen_context = GC_MALLOC(sizeof *gen_context); memset(gen_context, 0, sizeof *gen_context); ctx -> gen_context = gen_context; } void oberon_generator_destroy_context(oberon_context_t * ctx) { } static void oberon_generate_procedure_class(oberon_type_t * proc) { FILE * fp; char * cname; char * signature; struct gen_class * class; cname = jvm_get_class_full_name(proc); class = jvm_create_class(cname); fp = class -> fp; fprintf(fp, ".source SYSTEM\n"); fprintf(fp, ".class public abstract %s\n", cname); fprintf(fp, ".super java/lang/Object\n\n"); fprintf(fp, ".method public ()V\n"); fprintf(fp, " aload_0\n"); fprintf(fp, " invokespecial java/lang/Object/()V\n"); fprintf(fp, " return\n"); fprintf(fp, ".end method\n\n"); signature = jvm_get_procedure_signature(proc); fprintf(fp, ".method public abstract invoke%s\n", signature); fprintf(fp, ".end method\n\n"); jvm_destroy_class(class); } static void oberon_generate_record_class(gen_module_t * m, oberon_type_t * rec) { char * cname; struct gen_class * class; /* Устанавливаем новоый id */ rec -> gen_type -> rec_id = m -> rec_id; m -> rec_id += 1; cname = jvm_get_class_full_name(rec); class = jvm_create_class(cname); fprintf(class -> fp, ".source %s\n", rec -> module -> name); fprintf(class -> fp, ".class public %s\n", cname); fprintf(class -> fp, ".super java/lang/Object\n\n"); rec -> gen_type -> class = class; } void oberon_generator_init_type(oberon_context_t * ctx, oberon_type_t * type) { gen_type_t * t = GC_MALLOC(sizeof *t); memset(t, 0, sizeof *t); type -> gen_type = t; switch(type -> class) { case OBERON_TYPE_VOID: case OBERON_TYPE_INTEGER: case OBERON_TYPE_BOOLEAN: case OBERON_TYPE_ARRAY: case OBERON_TYPE_REAL: break; case OBERON_TYPE_RECORD: ; gen_module_t * m; m = type -> module -> gen_mod; oberon_generate_record_class(m, type); break; case OBERON_TYPE_PROCEDURE: oberon_generate_procedure_class(type); break; case OBERON_TYPE_POINTER: break; default: gen_error("oberon_generator_init_type: unk calss %i", type -> class); break; } } void oberon_generator_init_record(oberon_context_t * ctx, oberon_type_t * rec) { struct gen_class * class; class = rec -> gen_type -> class; int num = rec -> num_decl; oberon_object_t * field = rec -> decl; for(int i = 0; i < num; i++) { gen_var_t * v = field -> gen_var; char * name = field -> name; char * desc = jvm_get_descriptor(field -> type); jvm_generate_and_init_field(v, class, "public", name, desc); field = field -> next; } gen_proc_t * p = jvm_create_proc(class); jvm_generate_function_header(p, "public", "", "()V"); jvm_alloc_register_untyped(p -> rf, false); jvm_generate(p, 0, 1, "aload_0"); jvm_generate(p, 1, 0, "invokespecial java/lang/Object/()V"); num = rec -> num_decl; field = rec -> decl; for(int i = 0; i < num; i++) { if(field -> type -> class == OBERON_TYPE_RECORD || field -> type -> class == OBERON_TYPE_ARRAY) { jvm_generate(p, 0, 1, "aload_0"); jvm_generate_new_static(p, field -> type); jvm_generate_store(p, field -> type, field -> gen_var); } field = field -> next; } jvm_generate(p, 0, 0, "return"); jvm_generate_function_end(p); jvm_destroy_class(class); } void oberon_generator_init_var(oberon_context_t * ctx, oberon_object_t * var) { gen_var_t * v = oberon_generator_new_var(); var -> gen_var = v; gen_module_t * m; m = ctx -> mod -> gen_mod; struct gen_class * class; class = m -> class; char * desc; switch(var -> class) { case OBERON_CLASS_VAR_PARAM: gen_error("generator: VAR-parameters not implemented"); break; case OBERON_CLASS_PARAM: /* Заполняется при генерации функции */ /* смотри jvm_init_local_object() */ break; case OBERON_CLASS_FIELD: /* Заполняются при инициализации структуры */ /* смотри oberon_generator_init_record() */ break; case OBERON_CLASS_VAR: /* Локальные заполняются при генерации функции */ /* смотри jvm_init_local_object() */ if(var -> local == 0) { desc = jvm_get_descriptor(var -> type); jvm_generate_and_init_global_var(v, class, "public", var -> name, desc); } break; default: gen_error("oberon_generator_init_var: unk var class %i", var -> class); break; } } void oberon_generator_init_proc(oberon_context_t * ctx, oberon_object_t * proc) { struct gen_class * class = proc -> module -> gen_mod -> class; proc -> gen_proc = jvm_create_proc(class); if(proc -> local) { gen_error("generator: local procedures not implemented"); } } void oberon_generator_init_module(oberon_context_t * ctx, oberon_module_t * mod) { gen_module_t * m = GC_MALLOC(sizeof *m); memset(m, 0, sizeof *m); mod -> gen_mod = m; struct gen_class * class; class = jvm_create_class(mod -> name); fprintf(class -> fp, ".source %s\n", mod -> name); fprintf(class -> fp, ".class %s\n", mod -> name); fprintf(class -> fp, ".super java/lang/Object\n\n"); m -> class = class; ctx -> gen_context -> current_m = m; } void oberon_generator_fini_module(oberon_module_t * mod) { jvm_destroy_class(mod -> gen_mod -> class); } static void push_expr(gen_proc_t * p, oberon_expr_t * expr); void oberon_generate_begin_module(oberon_context_t * ctx) { struct gen_class * class = ctx -> mod -> gen_mod -> class; gen_proc_t * p = jvm_create_proc(class); jvm_generate_function_header(p, "public", "", "()V"); jvm_alloc_register_untyped(p -> rf, false); jvm_generate(p, 0, 1, "aload_0"); jvm_generate(p, 1, 0, "invokespecial java/lang/Object/()V"); } void oberon_generate_end_module(oberon_context_t * ctx) { struct gen_class * class = ctx -> mod -> gen_mod -> class; gen_proc_t * p = class -> p; jvm_generate(p, 0, 0, "return"); jvm_generate_function_end(class -> p); } static void jvm_init_local_object(gen_proc_t * p, oberon_object_t * x) { gen_var_t * v; bool wide; char * desc; struct gen_class * class; v = x -> gen_var; class = p -> class; wide = jvm_is_wide_type(x -> type); desc = jvm_get_descriptor(x -> type); // Убеждаемся что сейчас находимся в функции assert(class -> p); assert(x -> local); switch(x -> class) { case OBERON_CLASS_VAR: case OBERON_CLASS_PARAM: jvm_generate_and_init_named_local_var(v, p, wide, x -> name, desc); break; default: gen_error("jvm_init_local_object: wat"); break; } } void oberon_generate_begin_proc(oberon_context_t * ctx, oberon_object_t * proc) { gen_proc_t * p; char * signature; 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; } } void oberon_generate_end_proc(oberon_context_t * ctx) { gen_module_t * m; gen_proc_t * p; m = ctx -> mod -> gen_mod; p = m -> class -> p; jvm_generate_function_end(p); } static void jvm_generate_call_proc(gen_proc_t * p, oberon_expr_t * desig) { assert(desig -> is_item); assert(desig -> item.mode == MODE_CALL); oberon_object_t * proc; char * fullname; char * signature; proc = desig -> item.var; fullname = jvm_get_field_full_name(proc); signature = jvm_get_procedure_signature(proc -> type); int args_cells = 0; int result_cells = jvm_cell_size_for_type(proc -> type -> base); int num = desig -> item.num_args; oberon_expr_t * arg = desig -> item.args; for(int i = 0; i < num; i++) { args_cells += jvm_cell_size_for_type(arg -> result); push_expr(p, arg); arg = arg -> next; } jvm_generate(p, args_cells, result_cells, "invokestatic %s%s", fullname, signature); } void oberon_generate_call_proc(oberon_context_t * ctx, oberon_expr_t * desig) { jvm_generate_call_proc(ctx -> gen_context -> current_m -> class -> p, desig); } void oberon_generate_return(oberon_context_t * ctx, oberon_expr_t * expr) { gen_module_t * m; gen_proc_t * p; char prefix; int cell_size; m = ctx -> mod -> gen_mod; p = m -> class -> p; if(expr) { push_expr(p, expr); prefix = jvm_get_prefix(expr -> result); cell_size = jvm_cell_size_for_type(expr -> result); jvm_generate(p, cell_size, 0, "%creturn", prefix); } else { jvm_generate(p, 0, 0, "return"); } } static void jvm_push_var(gen_proc_t * p, oberon_object_t * var) { int cell_size = jvm_cell_size_for_type(var -> type); if(var -> local) { int reg = var -> gen_var -> reg; char prefix = jvm_get_prefix(var -> type); jvm_generate(p, 0, cell_size, "%cload %i", prefix, reg); } else { char * fullname = jvm_get_field_full_name(var); char * desc = jvm_get_descriptor(var -> type); jvm_generate(p, 0, cell_size, "getstatic %s %s", fullname, desc); } } static void jvm_generate_expr_new_static(gen_proc_t * p, oberon_type_t * type, int num, oberon_expr_t * arg) { assert(num == 0); jvm_generate_new_static(p, type); } static void jvm_generate_expr_new_pointer(gen_proc_t * p, oberon_type_t * type, int num, oberon_expr_t * arg) { assert(type -> class == OBERON_TYPE_POINTER); jvm_generate_expr_new_static(p, type -> base, num, arg); } static void push_item(gen_proc_t * p, oberon_item_t * item) { switch(item -> mode) { case MODE_VAR: jvm_push_var(p, item -> var); break; case MODE_INTEGER: jvm_generate_push_int(p, item -> integer); break; case MODE_BOOLEAN: jvm_generate_push_int(p, item -> boolean); break; case MODE_CALL: jvm_generate_call_proc(p, (oberon_expr_t *) item); break; case MODE_INDEX: gen_error("push_item: TODO index"); break; case MODE_FIELD: push_item(p, item -> parent); char * field = jvm_get_field_full_name(item -> var); char * desc = jvm_get_descriptor(item -> var -> type); jvm_generate(p, 1, 1, "getfield %s %s", field, desc); break; case MODE_DEREF: /* Все объекты представляются как увказатели */ push_item(p, item -> parent); break; case MODE_NIL: jvm_generate(p, 0, 1, "aconst_null"); break; case MODE_NEW: jvm_generate_expr_new_pointer(p, item -> result, item -> num_args, item -> args); break; case MODE_REAL: jvm_generate_push_float(p, item -> real, item -> result -> size); break; default: gen_error("push_item: unk mode %i", item -> mode); break; } } static void jvm_generate_logical_not(gen_proc_t * p) { int label_done = jvm_new_label_id(p); int label_false = jvm_new_label_id(p); char * label_name_done = jvm_get_label_name(label_done); char * label_name_false = jvm_get_label_name(label_false); jvm_generate(p, 1, 0, "ifne %s", label_name_false); jvm_generate(p, 0, 1, "iconst_1"); jvm_generate(p, 0, 0, "goto %s", label_name_done); jvm_generate_label(p, label_false); jvm_generate(p, 0, 1, "iconst_0"); jvm_generate_label(p, label_done); } static void jvm_generate_abs(gen_proc_t * p, char prefix) { char t = jvm_get_type_of_prefix(prefix); int cell_size = jvm_cell_size_for_prefix(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) { 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_prefix(prefix); assert(prefix == 'i' || prefix == 'a'); const char * cmpop = ""; switch(op) { case OP_EQ: cmpop = "eq"; break; case OP_NEQ: cmpop = "ne"; break; case OP_LSS: cmpop = "lt"; break; case OP_LEQ: cmpop = "le"; break; case OP_GRT: cmpop = "gt"; break; case OP_GEQ: cmpop = "ge"; break; default: gen_error("jvm_generate_compare_op: wat"); break; } 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_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) { int cell_size = jvm_cell_size_for_prefix(prefix); switch(op) { case OP_UNARY_MINUS: jvm_generate(p, cell_size, cell_size, "%cneg", prefix); break; case OP_BITWISE_NOT: jvm_generate_push_int(p, -1); jvm_generate(p, 2 * cell_size, cell_size, "%cxor", prefix); break; case OP_LOGIC_NOT: jvm_generate_logical_not(p); break; case OP_ABS: jvm_generate_abs(p, prefix); break; case OP_ADD: jvm_generate(p, 2 * cell_size, cell_size, "%cadd", prefix); break; case OP_SUB: jvm_generate(p, 2 * cell_size, cell_size, "%csub", prefix); break; case OP_MUL: jvm_generate(p, 2 * cell_size, cell_size, "%cmul", prefix); break; case OP_DIV: jvm_generate(p, 2 * cell_size, cell_size, "%cdiv", prefix); break; case OP_MOD: jvm_generate(p, 2 * cell_size, cell_size, "%crem", prefix); break; case OP_BITWISE_AND: jvm_generate(p, 2 * cell_size, cell_size, "%cand", prefix); break; case OP_BITWISE_XOR: jvm_generate(p, 2 * cell_size, cell_size, "%cxor", prefix); break; case OP_BITWISE_OR: jvm_generate(p, 2 * cell_size, cell_size, "%cor", prefix); break; case OP_EQ: case OP_NEQ: case OP_LSS: case OP_LEQ: case OP_GRT: case OP_GEQ: jvm_generate_compare_op(p, prefix, op); break; default: gen_error("jvm_generate_operator: unk op %i", op); break; } } static void jvm_generate_logical_or(gen_proc_t * p, oberon_expr_t * a, oberon_expr_t * b) { int label_calc_b = jvm_new_label_id(p); int label_done = jvm_new_label_id(p); char * label_name_calc_b = jvm_get_label_name(label_calc_b); char * label_name_done = jvm_get_label_name(label_done); /* a OR b -- если a, то TRUE, иначе b */ push_expr(p, a); jvm_generate(p, 1, 0, "ifne %s", label_name_calc_b); jvm_generate(p, 0, 1, "iconst_1"); jvm_generate(p, 0, 0, "goto %s", label_name_done); jvm_generate_label(p, label_calc_b); push_expr(p, b); jvm_generate_label(p, label_done); } static void jvm_generate_logical_and(gen_proc_t * p, oberon_expr_t * a, oberon_expr_t * b) { int label_false = jvm_new_label_id(p); int label_done = jvm_new_label_id(p); char * label_name_false = jvm_get_label_name(label_false); char * label_name_done = jvm_get_label_name(label_done); /* a AND b -- если a, то b, иначе FALSE */ push_expr(p, a); jvm_generate(p, 1, 0, "ifne %s", label_name_false); push_expr(p, b); jvm_generate(p, 0, 0, "goto %s", label_name_done); jvm_generate_label(p, label_false); jvm_generate(p, 0, 1, "iconst_0"); jvm_generate_label(p, label_done); } static void push_operator(gen_proc_t * p, oberon_oper_t * oper) { char prefix = jvm_get_prefix(oper -> result); int op = oper -> op; switch(op) { case OP_UNARY_MINUS: case OP_BITWISE_NOT: case OP_LOGIC_NOT: case OP_ABS: push_expr(p, oper -> left); jvm_generate_operator(p, 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(p, oper -> left); push_expr(p, oper -> right); jvm_generate_operator(p, prefix, op); break; case OP_LOGIC_OR: jvm_generate_logical_or(p, oper -> left, oper -> right); break; case OP_LOGIC_AND: jvm_generate_logical_and(p, oper -> left, oper -> right); break; default: gen_error("push_oper: unk op %i", op); break; } } static void push_expr(gen_proc_t * p, oberon_expr_t * expr) { if(expr -> is_item) { push_item(p, (oberon_item_t *) expr); } else { push_operator(p, (oberon_oper_t *) expr); } } static void store_expr(gen_proc_t * p, oberon_expr_t * dst, oberon_expr_t * src) { assert(dst -> is_item); oberon_item_t * item = (oberon_item_t *) dst; switch(item -> mode) { case MODE_VAR: push_expr(p, src); jvm_generate_store(p, src -> result, item -> var -> gen_var); break; case MODE_INDEX: gen_error("store_expr: TODO index"); break; case MODE_FIELD: push_item(p, item -> parent); push_expr(p, src); jvm_generate_store(p, src -> result, item -> var -> gen_var); break; default: gen_error("store_expr: unk mode %i", item -> mode); break; } } /* static void store_expr(gen_proc_t * p, oberon_expr_t * dst, oberon_expr_t * src) { assert(dst -> is_item); oberon_item_t * item = (oberon_item_t *) dst; int cell_size = jvm_cell_size_for_type(src -> result); char prefix; switch(item -> mode) { case MODE_VAR: push_expr(p, src); if(item -> var -> local) { int reg = item -> var -> gen_var -> reg; prefix = jvm_get_prefix(item -> result); jvm_generate(p, cell_size, 0, "%cstore %i", prefix, reg); } else { char * fullname = jvm_get_field_full_name(item -> var); char * desc = jvm_get_descriptor(item -> result); jvm_generate(p, cell_size, 0, "putstatic %s %s", fullname, desc); } break; case MODE_INDEX: gen_error("store_expr: TODO index"); break; case MODE_FIELD: { char * fullname = jvm_get_field_full_name(item -> var); char * desc = jvm_get_descriptor(item -> result); push_item(p, item -> parent); push_expr(p, src); jvm_generate(p, 1 + cell_size, 0, "putfield %s %s", fullname, desc); } break; default: gen_error("store_expr: unk mode %i", item -> mode); break; } } */ void oberon_generate_assign(oberon_context_t * ctx, oberon_expr_t * src, oberon_expr_t * dst) { gen_module_t * m; gen_proc_t * p; m = ctx -> mod -> gen_mod; p = m -> class -> p; store_expr(p, dst, src); } void oberon_generate_code(oberon_context_t * ctx) { printf("generate code\n"); } void oberon_generator_dump(oberon_context_t * ctx, char * path) { printf("jit: dump code\n"); } void * oberon_generator_get_procedure(oberon_context_t * ctx, const char * name) { printf("jit: get pointer to procedure %s\n", name); return NULL; } void * oberon_generator_get_var(oberon_context_t * ctx, const char * name) { printf("jit: get pointer to var %s\n", name); return NULL; }