index 2a2abcdcd3632f1b73a22aecc2135138f8e94523..c217ccb3d6f37ebb809bf076dcd35e62636d3c5e 100644 (file)
fprintf(fp, " aload_0\n");
fprintf(fp, " invokespecial java/lang/Object/<init>()V\n");
fprintf(fp, " return\n");
- fprintf(fp, ".end method\n");
+ fprintf(fp, ".end method\n\n");
fprintf(fp, ".method public abstract invoke%s\n", signature);
fprintf(fp, ".end method\n\n");
switch(var -> class)
{
+ case OBERON_CLASS_VAR_PARAM:
+ oberon_error(ctx, "generator: VAR-parameters not implemented");
+ break;
case OBERON_CLASS_PARAM:
case OBERON_CLASS_FIELD:
break;
memset(p, 0, sizeof *p);
proc -> gen_proc = p;
+ struct gen_register_file * rf = GC_MALLOC(sizeof *rf);
+ memset(rf, 0, sizeof *rf);
+ p -> rf = rf;
+
if(proc -> local)
{
oberon_error(ctx, "generator: local procedures not implemented");
// GENERATOR
// =======================================================================
+static void
+push_expr(oberon_context_t * ctx, FILE * fp, oberon_expr_t * expr);
+
void
oberon_generate_begin_module(oberon_context_t * ctx)
{
fprintf(m -> fp, ".end method\n");
}
+static int
+jvm_cell_size_for_type(oberon_type_t * type)
+{
+ if(type -> class == OBERON_TYPE_INTEGER
+ || type -> class == OBERON_TYPE_REAL)
+ {
+ if(type -> size > 4)
+ {
+ return 2;
+ }
+ }
+
+ return 1;
+}
+
+static bool
+jvm_is_wide_type(oberon_type_t * type)
+{
+ int cell;
+ cell = jvm_cell_size_for_type(type);
+ assert(cell <= 2);
+ return (cell == 2);
+}
+
+static bool
+jvm_is_free_register(struct gen_register_file * rf, int i, bool wide)
+{
+ if(wide)
+ {
+ assert(i + 1 < MAX_REGISTERS);
+ return !(rf -> reg[i].used || rf -> reg[i + 1].used);
+ }
+ else
+ {
+ assert(i < MAX_REGISTERS);
+ return !(rf -> reg[i].used);
+ }
+}
+
+static int
+jvm_alloc_register(struct gen_register_file * rf, oberon_type_t * type)
+{
+ bool wide;
+ wide = jvm_is_wide_type(type);
+
+ int i = 0;
+ while(i < MAX_REGISTERS && !jvm_is_free_register(rf, i, wide))
+ {
+ i += 1;
+ }
+
+ if(wide)
+ {
+ assert(i + 1 <= MAX_REGISTERS);
+ rf -> num_used += 2;
+ rf -> reg[i].used = true;
+ rf -> reg[i + 1].used = true;
+ rf -> reg[i].used = true;
+ rf -> reg[i + 1].wide = false;
+ }
+ else
+ {
+ assert(i <= MAX_REGISTERS);
+ rf -> num_used += 2;
+ rf -> reg[i].used = true;
+ rf -> reg[i].wide = false;
+ }
+
+ if(rf -> num_used > rf -> max_used)
+ {
+ rf -> max_used = rf -> num_used;
+ }
+
+ return i;
+}
+
+static void
+jvm_init_local_object(oberon_context_t * ctx, FILE * fp, oberon_object_t * x)
+{
+ int reg;
+ gen_context_t * c;
+ gen_var_t * v;
+ char * desc;
+
+ c = ctx -> gen_context;
+ v = x -> gen_var;
+ desc = get_descriptor(ctx, x -> type);
+
+ reg = -1;
+ switch(x -> class)
+ {
+ case OBERON_CLASS_VAR:
+ case OBERON_CLASS_PARAM:
+ if(x -> local)
+ {
+ reg = jvm_alloc_register(c -> rf, x -> type);
+ }
+ v -> reg = reg;
+ fprintf(fp, ".var %i is %s %s from start to end\n", reg, x -> name, desc);
+ break;
+ default:
+ oberon_error(ctx, "jvm_init_local_object: wat");
+ break;
+ }
+}
+
void
oberon_generate_begin_proc(oberon_context_t * ctx, oberon_object_t * proc)
{
+ gen_context_t * c;
gen_module_t * m;
+ gen_proc_t * p;
char * signature;
+ c = ctx -> gen_context;
m = ctx -> mod -> gen_mod;
- signature = get_procedure_signature(ctx, proc -> type);
+ p = proc -> gen_proc;
+ signature = get_procedure_signature(ctx, proc -> type);
fprintf(m -> fp, ".method public static %s%s\n", proc -> name, signature);
-}
-void
-oberon_generate_call_proc(oberon_context_t * ctx, oberon_expr_t * desig)
-{
- printf("call proc\n");
+ /* Сохраняем регистровый файл в стеке */
+ p -> rf -> up = c -> rf;
+ c -> rf = p -> rf;
+
+ oberon_object_t * var = proc -> type -> decl;
+ while(var)
+ {
+ jvm_init_local_object(ctx, m -> fp, var);
+ var = var -> next;
+ }
+
+ fprintf(m -> fp, "start:\n");
}
void
oberon_generate_end_proc(oberon_context_t * ctx)
{
+ gen_context_t * c;
gen_module_t * m;
+
+ c = ctx -> gen_context;
m = ctx -> mod -> gen_mod;
+ fprintf(m -> fp, "end:\n");
fprintf(m -> fp, " .limit stack 32\n");
- fprintf(m -> fp, " .limit locals 32\n");
+ fprintf(m -> fp, " .limit locals %i\n", c -> rf -> max_used);
fprintf(m -> fp, ".end method\n\n");
+
+ /* Возвращаем исходный регистровый файл */
+ c -> rf = c -> rf -> up;
+}
+
+void
+oberon_generate_call_proc(oberon_context_t * ctx, oberon_expr_t * desig)
+{
+ oberon_object_t * proc;
+ gen_module_t * m;
+ char * fullname;
+ char * signature;
+
+ assert(desig -> is_item);
+ assert(desig -> item.mode == MODE_CALL);
+
+ m = ctx -> mod -> gen_mod;
+ proc = desig -> item.var;
+ fullname = get_field_full_name(ctx, proc);
+ signature = get_procedure_signature(ctx, proc -> type);
+
+ int num = desig -> item.num_args;
+ oberon_expr_t * arg = desig -> item.args;
+ for(int i = 0; i < num; i++)
+ {
+ push_expr(ctx, m -> fp, arg);
+ arg = arg -> next;
+ }
+
+ fprintf(m -> fp, "invokestatic %s%s\n", fullname, signature);
}
void
oberon_generate_return(oberon_context_t * ctx, oberon_expr_t * expr)
{
gen_module_t * m;
+ char prefix;
m = ctx -> mod -> gen_mod;
if(expr)
{
- oberon_error(ctx, "oberon_generate_return: TODO return expr");
+ push_expr(ctx, m -> fp, expr);
+ prefix = get_prefix(ctx, expr -> result);
+ fprintf(m -> fp, " %creturn\n", prefix);
}
else
{
}
}
-static void push_expr(oberon_context_t * ctx, FILE * fp, oberon_expr_t * expr);
-
static void
push_var(oberon_context_t * ctx, FILE * fp, oberon_object_t * var)
{
push_int(fp, item -> boolean);
break;
case MODE_CALL:
- oberon_error(ctx, "push_item: TODO call");
+ oberon_generate_call_proc(ctx, (oberon_expr_t *) item);
break;
case MODE_INDEX:
oberon_error(ctx, "push_item: TODO index");