DEADSOFTWARE

Первые наработки бэкэнда для jvm
authorDeaDDooMER <deaddoomer@deadsoftware.ru>
Tue, 25 Jul 2017 17:51:11 +0000 (20:51 +0300)
committerDeaDDooMER <deaddoomer@deadsoftware.ru>
Tue, 25 Jul 2017 17:51:11 +0000 (20:51 +0300)
13 files changed:
.gitignore
Launcher.java [new file with mode: 0644]
jvm_test.sh [new file with mode: 0755]
make.sh
src/backends/dummy/generator-dummy.c [moved from src/backends/dummy/generator-libgccjit.c with 98% similarity]
src/backends/dummy/generator-dummy.h [moved from src/backends/dummy/generator-libgccjit.h with 100% similarity]
src/backends/jvm/generator-jvm.c [new file with mode: 0644]
src/backends/jvm/generator-jvm.h [new file with mode: 0644]
src/generator.h
src/oberon-internals.h
src/oberon.c
src/test.c
tst.java [new file with mode: 0644]

index bbbc7ed94402c43a37c1fddd5e9bd0d0b86d1a1f..6cd2ab3a081c657a4b4dd104c2c87a7eb72f44b0 100644 (file)
@@ -1,2 +1,4 @@
 *.out
 dump.txt
