From 33dd153448f426558fede7a951be657622163e76 Mon Sep 17 00:00:00 2001 From: DeaDDooMER Date: Wed, 26 Jul 2017 20:06:00 +0300 Subject: [PATCH] =?utf8?q?JVM:=20=D0=A0=D0=B5=D0=B0=D0=BB=D0=B8=D0=B7?= =?utf8?q?=D0=BE=D0=B2=D0=B0=D0=BD=D1=8B=20=D0=BB=D0=BE=D0=BA=D0=B0=D0=BB?= =?utf8?q?=D1=8C=D0=BD=D1=8B=D0=B5=20=D0=BF=D0=B5=D1=80=D0=B5=D0=BC=D0=B5?= =?utf8?q?=D0=BD=D0=BD=D1=8B=D0=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit --- jvm_test.sh | 13 ++- notes | 2 + src/backends/jvm/generator-jvm.c | 158 ++++++++++++++++++++++++++++--- src/backends/jvm/generator-jvm.h | 6 +- src/test.c | 5 +- 5 files changed, 166 insertions(+), 18 deletions(-) diff --git a/jvm_test.sh b/jvm_test.sh index 9dce872..2d8ee55 100755 --- a/jvm_test.sh +++ b/jvm_test.sh @@ -4,12 +4,17 @@ set -e ./make.sh jvm ./run.sh -jasmin *.j -proguard -injars . \ + +rm -rf classes +mkdir -p classes +javac -d classes Launcher.java +jasmin -d classes *.j + +proguard -injars classes \ -libraryjars /usr/lib/jvm/java-8-openjdk/jre/lib/rt.jar \ - -dontshrink -dontobfuscate -keep class Test + -dontshrink -dontobfuscate -keep class Test -keep class Launcher -java -cp . Launcher Test +java -cp classes Launcher Test echo Everythin ok! Wheee... diff --git a/notes b/notes index 60b17bd..c6cd902 100644 --- a/notes +++ b/notes @@ -1,3 +1,5 @@ +- унарный минус имеет не правильный приоритет + - нет символов и строк - нужен автокаст int -> real для DIV. Да и вообще каст типов. diff --git a/src/backends/jvm/generator-jvm.c b/src/backends/jvm/generator-jvm.c index dc04ffe..c217ccb 100644 --- a/src/backends/jvm/generator-jvm.c +++ b/src/backends/jvm/generator-jvm.c @@ -369,6 +369,10 @@ oberon_generator_init_proc(oberon_context_t * ctx, oberon_object_t * proc) 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"); @@ -424,16 +428,157 @@ oberon_generate_end_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); + + /* Сохраняем регистровый файл в стеке */ + 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 %i\n", c -> rf -> max_used); + fprintf(m -> fp, ".end method\n\n"); + + /* Возвращаем исходный регистровый файл */ + c -> rf = c -> rf -> up; } void @@ -463,17 +608,6 @@ oberon_generate_call_proc(oberon_context_t * ctx, oberon_expr_t * desig) fprintf(m -> fp, "invokestatic %s%s\n", fullname, signature); } -void -oberon_generate_end_proc(oberon_context_t * ctx) -{ - gen_module_t * m; - m = ctx -> mod -> gen_mod; - - fprintf(m -> fp, " .limit stack 32\n"); - fprintf(m -> fp, " .limit locals 32\n"); - fprintf(m -> fp, ".end method\n\n"); -} - void oberon_generate_return(oberon_context_t * ctx, oberon_expr_t * expr) { diff --git a/src/backends/jvm/generator-jvm.h b/src/backends/jvm/generator-jvm.h index 9357519..01c29ee 100644 --- a/src/backends/jvm/generator-jvm.h +++ b/src/backends/jvm/generator-jvm.h @@ -4,13 +4,16 @@ struct gen_register_file { struct { bool used; + bool wide; } reg[MAX_REGISTERS]; + int num_used; int max_used; + struct gen_register_file * up; }; struct gen_proc_t { - + struct gen_register_file * rf; }; struct gen_type_t @@ -32,6 +35,7 @@ struct gen_block_t struct gen_context_t { gen_module_t * m; + struct gen_register_file * rf; }; struct gen_module_t diff --git a/src/test.c b/src/test.c index e042f24..eb1008c 100644 --- a/src/test.c +++ b/src/test.c @@ -11,8 +11,11 @@ static char source_test[] = " x : INTEGER;" "" "PROCEDURE Tier(x : INTEGER) : INTEGER;" + "VAR" + " y, z, w : INTEGER;" "BEGIN" - " RETURN x * x;" + " y := 7777;" + " RETURN x * x + y;" "END Tier;" "" "BEGIN;" -- 2.29.2