+*.j
+*.class
diff --git a/Launcher.java b/Launcher.java
new file mode 100644 (file)
index 0000000..220f671
--- /dev/null
@@ -0,0 +1,6 @@
+class Launcher {
+       public static void main(String[] args)
+       throws ClassNotFoundException, InstantiationException, IllegalAccessException {
+               Class.forName(args[0]).newInstance();;
+       }
+}
diff --git a/jvm_test.sh b/jvm_test.sh
new file mode 100755 (executable)
index 0000000..9dce872
--- /dev/null
@@ -0,0 +1,15 @@
+#!/bin/sh
+
+set -e
+
+./make.sh jvm
+./run.sh
+jasmin *.j
+proguard -injars . \
+       -libraryjars /usr/lib/jvm/java-8-openjdk/jre/lib/rt.jar \
+       -dontshrink -dontobfuscate -keep class Test
+
+java -cp . Launcher Test
+
+echo Everythin ok! Wheee...
+
diff --git a/make.sh b/make.sh
index 9e4b2551b852601b51ca3a7840b8c90d7d226739..561238eda9798416c20e73fb5c80f65c3312c8f5 100755 (executable)
--- a/make.sh
+++ b/make.sh
@@ -9,11 +9,14 @@ case "$1" in
   dummy)
     $CC $CFLAGS src/*.c src/backends/dummy/*.c
   ;;
+  jvm)
+    $CC $CFLAGS src/*.c src/backends/jvm/*.c
+  ;;
   libgccjit)
     CFLAGS="-lgccjit $CFLAGS"
     $CC $CFLAGS src/*.c src/backends/libgccjit/*.c
   ;;
   ***)
     echo "use: make.sh <backend>"
-    echo "list of backends: dummy libgccjit"
+    echo "list of backends: dummy jvm libgccjit"
 esac
similarity index 98%
rename from src/backends/dummy/generator-libgccjit.c
rename to src/backends/dummy/generator-dummy.c
index e9b26b514b3bcf192b612b9ffdaeb4a8038c07b1..fc709a075baf48e2bb141e671a7059daa4a9d084 100644 (file)
@@ -5,7 +5,7 @@
 
 #include "../../../include/oberon.h"
 #include "../../oberon-internals.h"
-#include "generator-libgccjit.h"
+#include "generator-dummy.h"
 
 void
 oberon_generator_init_context(oberon_context_t * ctx)
diff --git a/src/backends/jvm/generator-jvm.c b/src/backends/jvm/generator-jvm.c
new file mode 100644 (file)
index 0000000..2a2abcd
--- /dev/null
@@ -0,0 +1,744 @@
+#include <stdio.h>
+#include <stdarg.h>
+#include <stdbool.h>
+#include <string.h>
+#include <assert.h>
+
+#include <gc.h>
+
+#include "../../../include/oberon.h"
+#include "../../oberon-internals.h"
+#include "generator-jvm.h"
+
+char *
+new_string(const char * format, ...)
+{
+       va_list ptr;
+       va_start(ptr, format);
+
+       char buf[1024];
+       vsnprintf(buf, 1024, format, ptr);
+
+       va_end(ptr);
+
+       char * result;
+       int size;
+
+       size = strlen(buf);
+       result = GC_MALLOC(size + 1);
+       memset(result, 0, size);
+       strncpy(result, buf, size);
+
+       return result;
+}
+
+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)
+{
+       ctx -> gen_context = NULL;
+}
+
+static char * get_class_full_name(oberon_context_t * ctx, oberon_type_t * type);
+
+static char *
+get_descriptor(oberon_context_t * ctx, oberon_type_t * type)
+{
+       char * desc;
+
+       switch(type -> class)
+       {
+               case OBERON_TYPE_VOID:
+                       return new_string("V");
+                       break;
+               case OBERON_TYPE_INTEGER:
+                       switch(type -> size)
+                       {
+                               case 1:
+                                       return new_string("B");
+                                       break;
+                               case 2:
+                                       return new_string("S");
+                                       break;
+                               case 4:
+                                       return new_string("I");
+                                       break;
+                               case 8:
+                                       return new_string("J");
+                                       break;
+                               default:
+                                       oberon_error(ctx, "get_descriptor: unsupported int size %i", type -> size);
+                                       break;
+                       }
+                       break;
+               case OBERON_TYPE_REAL:
+                       switch(type -> size)
+                       {
+                               case 4:
+                                       return new_string("F");
+                                       break;
+                               case 8:
+                                       return new_string("D");
+                                       break;
+                               default:
+                                       oberon_error(ctx, "get_descriptor: unsupported float size %i", type -> size);
+                                       break;
+                       }
+                       break;
+               case OBERON_TYPE_BOOLEAN:
+                       return new_string("Z");
+                       break;
+               case OBERON_TYPE_PROCEDURE:
+               case OBERON_TYPE_RECORD:
+                       desc = get_class_full_name(ctx, type);
+                       return new_string("L%s;", desc);
+                       break;
+               case OBERON_TYPE_ARRAY:
+                       desc = get_descriptor(ctx, type -> base);
+                       return new_string("[%s", desc);
+                       break;
+               default:
+                       oberon_error(ctx, "print_descriptor: unsupported type class %i", type -> class);
+                       break;
+       }
+
+       return NULL;
+}
+
+static char
+get_prefix(oberon_context_t * ctx, oberon_type_t * type)
+{
+       int size = type -> size;
+       switch(type -> class)
+       {
+               case OBERON_TYPE_BOOLEAN:
+               case OBERON_TYPE_INTEGER:
+                       return (size <= 4) ? ('i') : ('l');
+                       break;
+               case OBERON_TYPE_PROCEDURE:
+               case OBERON_TYPE_ARRAY:
+               case OBERON_TYPE_RECORD:
+               case OBERON_TYPE_POINTER:
+                       return 'a';
+                       break;
+               case OBERON_TYPE_REAL:
+                       return (size <= 4) ? ('f') : ('d');
+                       break;
+       }
+
+       oberon_error(ctx, "get_prefix: wat");
+       return '!';
+}
+
+static char *
+get_field_full_name(oberon_context_t * ctx, oberon_object_t * x)
+{
+       return new_string("%s/%s", x -> module -> name, x -> name);
+}
+
+static char *
+get_class_full_name(oberon_context_t * ctx, oberon_type_t * type)
+{
+       int rec_id;
+       char * name = NULL;
+
+       switch(type -> class)
+       {
+               case OBERON_TYPE_PROCEDURE:
+                       name = new_string("SYSTEM$PROCEDURE");
+
+                       char * desc;
+                       desc = get_descriptor(ctx, type -> base);
+                       name = new_string("%s$%s", name, desc);
+
+                       int num = type -> num_decl;
+                       oberon_object_t * arg = type -> decl;
+                       for(int i = 0; i < num; i++)
+                       {
+                               desc = get_descriptor(ctx, arg -> type);
+                               name = new_string("%s%s", name, desc);
+                               arg = arg -> next;
+                       }
+
+                       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;
+               default:
+                       oberon_error(ctx, "get_record_full_name: unk type class %i", type -> class);
+                       break;
+       }
+
+       return name;
+}
+
+static char *
+get_procedure_signature(oberon_context_t * ctx, oberon_type_t * proc)
+{
+       char * signature;
+       char * desc;
+
+       signature = new_string("(");
+
+       int num = proc -> num_decl;
+       oberon_object_t * arg = proc -> decl;
+       for(int i = 0; i < num; i++)
+       {
+               desc = get_descriptor(ctx, arg -> type);
+               signature = new_string("%s%s", signature, desc);
+               arg = arg -> next;
+       }
+
+       desc = get_descriptor(ctx, proc -> base);
+       signature = new_string("%s)%s", signature, desc);
+
+       return signature;
+}
+
+static void
+oberon_generate_procedure_class(oberon_context_t * ctx, oberon_type_t * proc)
+{
+       FILE * fp;
+       char * cname;
+       char * fname;
+       char * signature;
+
+       cname = get_class_full_name(ctx, proc);
+       fname = new_string("%s.j", cname);
+
+       fp = fopen(fname, "w");
+
+       fprintf(fp, ".source SYSTEM\n");
+       fprintf(fp, ".class  public abstract %s\n", cname);
+       fprintf(fp, ".super  java/lang/Object\n\n");
+
+       signature = get_procedure_signature(ctx, proc);
+
+       fprintf(fp, ".method public <init>()V\n");
+       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, ".method public abstract invoke%s\n", signature);
+       fprintf(fp, ".end method\n\n");
+
+       fclose(fp);
+}
+
+static void
+oberon_generate_record_class(oberon_context_t * ctx, oberon_type_t * rec)
+{
+       FILE * fp;
+       char * cname;
+       char * fname;
+
+       /* Устанавливаем новоый id */
+       rec -> gen_type -> rec_id = rec -> module -> gen_mod -> rec_id;
+       rec -> module -> gen_mod -> rec_id += 1;
+
+       cname = get_class_full_name(ctx, rec);
+       fname = new_string("%s.j", cname);
+
+       fp = fopen(fname, "w");
+
+       fprintf(fp, ".source %s\n", rec -> module -> name);
+       fprintf(fp, ".class  public %s\n", cname);
+       fprintf(fp, ".super  java/lang/Object\n\n");
+
+       rec -> gen_type -> fp = fp;
+}
+
+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:
+                       oberon_generate_record_class(ctx, type);
+                       break;
+               case OBERON_TYPE_PROCEDURE:
+                       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);
+                       break;
+       }
+}
+
+static void
+oberon_generate_object(oberon_context_t * ctx, FILE * fp, oberon_object_t * x)
+{
+       char * name;
+       char * desc;
+
+       name = x -> name;
+       desc = get_descriptor(ctx, x -> type);
+       switch(x -> class)
+       {
+               case OBERON_CLASS_VAR:
+                       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);
+                       break;
+               default:
+                       oberon_error(ctx, "oberon_generate_object: unk class %i", x -> class);
+                       break;
+       }
+}
+
+void
+oberon_generator_init_record(oberon_context_t * ctx, oberon_type_t * rec)
+{
+       FILE * fp;
+
+       fp = rec -> gen_type -> fp;
+
+       int num = rec -> num_decl;
+       oberon_object_t * field = rec -> decl;
+       for(int i = 0; i < num; i++)
+       {
+               oberon_generate_object(ctx, fp, field);
+               field = field -> next;
+       }
+
+       fprintf(fp, ".method public <init>()V\n");
+       fprintf(fp, "  aload_0\n");
+       fprintf(fp, "  invokespecial java/lang/Object/<init>()V\n");
+       fprintf(fp, "  return\n");
+       fprintf(fp, ".end method\n");
+
+       fclose(fp);
+}
+
+void
+oberon_generator_init_var(oberon_context_t * ctx, oberon_object_t * var)
+{
+       gen_var_t * v = GC_MALLOC(sizeof *v);
+       memset(v, 0, sizeof *v);
+       var -> gen_var = v;
+
+       gen_module_t * m = ctx -> mod -> gen_mod;       
+
+       switch(var -> class)
+       {
+               case OBERON_CLASS_PARAM:
+               case OBERON_CLASS_FIELD:
+                       break;
+               case OBERON_CLASS_VAR:
+                       oberon_generate_object(ctx, m -> fp, var);
+                       break;
+               default:
+                       oberon_error(ctx, "oberon_generator_init_var: unk var class %i", var -> class);
+                       break;
+       }
+}
+
+void
+oberon_generator_init_proc(oberon_context_t * ctx, oberon_object_t * proc)
+{
+       gen_proc_t * p = GC_MALLOC(sizeof *p);
+       memset(p, 0, sizeof *p);
+       proc -> gen_proc = p;
+
+       if(proc -> local)
+       {
+               oberon_error(ctx, "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;
+
+       int fnamesz = strlen(mod -> name) + 3;
+       char fname[fnamesz + 1];
+       snprintf(fname, fnamesz, "%s.j", mod -> name);
+
+       FILE * fp;
+       fp = fopen(fname, "w");
+       assert(fp != NULL);
+
+       fprintf(fp, ".source %s\n", mod -> name);
+       fprintf(fp, ".class %s\n", mod -> name);
+       fprintf(fp, ".super java/lang/Object\n\n");
+
+       m -> fp = fp;
+}
+
+// =======================================================================
+//   GENERATOR
+// ======================================================================= 
+
+void
+oberon_generate_begin_module(oberon_context_t * ctx)
+{
+       gen_module_t * m = ctx -> mod -> gen_mod;
+       fprintf(m -> fp, ".method public <init>()V\n");
+       fprintf(m -> fp, "  aload_0\n");
+       fprintf(m -> fp, "  invokespecial java/lang/Object/<init>()V\n");
+}
+
+void
+oberon_generate_end_module(oberon_context_t * ctx)
+{
+       gen_module_t * m = ctx -> mod -> gen_mod;
+
+       fprintf(m -> fp, "  .limit stack 32\n");
+       fprintf(m -> fp, "  .limit locals 32\n");
+       fprintf(m -> fp, "  return\n");
+       fprintf(m -> fp, ".end method\n");
+}
+
+void
+oberon_generate_begin_proc(oberon_context_t * ctx, oberon_object_t * proc)
+{
+       gen_module_t * m;
+       char * signature;
+
+       m = ctx -> mod -> gen_mod;
+       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");
+}
+
+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)
+{
+       gen_module_t * m;
+
+       m = ctx -> mod -> gen_mod;
+
+       if(expr)
+       {
+               oberon_error(ctx, "oberon_generate_return: TODO return expr");
+       }
+       else
+       {
+               fprintf(m -> fp, "  return\n");
+       }
+}
+
+static void
+push_int(FILE * fp, long i)
+{
+       if(i == -1)
+       {
+               fprintf(fp, "iconst_m1\n");
+       }
+       else if(i >= 0 && i <= 5)
+       {
+               fprintf(fp, "iconst_%li\n", i);
+       }
+       else if(i >= -128 && i <= 127)
+       {
+               fprintf(fp, "bipush %li\n", i);
+       }
+       else if(i >= -32768 && i <= 32767)
+       {
+               fprintf(fp, "sipush %li\n", i);         
+       }
+       else if(i >= -2147483648 && i <= 2147483647)
+       {
+               fprintf(fp, "ldc %li\n", i);
+       }
+       else
+       {
+               fprintf(fp, "ldc2 %li\n", i);
+       }
+}
+
+static void
+push_float(FILE * fp, double f, int size)
+{
+       if(size <= 4)
+       {
+               if(f == 0.0)
+               {
+                       fprintf(fp, "fconst_0\n");
+               }
+               if(f == 1.0)
+               {
+                       fprintf(fp, "fconst_1\n");
+               }
+               if(f == 2.0)
+               {
+                       fprintf(fp, "fconst_2\n");
+               }
+               else
+               {
+                       fprintf(fp, "ldc %lf\n", f);
+               }
+       }
+       else
+       {
+               if(f == 0.0)
+               {
+                       fprintf(fp, "dconst_0\n");
+               }
+               if(f == 1.0)
+               {
+                       fprintf(fp, "dconst_1\n");
+               }
+               else
+               {
+                       fprintf(fp, "ldc2 %lf\n", f);
+               }
+       }
+}
+
+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)
+{
+       if(var -> local)
+       {
+               int reg = var -> gen_var -> reg;
+               char prefix = get_prefix(ctx, var -> type);
+               fprintf(fp, "%cload %i\n", prefix, reg);
+       }
+       else
+       {
+               char * fullname = get_field_full_name(ctx, var);
+               char * desc = get_descriptor(ctx, var -> type);
+               fprintf(fp, "getstatic %s %s\n", fullname, desc);
+       }
+}
+
+static void
+push_item(oberon_context_t * ctx, FILE * fp, oberon_item_t * item)
+{
+       switch(item -> mode)
+       {
+               case MODE_VAR:
+                       push_var(ctx, fp, item -> var);
+                       break;
+               case MODE_INTEGER:
+                       push_int(fp, item -> integer);
+                       break;
+               case MODE_BOOLEAN:
+                       push_int(fp, item -> boolean);
+                       break;
+               case MODE_CALL:
+                       oberon_error(ctx, "push_item: TODO call");
+                       break;
+               case MODE_INDEX:
+                       oberon_error(ctx, "push_item: TODO index");
+                       break;
+               case MODE_FIELD:
+                       oberon_error(ctx, "push_item: TODO field");
+                       break;
+               case MODE_DEREF:
+                       oberon_error(ctx, "push_item: TODO deref");
+                       break;
+               case MODE_NIL:
+                       fprintf(fp, "aconst_null\n");
+                       break;
+               case MODE_NEW:
+                       oberon_error(ctx, "push_item: TODO new");
+                       break;
+               case MODE_REAL:
+                       push_float(fp, item -> real, item -> result -> size);
+                       break;
+               default:
+                       oberon_error(ctx, "push_item: unk mode %i", item -> mode);
+                       break;
+       }
+}
+
+static void
+push_operator(oberon_context_t * ctx, FILE * fp, oberon_oper_t * oper)
+{
+       char prefix = get_prefix(ctx, oper -> result);
+       switch(oper -> 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_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;
+
+               case OP_EQ:
+               case OP_NEQ:
+               case OP_LSS:
+               case OP_LEQ:
+               case OP_GRT:
+               case OP_GEQ:
+               case OP_LOGIC_NOT:
+               case OP_ABS:
+                       oberon_error(ctx, "push_oper: TODO op %i", oper -> op);
+                       break;
+               default:
+                       oberon_error(ctx, "push_oper: unk op %i", oper -> op);
+                       break;
+       }
+}
+
+static void
+push_expr(oberon_context_t * ctx, FILE * fp, oberon_expr_t * expr)
+{
+       if(expr -> is_item)
+       {
+               push_item(ctx, fp, (oberon_item_t *) expr);
+       }
+       else
+       {
+               push_operator(ctx, fp, (oberon_oper_t *) expr);
+       }
+}
+
+static void
+store_expr(oberon_context_t * ctx, FILE * fp, oberon_expr_t * expr)
+{
+       assert(expr -> is_item);
+       oberon_item_t * item = (oberon_item_t *) expr;
+
+       char prefix;
+       switch(item -> mode)
+       {
+               case MODE_VAR:
+                       if(item -> var -> local)
+                       {
+                               int reg = item -> var -> gen_var -> reg;
+                               prefix = get_prefix(ctx, item -> result);
+                               fprintf(fp, "%cstore %i\n", prefix, reg);
+                       }
+                       else
+                       {
+                               char * fullname = get_field_full_name(ctx, item -> var);
+                               char * desc = get_descriptor(ctx, item -> result);
+                               fprintf(fp, "putstatic %s %s\n", fullname, desc);
+                       }
+                       break;
+               default:
+                       oberon_error(ctx, "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;
+       m = ctx -> mod -> gen_mod;
+
+       push_expr(ctx, m -> fp, src);
+       store_expr(ctx, m -> fp, dst);
+}
+
+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;
+}
diff --git a/src/backends/jvm/generator-jvm.h b/src/backends/jvm/generator-jvm.h
new file mode 100644 (file)
index 0000000..9357519
--- /dev/null
@@ -0,0 +1,41 @@
+#define MAX_REGISTERS 256
+
+struct gen_register_file {
+       struct
+       {
+               bool used;
+       } reg[MAX_REGISTERS];
+       int max_used;
+};
+
+struct gen_proc_t
+{
+
+};
+
+struct gen_type_t
+{
+       int rec_id;
+       FILE * fp;
+};
+
+struct gen_var_t
+{
+       int reg;
+};
+
+struct gen_block_t
+{
+
+};
+
+struct gen_context_t
+{
+       gen_module_t * m;
+};
+
+struct gen_module_t
+{
+       int rec_id;
+       FILE * fp;
+};
index 08df5c892abb414e4f376e6829a697554a5b6398..885b9faca57509a697088c697353a5808e3b7296 100644 (file)
@@ -7,6 +7,7 @@ void oberon_generator_init_type(oberon_context_t * ctx, oberon_type_t * type);
 void oberon_generator_init_record(oberon_context_t * ctx, oberon_type_t * type);
 void oberon_generator_init_var(oberon_context_t * ctx, oberon_object_t * var);
 void oberon_generator_init_proc(oberon_context_t * ctx, oberon_object_t * proc);
+void oberon_generator_init_module(oberon_context_t * ctx, oberon_module_t * mod);
 void oberon_generator_destroy_context(oberon_context_t * ctx);
 
 /*
index e265a79cc1b39aff1e2a6afa7d3b51913853c756..a6174c36094ea7e23fb510bfc65036953917c743 100644 (file)
@@ -1,6 +1,7 @@
 #ifndef OBERON_INTERNALS_H
 #define OBERON_INTERNALS_H
 
+typedef struct gen_module_t gen_module_t;
 typedef struct gen_proc_t gen_proc_t;
 typedef struct gen_type_t gen_type_t;
 typedef struct gen_var_t gen_var_t;
@@ -107,6 +108,8 @@ struct oberon_module_t
        oberon_scope_t * decl;
 
        oberon_module_t * next;
+
+       gen_module_t * gen_mod;
 };
 
 typedef const char * (*ModuleImportCallback)(const char * name);
@@ -168,7 +171,7 @@ enum
        OP_MOD,
        OP_BITWISE_AND,
        OP_BITWISE_XOR,
-       OP_BITWISE_OP,
+       OP_BITWISE_OR,
        OP_LOGIC_AND,
        OP_LOGIC_OR,
 
index d636fba6b19d253c65a167420a25f21547bef892..382f4f182b2e98ca1032a7f720cc575e58ae9fc5 100644 (file)
@@ -2083,6 +2083,7 @@ oberon_type(oberon_context_t * ctx, oberon_type_t ** type)
                oberon_type_t * rec;
                rec = *type;
                rec -> class = OBERON_TYPE_RECORD;
+               rec -> module = ctx -> mod;
 
                oberon_scope_t * record_scope;
                record_scope = oberon_open_scope(ctx);
@@ -2672,6 +2673,8 @@ oberon_parse_module(oberon_context_t * ctx)
        oberon_assert_token(ctx, SEMICOLON);
        ctx -> mod -> name = name1;
 
+       oberon_generator_init_module(ctx, ctx -> mod);
+
        if(ctx -> token == IMPORT)
        {
                oberon_import_list(ctx);
index 1c3c8e39347533eb9db1d0b2e289f0348f77b693..53be5869213c0d3ee4a5e3e7fcd30639cf82ea59 100644 (file)
@@ -7,40 +7,31 @@
 static char source_test[] =
        "(* Main module *)"
        "MODULE Test;"
-       "IMPORT Out;"
-       "TYPE Ar = ARRAY OF ARRAY OF INTEGER;"
-       "VAR a : POINTER TO Ar;"
+       "VAR"
+       "  x : INTEGER;"
+       "  z : BOOLEAN;"
        ""
-       "PROCEDURE Ax(VAR x : POINTER TO Ar);"
-       "BEGIN"
-       "  x[0, 0] := 777;"
-       "END Ax;"
+       "PROCEDURE Tier(a, b :INTEGER);"
+       "END Tier;"
        ""
        "BEGIN;"
-       "  NEW(a, 2, 2);"
-       "  a[0, 0] := 666;"
-       "  Out.Open;"
-       "  Out.Int(a[0, 0], 0);"
-       "  Out.Ln;"
-       ""
-       "  Ax(a);"
-//     "  Out.Int(a[0, 0], 0);"
-//     "  Out.Ln;"
+       " x := x + 1;"
+       " z := TRUE;"
        "END Test."
 ;
 
 static char source_out[] =
        "MODULE Out;"
-       "(* Interface to outer program ;) *)"
-       "VAR"
-       "  Open-     : PROCEDURE;"
+//     "(* Interface to outer program ;) *)"
+//     "VAR"
+//     "  Open-     : PROCEDURE;"
 //     "  Char-     : PROCEDURE(ch : CHAR);"
 //     "  String-   : PROCEDURE(str : ARRAY OF CHAR)"
 //     "  Int-      : PROCEDURE(i, n : LONGINT);"
-       "  Int-      : PROCEDURE(i, n : INTEGER);"
-       "  Real-     : PROCEDURE(x : REAL; n : INTEGER);"
+//     "  Int-      : PROCEDURE(i, n : INTEGER);"
+//     "  Real-     : PROCEDURE(x : REAL; n : INTEGER);"
 //     "  LongReal- : PROCEDURE(x : LONGREAL; n : INTEGER);"
-       "  Ln-       : PROCEDURE;"
+//     "  Ln-       : PROCEDURE;"
        "END Out."
 ;
 
@@ -131,11 +122,11 @@ main(int argc, char ** argv)
 
        oberon_generate_code(ctx);
 
-       init_system_modules();
+//     init_system_modules();
 
-       oberon_generator_dump(ctx, "dump.txt");
+//     oberon_generator_dump(ctx, "dump.txt");
 
-       start_module();
+//     start_module();
 
        oberon_destroy_context(ctx);
        return 0;
diff --git a/tst.java b/tst.java
new file mode 100644 (file)
index 0000000..2dae5b2
--- /dev/null
+++ b/tst.java
@@ -0,0 +1,4 @@
+public abstract class tst
+{
+       public abstract void invoke();
+}