summary | shortlog | log | commit | commitdiff | tree
raw | patch | inline | side by side (parent: 3edc4e9)
raw | patch | inline | side by side (parent: 3edc4e9)
author | DeaDDooMER <deaddoomer@deadsoftware.ru> | |
Sun, 6 Aug 2017 16:23:41 +0000 (19:23 +0300) | ||
committer | DeaDDooMER <deaddoomer@deadsoftware.ru> | |
Sun, 6 Aug 2017 16:23:41 +0000 (19:23 +0300) |
src/backends/jvm/generator-jvm-abi.c | [new file with mode: 0644] | patch | blob |
src/backends/jvm/generator-jvm-abi.h | [new file with mode: 0644] | patch | blob |
src/backends/jvm/generator-jvm-asm.c | [new file with mode: 0644] | patch | blob |
src/backends/jvm/generator-jvm-asm.h | [new file with mode: 0644] | patch | blob |
src/backends/jvm/generator-jvm-basic.c | patch | blob | history | |
src/backends/jvm/generator-jvm.c | patch | blob | history | |
src/backends/jvm/generator-jvm.h | patch | blob | history | |
src/oberon.c | patch | blob | history | |
src/test.c | patch | blob | history |
diff --git a/src/backends/jvm/generator-jvm-abi.c b/src/backends/jvm/generator-jvm-abi.c
--- /dev/null
@@ -0,0 +1,196 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <stdint.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"
+#include "generator-jvm-abi.h"
+#include "generator-jvm-asm.h"
+#include "generator-jvm-basic.h"
+
+/*
+ * --- Каждый модуль является объектом.
+ * Импортируемые модули представляются полями.
+ * Каждая глобальная переменная представляется не статическим полем.
+ * Каждая процедура представляется не статическим метеодом.
+ * Процедура инициализации модуля имеет название BEGIN.
+ * Процедура финализации модуля имеет название END.
+ * Это позволит сделать динамическую загрузку и выгрузку.
+ * +++ всем переменным и полям в дескриптор добавляется "["
+ * Это позволит делать ссылки на переменные в VAR-параметрах.
+ * --- Каждая процедура снабжается параметром-фреймом.
+ * Это позволит реализовать локальные процедуры и средства рефлекции над стеком.
+ */
+
+void
+jvm_generate_ldst_prepare(gen_proc_t * p, gen_var_t * v)
+{
+ char * full_name = v -> full_name;
+ char * desc = v -> type -> desc;
+
+ switch(v -> storage)
+ {
+ case JVM_STORAGE_REGISTER:
+ break;
+ case JVM_STORAGE_STATIC:
+ jvm_generate(p, 0, 1, "getstatic %s [%s", full_name, desc);
+ jvm_generate(p, 0, 1, "iconst_0");
+ break;
+ case JVM_STORAGE_FIELD:
+ jvm_generate(p, 1, 1, "getfield %s [%s", full_name, desc);
+ jvm_generate(p, 0, 1, "iconst_0");
+ break;
+ case JVM_STORAGE_LOCAL:
+ jvm_generate(p, 0, 1, "aload %i", v -> reg);
+ jvm_generate(p, 0, 1, "iconst_0");
+ break;
+ case JVM_STORAGE_VARPTR:
+ jvm_generate(p, 0, 1, "aload %i", v -> reg);
+ jvm_generate(p, 0, 1, "iload %i", v -> reg + 1);
+ break;
+ default:
+ gen_error("jvm_abi_obn_generate_ldst_prepare: wat %i", v -> storage);
+ }
+}
+
+void
+jvm_generate_load(gen_proc_t * p, gen_var_t * src)
+{
+ char prefix = src -> type -> prefix;
+ int cell_size = src -> type -> cell_size;
+
+ switch(src -> storage)
+ {
+ case JVM_STORAGE_REGISTER:
+ jvm_generate(p, 0, cell_size, "%cload %i", prefix, src -> reg);
+ break;
+ case JVM_STORAGE_STATIC:
+ case JVM_STORAGE_FIELD:
+ case JVM_STORAGE_LOCAL:
+ case JVM_STORAGE_VARPTR:
+ jvm_generate_ldst_prepare(p, src);
+ jvm_generate(p, 1 + 1, cell_size, "%caload", prefix);
+ break;
+ default:
+ gen_error("jvm_generate_load: unknow storage type %i", src -> storage);
+ break;
+ }
+}
+
+void
+jvm_generate_store(gen_proc_t * p, gen_var_t * dst)
+{
+ char prefix = dst -> type -> prefix;
+ int cell_size = dst -> type -> cell_size;
+
+ switch(dst -> storage)
+ {
+ case JVM_STORAGE_REGISTER:
+ jvm_generate(p, cell_size, 0, "%cstore %i", prefix, dst -> reg);
+ break;
+ case JVM_STORAGE_STATIC:
+ case JVM_STORAGE_FIELD:
+ case JVM_STORAGE_LOCAL:
+ case JVM_STORAGE_VARPTR:
+ jvm_generate(p, 1 + 1 + cell_size, 0, "%castore", prefix);
+ break;
+ default:
+ gen_error("jvm_generate_store: unknow storage type %i", dst -> storage);
+ break;
+ }
+}
+
+void
+jvm_generate_and_init_global_var(struct gen_class * class, gen_var_t * v, char * name, gen_type_t * t)
+{
+ assert(class -> p == NULL);
+ fprintf(class -> fp, ".field public static %s [%s\n\n", name, t -> desc);
+
+ v -> storage = JVM_STORAGE_STATIC;
+ v -> full_name = new_string("%s/%s", class -> full_name, name);
+ v -> type = t;
+}
+
+void
+jvm_generate_and_init_field(struct gen_class * class, gen_var_t * v, char * name, gen_type_t * t)
+{
+ assert(class -> p == NULL);
+ fprintf(class -> fp, ".field public %s [%s\n\n", name, t -> desc);
+
+ v -> storage = JVM_STORAGE_FIELD;
+ v -> full_name = new_string("%s/%s", class -> full_name, name);
+ v -> type = t;
+}
+
+void
+jvm_generate_and_init_local_var(gen_proc_t * p, gen_var_t * v, gen_type_t * t)
+{
+ v -> storage = JVM_STORAGE_REGISTER;
+ v -> reg = jvm_alloc_register_untyped(p -> rf, t -> wide);
+ v -> type = t;
+}
+
+void
+jvm_generate_and_init_named_local_var(gen_proc_t * p, gen_var_t * v, char * name, gen_type_t * t)
+{
+ jvm_generate_and_init_local_var(p, v, t);
+ jvm_generate(p, 0, 0, ".var %i is %s %s from start to end", v -> reg, name, t -> desc);
+}
+
+void
+jvm_generate_and_init_var_param(gen_proc_t * p, gen_var_t * v, char * name, gen_type_t * t)
+{
+ v -> storage = JVM_STORAGE_VARPTR;
+ v -> reg = jvm_alloc_register_untyped(p -> rf, true);
+ v -> type = t;
+ jvm_generate(p, 0, 0, ".var %i is %s [%s from start to end", v -> reg, name, t -> desc);
+ jvm_generate(p, 0, 0, ".var %i is __%s_offset I from start to end", v -> reg + 1, name);
+}
+
+void
+jvm_generate_variable_initialization(gen_proc_t * p, gen_var_t * v)
+{
+ if(v -> storage == JVM_STORAGE_STATIC)
+ {
+ jvm_generate(p, 0, 1, "iconst_1");
+ jvm_generate(p, 1, 1, "multianewarray [%s 1", v -> type -> desc);
+ jvm_generate(p, 1, 0, "putstatic %s [%s", v -> full_name, v -> type -> desc);
+ }
+ else if(v -> storage == JVM_STORAGE_FIELD)
+ {
+ jvm_generate(p, 0, 1, "iconst_1");
+ jvm_generate(p, 1, 1, "multianewarray [%s 1", v -> type -> desc);
+ jvm_generate(p, 1, 0, "putfield %s [%s", v -> full_name, v -> type -> desc);
+ }
+}
+
+void
+jvm_generate_param_initialization(gen_proc_t * p, gen_var_t * v)
+{
+ assert(v -> storage == JVM_STORAGE_REGISTER);
+
+ int old_reg = v -> reg;
+ bool wide = v -> type -> wide;
+ int cell_size = v -> type -> cell_size;
+ char prefix = v -> type -> prefix;
+ char * desc = v -> type -> desc;
+
+ v -> storage = JVM_STORAGE_LOCAL;
+ v -> reg = jvm_alloc_register_untyped(p -> rf, wide);
+
+ jvm_generate(p, 0, 1, "iconst_1");
+ jvm_generate(p, 1, 1, "multianewarray [%s 1", desc);
+ jvm_generate(p, 1, 2, "dup");
+ jvm_generate(p, 1, 0, "astore %i", v -> reg);
+
+ jvm_generate(p, 0, 1, "iconst_0");
+ jvm_generate(p, 0, cell_size, "%cload %i", prefix, old_reg);
+ jvm_generate(p, 1 + 1 + cell_size, 0, "%castore", prefix);
+}
diff --git a/src/backends/jvm/generator-jvm-abi.h b/src/backends/jvm/generator-jvm-abi.h
--- /dev/null
@@ -0,0 +1,29 @@
+void
+jvm_generate_ldst_prepare(gen_proc_t * p, gen_var_t * v);
+
+void
+jvm_generate_load(gen_proc_t * p, gen_var_t * src);
+
+void
+jvm_generate_store(gen_proc_t * p, gen_var_t * dst);
+
+void
+jvm_generate_and_init_global_var(struct gen_class * class, gen_var_t * v, char * name, gen_type_t * t);
+
+void
+jvm_generate_and_init_field(struct gen_class * class, gen_var_t * v, char * name, gen_type_t * t);
+
+void
+jvm_generate_and_init_local_var(gen_proc_t * p, gen_var_t * v, gen_type_t * t);
+
+void
+jvm_generate_and_init_named_local_var(gen_proc_t * p, gen_var_t * v, char * name, gen_type_t * t);
+
+void
+jvm_generate_and_init_var_param(gen_proc_t * p, gen_var_t * v, char * name, gen_type_t * t);
+
+void
+jvm_generate_variable_initialization(gen_proc_t * p, gen_var_t * v);
+
+void
+jvm_generate_param_initialization(gen_proc_t * p, gen_var_t * v);
diff --git a/src/backends/jvm/generator-jvm-asm.c b/src/backends/jvm/generator-jvm-asm.c
--- /dev/null
@@ -0,0 +1,302 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <stdint.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"
+#include "generator-jvm-abi.h"
+#include "generator-jvm-asm.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);
+ fprintf(class -> fp, " start:\n");
+}
+
+void
+jvm_generate_function_end(gen_proc_t * p)
+{
+ struct gen_class * class;
+ class = p -> class;
+
+ assert(class -> p);
+ class -> p = NULL;
+
+ int pointer = p -> stack -> pointer;
+ int max_pointer = p -> stack -> max_pointer;
+ int locals = p -> rf -> num_used;
+ int max_locals = p -> rf -> max_used;
+
+ fprintf(class -> fp, " .limit stack %i \t; current(%i)\n", max_pointer, pointer);
+ fprintf(class -> fp, " .limit locals %i \t; current(%i)\n", max_locals, locals);
+ fprintf(class -> fp, " end:\n");
+ 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;
+}
+
+void
+jvm_destroy_class(struct gen_class * class)
+{
+ assert(class -> p == NULL);
+ fclose(class -> fp);
+}
+
+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;
+ }
+}
+
+void
+jvm_stack_pop(gen_proc_t * p, unsigned size)
+{
+ p -> stack -> pointer -= size;
+
+ if(p -> stack -> pointer < 0)
+ {
+ printf("WARING: stack pointer %i\n", p -> stack -> pointer);
+ }
+}
+
+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);
+ jvm_stack_push(p, push);
+ fprintf(p -> class -> fp, " \t ;>>>> %i -- %i : current_stack(%i)\n", get, push, p -> stack -> pointer);
+
+ va_end(ptr);
+}
+
+void
+jvm_generate_comment(gen_proc_t * p, char * format, ...)
+{
+ va_list ptr;
+ va_start(ptr, format);
+
+ fprintf(p -> class -> fp, " ;;;; ");
+ vfprintf(p -> class -> fp, format, ptr);
+ fprintf(p -> class -> fp, "\n");
+
+ va_end(ptr);
+}
+
+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_w %li", i);
+ }
+}
+
+void
+jvm_generate_push_int_size(gen_proc_t * p, int64_t i, int size)
+{
+ int pushed_cell = 1;
+
+ 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
+ {
+ pushed_cell = 2;
+ jvm_generate(p, 0, 2, "ldc2_w %li", i);
+ }
+
+ assert(size <= 8);
+ if(size > 4 && pushed_cell == 1)
+ {
+ jvm_generate(p, pushed_cell, 2, "i2l");
+ }
+ else if(size <= 4)
+ {
+ if(pushed_cell > 1)
+ {
+ jvm_generate(p, 2, 1, "l2i");
+ }
+
+ if(size == 2)
+ {
+ jvm_generate(p, 1, 1, "i2s");
+ }
+ else if(size == 1)
+ {
+ jvm_generate(p, 1, 1, "i2b");
+ }
+ }
+}
+
+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_w %lf", f);
+ }
+ }
+}
+
+void
+jvm_generate_push_string(gen_proc_t * p, char * str, int char_size)
+{
+ assert(char_size == 1);
+ int len = strlen(str);
+
+ jvm_generate_push_int(p, len + 1);
+ jvm_generate(p, 1, 1, "newarray byte");
+
+ for(int i = 0; i < len; i++)
+ {
+ jvm_generate(p, 1, 2, "dup");
+ jvm_generate_push_int(p, i);
+ jvm_generate_push_int(p, str[i]);
+ jvm_generate(p, 3, 0, "bastore");
+ }
+}
+
+gen_var_t *
+oberon_generator_new_var()
+{
+ gen_var_t * v = GC_MALLOC(sizeof *v);
+ memset(v, 0, sizeof *v);
+ return v;
+}
+
+int
+jvm_new_label_id(gen_proc_t * p)
+{
+ int label_id = p -> label_id;
+ p -> label_id += 1;
+ return label_id;
+}
+
+void
+jvm_generate_label(gen_proc_t * p, int label_id)
+{
+ jvm_generate(p, 0, 0, "L%i:", label_id);
+}
diff --git a/src/backends/jvm/generator-jvm-asm.h b/src/backends/jvm/generator-jvm-asm.h
--- /dev/null
@@ -0,0 +1,53 @@
+struct gen_class *
+jvm_create_class(char * full_name);
+
+void
+jvm_destroy_class(struct gen_class * class);
+
+gen_proc_t *
+jvm_create_proc(struct gen_class * class);
+
+gen_var_t *
+oberon_generator_new_var();
+
+
+
+void
+jvm_generate_function_header(gen_proc_t * p, char * access, char * name, char * signature);
+
+void
+jvm_generate_function_end(gen_proc_t * p);
+
+int
+jvm_new_label_id(gen_proc_t * p);
+
+void
+jvm_generate_label(gen_proc_t * p, int label_id);
+
+
+
+void
+jvm_stack_push(gen_proc_t * p, unsigned size);
+
+void
+jvm_stack_pop(gen_proc_t * p, unsigned size);
+
+
+
+void
+jvm_generate(gen_proc_t * p, unsigned get, unsigned push, char * format, ...);
+
+void
+jvm_generate_comment(gen_proc_t * p, char * format, ...);
+
+void
+jvm_generate_push_int(gen_proc_t * p, int64_t i);
+
+void
+jvm_generate_push_int_size(gen_proc_t * p, int64_t i, int size);
+
+void
+jvm_generate_push_float(gen_proc_t * p, double f, int size);
+
+void
+jvm_generate_push_string(gen_proc_t * p, char * str, int char_size);
index bcd82a25476803cbcd4aca6e8aa0ecf9f4c24934..277940ce17b58fb18f46ee630aa162c2a250c62a 100644 (file)
desc = jvm_get_descriptor(type -> base);
return new_string("[%s", desc);
break;
+ case OBERON_TYPE_STRING:
+ switch(type -> size)
+ {
+ case 1:
+ return new_string("[B");
+ break;
+ case 2:
+ return new_string("[C");
+ break;
+ case 4:
+ return new_string("[I");
+ break;
+ case 8:
+ return new_string("[J");
+ break;
+ default:
+ gen_error("jvm_get_descriptor: unsupported string size %i", type -> size);
+ break;
+ }
+ break;
default:
gen_error("jvm_get_descriptor: unsupported type class %i", type -> class);
break;
case OBERON_TYPE_ARRAY:
case OBERON_TYPE_RECORD:
case OBERON_TYPE_POINTER:
+ case OBERON_TYPE_STRING:
return 'a';
break;
case OBERON_TYPE_REAL:
return (size <= 4) ? ('f') : ('d');
break;
default:
- gen_error("jvm_get_prefix: wat");
+ gen_error("jvm_get_prefix: wat %i", type -> class);
return '!';
break;
}
case OBERON_TYPE_ARRAY:
case OBERON_TYPE_RECORD:
case OBERON_TYPE_POINTER:
+ case OBERON_TYPE_STRING:
return 'a';
break;
case OBERON_TYPE_REAL:
for(int i = 0; i < num; i++)
{
desc = jvm_get_descriptor(arg -> type);
- signature = new_string("%s%s", signature, desc);
+ if(arg -> class == OBERON_CLASS_VAR_PARAM)
+ {
+ signature = new_string("%s[%sI", signature, desc);
+ }
+ else
+ {
+ signature = new_string("%s%s", signature, desc);
+ }
arg = arg -> next;
}
index a107efc119eca8a22afc620cbc912e8e284f86fa..da8b06b29f5142a7ea9b25cdd2e6c8ed18a00bb8 100644 (file)
#include "../../../include/oberon.h"
#include "../../oberon-internals.h"
#include "generator-jvm.h"
+#include "generator-jvm-abi.h"
+#include "generator-jvm-asm.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);
- fprintf(class -> fp, " start:\n");
-}
-
-void
-jvm_generate_function_end(gen_proc_t * p)
-{
- struct gen_class * class;
- class = p -> class;
-
- assert(class -> p);
- class -> p = NULL;
-
- int pointer = p -> stack -> pointer;
- int max_pointer = p -> stack -> max_pointer;
- int locals = p -> rf -> num_used;
- int max_locals = p -> rf -> max_used;
-
- fprintf(class -> fp, " .limit stack %i \t; current(%i)\n", max_pointer, pointer);
- fprintf(class -> fp, " .limit locals %i \t; current(%i)\n", max_locals, locals);
- fprintf(class -> fp, " end:\n");
- 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;
-
- if(p -> stack -> pointer < 0)
- {
- printf("WARING: stack pointer %i\n", p -> stack -> pointer);
- }
-}
-
-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);
- jvm_stack_push(p, push);
- fprintf(p -> class -> fp, " \t ;>>>> %i -- %i : current_stack(%i)\n", get, push, p -> stack -> pointer);
-
- va_end(ptr);
-}
-
-static void
-jvm_generate_comment(gen_proc_t * p, char * format, ...)
-{
- va_list ptr;
- va_start(ptr, format);
-
- fprintf(p -> class -> fp, " ;;;; ");
- vfprintf(p -> class -> fp, format, ptr);
- fprintf(p -> class -> fp, "\n");
-
- 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_w %li", i);
- }
-}
-
-static void
-jvm_generate_push_int_size(gen_proc_t * p, int64_t i, int size)
-{
- int pushed_cell = 1;
-
- 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
- {
- pushed_cell = 2;
- jvm_generate(p, 0, 2, "ldc2_w %li", i);
- }
-
- assert(size <= 8);
- if(size > 4 && pushed_cell == 1)
- {
- jvm_generate(p, pushed_cell, 2, "i2l");
- }
- else if(size <= 4)
- {
- if(pushed_cell > 1)
- {
- jvm_generate(p, 2, 1, "l2i");
- }
-
- if(size == 2)
- {
- jvm_generate(p, 1, 1, "i2s");
- }
- else if(size == 1)
- {
- jvm_generate(p, 1, 1, "i2b");
- }
- }
-}
-
-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_w %lf", f);
- }
- }
-}
-
-static void
-jvm_generate_push_string(gen_proc_t * p, char * str, int char_size)
-{
- assert(char_size == 1);
- int len = strlen(str);
-
- jvm_generate_push_int(p, len + 1);
- jvm_generate(p, 1, 1, "newarray byte");
-
- for(int i = 0; i < len; i++)
- {
- jvm_generate(p, 1, 2, "dup");
- jvm_generate_push_int(p, i);
- jvm_generate_push_int(p, str[i]);
- jvm_generate(p, 3, 0, "bastore");
- }
-}
-
-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);
-}
-
-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_load(gen_proc_t * p, oberon_type_t * src_type, gen_var_t * src)
-{
- char prefix;
- int cell_size;
-
- cell_size = jvm_cell_size_for_type(src_type);
-
- switch(src -> storage)
- {
- case JVM_STORAGE_REGISTER:
- prefix = jvm_get_prefix(src_type);
- jvm_generate(p, 0, cell_size, "%cload %i", prefix, src -> reg);
- break;
- case JVM_STORAGE_STATIC:
- jvm_generate(p, 0, cell_size, "getstatic %s %s", src -> full_name, src -> desc);
- break;
- case JVM_STORAGE_FIELD:
- jvm_generate(p, 1, cell_size, "getfield %s %s", src -> full_name, src -> desc);
- break;
- default:
- gen_error("jvm_generate_load: unknow storage type %i", src -> storage);
- 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;
- }
-}
+push_item(gen_proc_t * p, oberon_item_t * item);
static void
jvm_generate_new(gen_proc_t * p, oberon_type_t * type, int num);
}
struct {
- gen_var_t * index;
- gen_var_t * length;
+ int reg_index;
+ int reg_length;
int start;
int end;
} loop[dim];
- gen_var_t * dst = oberon_generator_new_var();
- jvm_generate_and_init_local_var(dst, p, false);
- jvm_generate_store(p, arr, dst);
+ int reg_dst;
+ reg_dst = jvm_alloc_register_untyped(p -> rf, false);
+ jvm_generate(p, 1, 0, "astore %i", reg_dst);
/*
* Входящие параметры заграблены.
for(int i = 0; i < dim; i++)
{
- loop[i].index = oberon_generator_new_var();
- loop[i].length = oberon_generator_new_var();
+ loop[i].reg_index = jvm_alloc_register_untyped(p -> rf, false);
+ loop[i].reg_length = jvm_alloc_register_untyped(p -> rf, false);
loop[i].start = jvm_new_label_id(p);
loop[i].end = jvm_new_label_id(p);
- jvm_generate_and_init_local_var(loop[i].index, p, false);
- jvm_generate_and_init_local_var(loop[i].length, p, false);
-
- /* TODO преределать через jvm_generate_load{{store}} */
jvm_generate(p, 0, 1, "iconst_0");
- jvm_generate(p, 1, 0, "istore %i", loop[i].index -> reg);
+ jvm_generate(p, 1, 0, "istore %i", loop[i].reg_index);
- jvm_generate_load(p, arr, dst);
+ jvm_generate(p, 0, 1, "aload %i", reg_dst);
jvm_generate(p, 1, 1, "arraylength");
- jvm_generate(p, 1, 0, "istore %i", loop[i].length -> reg);
+ jvm_generate(p, 1, 0, "istore %i", loop[i].reg_length);
/* if(i >= len) goto end; */
jvm_generate_label(p, loop[i].start);
- jvm_generate(p, 0, 1, "iload %i", loop[i].index -> reg);
- jvm_generate(p, 0, 1, "iload %i", loop[i].length -> reg);
+ jvm_generate(p, 0, 1, "iload %i", loop[i].reg_index);
+ jvm_generate(p, 0, 1, "iload %i", loop[i].reg_length);
jvm_generate(p, 2, 0, "if_icmpge L%i", loop[i].end);
}
- jvm_generate_load(p, arr, dst);
- jvm_generate(p, 0, 1, "iload %i", loop[0].index -> reg);
+ jvm_generate(p, 0, 1, "aload %i", reg_dst);
+ jvm_generate(p, 0, 1, "iload %i", loop[0].reg_index);
for(int i = 1; i < dim; i++)
{
jvm_generate(p, 2, 1, "aaload");
- jvm_generate(p, 0, 1, "iload %i", loop[i].index -> reg);
+ jvm_generate(p, 0, 1, "iload %i", loop[i].reg_index);
}
jvm_generate_new(p, base, 0);
jvm_generate(p, 3, 0, "aastore");
for(int i = dim - 1; i >= 0; i--)
{
- jvm_generate(p, 0, 0, "iinc %i 1", loop[i].index -> reg);
+ jvm_generate(p, 0, 0, "iinc %i 1", loop[i].reg_index);
jvm_generate(p, 0, 0, "goto L%i", loop[i].start);
jvm_generate_label(p, loop[i].end);
}
}
struct {
- gen_var_t * index;
- gen_var_t * length;
+ int reg_index;
+ int reg_length;
int start;
int end;
} loop[dim];
- gen_var_t * dst = oberon_generator_new_var();
- gen_var_t * src = oberon_generator_new_var();
- jvm_generate_and_init_local_var(dst, p, false);
- jvm_generate_and_init_local_var(src, p, false);
-
- jvm_generate_store(p, arr, src);
- jvm_generate_store(p, arr, dst);
+ int reg_dst = jvm_alloc_register_untyped(p -> rf, false);
+ int reg_src = jvm_alloc_register_untyped(p -> rf, false);
+ jvm_generate(p, 1, 0, "astore %i", reg_src);
+ jvm_generate(p, 1, 0, "astore %i", reg_dst);
/*
* Входящие параметры заграблены.
for(int i = 0; i < dim; i++)
{
- loop[i].index = oberon_generator_new_var();
- loop[i].length = oberon_generator_new_var();
+ loop[i].reg_index = jvm_alloc_register_untyped(p -> rf, false);
+ loop[i].reg_length = jvm_alloc_register_untyped(p -> rf, false);
loop[i].start = jvm_new_label_id(p);
loop[i].end = jvm_new_label_id(p);
- jvm_generate_and_init_local_var(loop[i].index, p, false);
- jvm_generate_and_init_local_var(loop[i].length, p, false);
-
- /* TODO преределать через jvm_generate_load{{store}} */
jvm_generate(p, 0, 1, "iconst_0");
- jvm_generate(p, 1, 0, "istore %i", loop[i].index -> reg);
+ jvm_generate(p, 1, 0, "istore %i", loop[i].reg_index);
- jvm_generate_load(p, arr, src);
+ jvm_generate(p, 0, 1, "aload %i", reg_src);
jvm_generate(p, 1, 1, "arraylength");
- jvm_generate(p, 1, 0, "istore %i", loop[i].length -> reg);
+ jvm_generate(p, 1, 0, "istore %i", loop[i].reg_length);
/* if(i >= len) goto end; */
jvm_generate_label(p, loop[i].start);
- jvm_generate(p, 0, 1, "iload %i", loop[i].index -> reg);
- jvm_generate(p, 0, 1, "iload %i", loop[i].length -> reg);
+ jvm_generate(p, 0, 1, "iload %i", loop[i].reg_index);
+ jvm_generate(p, 0, 1, "iload %i", loop[i].reg_length);
jvm_generate(p, 2, 0, "if_icmpge L%i", loop[i].end);
}
{
/* Получаем записи по индексам ( -- dst src ) */
- jvm_generate_load(p, arr, dst);
+ jvm_generate(p, 0, 1, "aload %i", reg_dst);
for(int i = 0; i < dim; i++)
{
- jvm_generate(p, 0, 1, "iload %i", loop[i].index -> reg);
+ jvm_generate(p, 0, 1, "iload %i", loop[i].reg_index);
jvm_generate(p, 2, 1, "aaload");
}
- jvm_generate_load(p, arr, src);
+ jvm_generate(p, 0, 1, "aload %i", reg_src);
for(int i = 0; i < dim; i++)
{
- jvm_generate(p, 0, 1, "iload %i", loop[i].index -> reg);
+ jvm_generate(p, 0, 1, "iload %i", loop[i].reg_index);
jvm_generate(p, 2, 1, "aaload");
}
/* Получаем массивы и индексы ( -- dst i src i ) */
- jvm_generate_load(p, arr, dst);
- jvm_generate(p, 0, 1, "iload %i", loop[0].index -> reg);
+ jvm_generate(p, 0, 1, "aload %i", reg_dst);
+ jvm_generate(p, 0, 1, "iload %i", loop[0].reg_index);
for(int i = 1; i < dim; i++)
{
jvm_generate(p, 2, 1, "aaload");
- jvm_generate(p, 0, 1, "iload %i", loop[i].index -> reg);
+ jvm_generate(p, 0, 1, "iload %i", loop[i].reg_index);
}
- jvm_generate_load(p, arr, src);
- jvm_generate(p, 0, 1, "iload %i", loop[0].index -> reg);
+ jvm_generate(p, 0, 1, "aload %i", reg_src);
+ jvm_generate(p, 0, 1, "iload %i", loop[0].reg_index);
for(int i = 1; i < dim; i++)
{
jvm_generate(p, 2, 1, "aaload");
- jvm_generate(p, 0, 1, "iload %i", loop[i].index -> reg);
+ jvm_generate(p, 0, 1, "iload %i", loop[i].reg_index);
}
/* Копируем значения ( dst i src i -- ) */
for(int i = dim - 1; i >= 0; i--)
{
- jvm_generate(p, 0, 0, "iinc %i 1", loop[i].index -> reg);
+ jvm_generate(p, 0, 0, "iinc %i 1", loop[i].reg_index);
jvm_generate(p, 0, 0, "goto L%i", loop[i].start);
jvm_generate_label(p, loop[i].end);
}
jvm_generate(p, 0, 1, "getstatic %s/pointer %s", full_name, desc);
}
-// ==========================================
-// ==========================================
-// ==========================================
-
-static void
-push_item(gen_proc_t * p, oberon_item_t * item);
-
void
oberon_generator_init_context(oberon_context_t * ctx)
{
signature = jvm_get_procedure_signature(proc -> type);
- gen_proc_t * p;
- gen_var_t * this_v;
-
- p = jvm_create_proc(class);
+ gen_proc_t * p = jvm_create_proc(class);
jvm_generate_function_header(p, "public", "invoke", signature);
+ jvm_alloc_register_untyped(p -> rf, false);
- this_v = oberon_generator_new_var();
- jvm_generate_and_init_local_var(this_v, p, false);
-
- gen_var_t * v;
int use_size = 0;
int num = proc -> type -> num_decl;
- oberon_object_t * arg = proc -> type -> decl;
+ oberon_object_t * param = proc -> type -> decl;
for(int i = 0; i < num; i++)
{
- v = oberon_generator_new_var();
- bool wide = jvm_is_wide_type(arg -> type);
- char * desc = jvm_get_descriptor(arg -> type);
- jvm_generate_and_init_named_local_var(v, p, wide, arg -> name, desc);
-
- jvm_generate_load(p, arg -> type, v);
-
- use_size += (wide) ? (2) : (1);
-
- arg = arg -> next;
+ gen_var_t * v = oberon_generator_new_var();
+ gen_type_t * t = param -> type -> gen_type;
+ use_size += t -> cell_size;
+ if(param -> class == OBERON_CLASS_VAR_PARAM)
+ {
+ jvm_generate_and_init_var_param(p, v, param -> name, t);
+ jvm_generate_ldst_prepare(p, v);
+ }
+ else
+ {
+ jvm_generate_and_init_named_local_var(p, v, param -> name, t);
+ jvm_generate_load(p, v);
+ }
+ param = param -> next;
}
+
char * full_name = jvm_get_field_full_name(proc);
int cell_size = jvm_cell_size_for_type(proc -> type -> base);
-
jvm_generate(p, use_size, cell_size, "invokestatic %s%s", full_name, signature);
if(proc -> type -> base -> class == OBERON_TYPE_VOID)
memset(t, 0, sizeof *t);
type -> gen_type = t;
+ if(type -> class != OBERON_TYPE_VOID)
+ {
+ t -> wide = jvm_is_wide_type(type);
+ t -> prefix = jvm_get_prefix(type);
+ t -> postfix = jvm_get_postfix(type);
+ }
+ t -> cell_size = jvm_cell_size_for_type(type);
+ t -> desc = jvm_get_descriptor(type);
+
switch(type -> class)
{
case OBERON_TYPE_VOID:
case OBERON_TYPE_INTEGER:
case OBERON_TYPE_BOOLEAN:
case OBERON_TYPE_ARRAY:
+ case OBERON_TYPE_POINTER:
case OBERON_TYPE_REAL:
case OBERON_TYPE_CHAR:
case OBERON_TYPE_STRING:
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;
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);
+ gen_var_t * v = field -> gen_var;
+ gen_type_t * t = field -> type -> gen_type;
+ jvm_generate_and_init_field(class, v, name, t);
field = field -> next;
}
field = rec -> decl;
for(int i = 0; i < num; i++)
{
+ jvm_generate(p, 0, 1, "aload_0");
+ jvm_generate_variable_initialization(p, field -> gen_var);
+
if(field -> type -> class == OBERON_TYPE_RECORD
|| field -> type -> class == OBERON_TYPE_ARRAY)
{
jvm_generate(p, 0, 1, "aload_0");
+ jvm_generate_ldst_prepare(p, field -> gen_var);
jvm_generate_new(p, field -> type, 0);
- jvm_generate_store(p, field -> type, field -> gen_var);
+ jvm_generate_store(p, field -> gen_var);
}
field = field -> next;
}
p = jvm_create_proc(class);
gen_var_t * copy_dst = oberon_generator_new_var();
gen_var_t * copy_src = oberon_generator_new_var();
- char * desc = jvm_get_descriptor(rec);
- char * signature = new_string("(%s%s)V", desc, desc);
+ char * signature = new_string("(%s%s)V", rec -> gen_type -> desc, rec -> gen_type -> desc);
jvm_generate_function_header(p, "public static", "$COPY$", signature);
- jvm_generate_and_init_named_local_var(copy_dst, p, false, "dst", desc);
- jvm_generate_and_init_named_local_var(copy_src, p, false, "src", desc);
+ jvm_generate_and_init_named_local_var(p, copy_dst, "dst", rec -> gen_type);
+ jvm_generate_and_init_named_local_var(p, copy_src, "src", rec -> gen_type);
num = rec -> num_decl;
field = rec -> decl;
for(int i = 0; i < num; i++)
{
if(field -> type -> class == OBERON_TYPE_RECORD)
{
- jvm_generate_load(p, rec, copy_dst);
- jvm_generate_load(p, field -> type, field -> gen_var);
- jvm_generate_load(p, rec, copy_src);
- jvm_generate_load(p, field -> type, field -> gen_var);
+ jvm_generate_load(p, copy_dst);
+ jvm_generate_load(p, field -> gen_var);
+ jvm_generate_load(p, copy_src);
+ jvm_generate_load(p, field -> gen_var);
jvm_generate_copy_record(p, field -> type);
}
else if(field -> type -> class == OBERON_TYPE_ARRAY)
{
- jvm_generate_load(p, rec, copy_dst);
- jvm_generate_load(p, field -> type, field -> gen_var);
- jvm_generate_load(p, rec, copy_src);
- jvm_generate_load(p, field -> type, field -> gen_var);
+ jvm_generate_load(p, copy_dst);
+ jvm_generate_load(p, field -> gen_var);
+ jvm_generate_load(p, copy_src);
+ jvm_generate_load(p, field -> gen_var);
jvm_generate_copy_array(p, field -> type);
}
else
{
- jvm_generate_load(p, rec, copy_dst);
- jvm_generate_load(p, rec, copy_src);
- jvm_generate_load(p, field -> type, field -> gen_var);
- jvm_generate_store(p, field -> type, field -> gen_var);
+ jvm_generate_load(p, copy_dst);
+ jvm_generate_ldst_prepare(p, field -> gen_var);
+ jvm_generate_load(p, copy_src);
+ jvm_generate_load(p, field -> gen_var);
+ jvm_generate_store(p, field -> gen_var);
}
field = field -> next;
}
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() */
case OBERON_CLASS_VAR:
/* Локальные заполняются при генерации функции */
/* смотри jvm_init_local_object() */
- if(var -> local == 0)
+ if(var -> local == false)
{
- desc = jvm_get_descriptor(var -> type);
- jvm_generate_and_init_global_var(v, class, "public", var -> name, desc);
+ jvm_generate_and_init_global_var(class, v, var -> name, var -> type -> gen_type);
}
break;
default:
gen_proc_t * p;
p = m -> class -> p;
- bool wide;
- wide = jvm_is_wide_type(var -> type);
-
- jvm_generate_and_init_local_var(v, p, wide);
+ jvm_generate_and_init_local_var(p, v, var -> type -> gen_type);
}
void
{
gen_error("generator: local procedures not implemented");
}
-
- oberon_generate_procedure_pointer_class(proc);
+ else
+ {
+ oberon_generate_procedure_pointer_class(proc);
+ }
}
void
{
if(x -> class == OBERON_CLASS_VAR)
{
+ jvm_generate_variable_initialization(p, x -> gen_var);
if(x -> type -> class == OBERON_TYPE_ARRAY
|| x -> type -> class == OBERON_TYPE_RECORD)
{
+ jvm_generate_ldst_prepare(p, x -> gen_var);
jvm_generate_new(p, x -> type, 0);
- jvm_generate_store(p, x -> type, x -> gen_var);
+ jvm_generate_store(p, x -> gen_var);
}
}
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;
- }
-}
-
/*
* Генерирует код для получения размера измерения массива
* Аналог Обероновского LEN(v, n); где n = 0 - первое измерение.
static void
jvm_generate_array_duplicate_and_replace(gen_proc_t * p, gen_var_t * v, oberon_type_t * arr)
{
+ jvm_generate_ldst_prepare(p, v);
+
int dim = 0;
oberon_type_t * base = arr;
while(base -> class == OBERON_TYPE_ARRAY)
{
if(base -> size == 0)
{
- jvm_generate_load(p, arr, v);
+ jvm_generate_load(p, v);
jvm_generate_array_len(p, dim);
dim += 1;
}
@@ -1203,19 +785,77 @@ jvm_generate_array_duplicate_and_replace(gen_proc_t * p, gen_var_t * v, oberon_t
jvm_generate_new(p, arr, dim);
jvm_generate(p, 1, 2, "dup");
- jvm_generate_load(p, arr, v);
+ jvm_generate_load(p, v);
jvm_generate_copy_array(p, arr);
- jvm_generate_store(p, arr, v);
+ jvm_generate_store(p, v);
}
static void
jvm_generate_record_duplicate_and_replace(gen_proc_t * p, gen_var_t * v, oberon_type_t * rec)
{
+ jvm_generate_ldst_prepare(p, v);
jvm_generate_new(p, rec, 0);
jvm_generate(p, 1, 2, "dup");
- jvm_generate_load(p, rec, v);
+ jvm_generate_load(p, v);
jvm_generate_copy_record(p, rec);
- jvm_generate_store(p, rec, v);
+ jvm_generate_store(p, v);
+}
+
+static void
+jvm_init_local_object(gen_proc_t * p, oberon_object_t * x)
+{
+ gen_var_t * v;
+ struct gen_class * class;
+
+ v = x -> gen_var;
+ class = p -> class;
+
+ // Убеждаемся что сейчас находимся в функции
+ assert(class -> p);
+ assert(x -> local);
+
+ switch(x -> class)
+ {
+ case OBERON_CLASS_VAR_PARAM:
+ jvm_generate_and_init_var_param(p, v, x -> name, x -> type -> gen_type);
+ break;
+ case OBERON_CLASS_VAR:
+ case OBERON_CLASS_PARAM:
+ jvm_generate_and_init_named_local_var(p, v, x -> name, x -> type -> gen_type);
+ break;
+ default:
+ gen_error("jvm_init_local_object: wat");
+ break;
+ }
+}
+
+static void
+jvm_generate_local_initialization(gen_proc_t * p, oberon_object_t * x)
+{
+ gen_var_t * v;
+ struct gen_class * class;
+
+ v = x -> gen_var;
+ class = p -> class;
+
+ // Убеждаемся что сейчас находимся в функции
+ assert(class -> p);
+ assert(x -> local);
+
+ switch(x -> class)
+ {
+ case OBERON_CLASS_VAR_PARAM:
+ break;
+ case OBERON_CLASS_VAR:
+ jvm_generate_variable_initialization(p, v);
+ break;
+ case OBERON_CLASS_PARAM:
+ jvm_generate_param_initialization(p, v);
+ break;
+ default:
+ gen_error("jvm_generate_local_initialization: wat");
+ break;
+ }
}
void
jvm_generate_function_header(p, "public static", proc -> name, signature);
/* Выделение регистров под параметры и переменные */
- oberon_object_t * var = proc -> type -> decl;
+ oberon_object_t * var = proc -> scope -> list -> next;
while(var)
{
jvm_init_local_object(p, var);
var = var -> next;
}
+ /* Инициализация */
+ var = proc -> scope -> list -> next;
+ while(var)
+ {
+ jvm_generate_local_initialization(p, var);
+ var = var -> next;
+ }
+
/* Копирование статических/открытых массивов и записей */
var = proc -> type -> decl;
while(var)
@@ -1332,6 +980,30 @@ oberon_generate_branch(oberon_context_t * ctx, oberon_expr_t * cond, bool gotoif
}
}
+static void
+push_varptr(gen_proc_t * p, oberon_expr_t * expr)
+{
+ assert(expr -> is_item);
+
+ switch(expr -> item.mode)
+ {
+ case MODE_VAR:
+ jvm_generate_ldst_prepare(p, expr -> item.var -> gen_var);
+ break;
+ case MODE_INDEX:
+ push_item(p, (oberon_item_t *) expr -> item.parent);
+ push_expr(p, expr -> item.args);
+ break;
+ case MODE_FIELD:
+ push_item(p, (oberon_item_t *) expr -> item.parent);
+ jvm_generate_ldst_prepare(p, expr -> item.var -> gen_var);
+ break;
+ default:
+ gen_error("push_varptr: wat %i", expr -> item.mode);
+ break;
+ }
+}
+
static void
jvm_generate_call_proc(gen_proc_t * p, oberon_item_t * desig)
{
int num = desig -> num_args;
oberon_expr_t * arg = desig -> args;
+ oberon_object_t * param = procsig -> decl;
for(int i = 0; i < num; i++)
{
- args_cells += jvm_cell_size_for_type(arg -> result);
- push_expr(p, arg);
+ if(param -> class == OBERON_CLASS_VAR_PARAM)
+ {
+ args_cells += 2;
+ push_varptr(p, arg);
+ }
+ else
+ {
+ args_cells += jvm_cell_size_for_type(arg -> result);
+ push_expr(p, arg);
+ }
arg = arg -> next;
+ param = param -> next;
}
if(direct_call)
}
else
{
- jvm_generate_load(p, item -> result, item -> var -> gen_var);
+ jvm_generate_load(p, item -> var -> gen_var);
}
break;
case MODE_INTEGER:
case MODE_FIELD:
assert(item -> parent -> is_item);
push_item(p, (oberon_item_t *) item -> parent);
- jvm_generate_load(p, item -> result, item -> var -> gen_var);
+ jvm_generate_load(p, item -> var -> gen_var);
break;
case MODE_DEREF:
/* Все объекты в jvm представляются как указатели */
{
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, 1, 0, "ifne L%i", label_false);
jvm_generate(p, 0, 1, "iconst_1");
- jvm_generate(p, 0, 0, "goto %s", label_name_done);
+ jvm_generate(p, 0, 0, "goto L%i", label_done);
jvm_generate_label(p, label_false);
jvm_generate(p, 0, 1, "iconst_0");
jvm_generate_label(p, label_done);
@@ -1684,15 +1364,13 @@ 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, "ifeq %s", label_name_calc_b);
+ jvm_generate(p, 1, 0, "ifeq L%i", label_calc_b);
jvm_generate(p, 0, 1, "iconst_1");
- jvm_generate(p, 0, 0, "goto %s", label_name_done);
+ jvm_generate(p, 0, 0, "goto L%i", label_done);
jvm_generate_label(p, label_calc_b);
push_expr(p, b);
jvm_generate_label(p, label_done);
@@ -1703,15 +1381,13 @@ 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, "ifeq %s", label_name_false);
+ jvm_generate(p, 1, 0, "ifeq L%i", label_false);
push_expr(p, b);
- jvm_generate(p, 0, 0, "goto %s", label_name_done);
+ jvm_generate(p, 0, 0, "goto L%i", label_done);
jvm_generate_label(p, label_false);
jvm_generate(p, 0, 1, "iconst_0");
jvm_generate_label(p, label_done);
char prefix;
int cell_size;
- oberon_type_t * t;
+ oberon_type_t * type;
gen_var_t * ra;
gen_var_t * rb;
int label_else;
int label_end;
- bool wide;
- t = a -> result;
- cell_size = jvm_cell_size_for_type(t);
- prefix = jvm_get_prefix(t);
+ type = a -> result;
+ cell_size = jvm_cell_size_for_type(type);
+ prefix = jvm_get_prefix(type);
if(b == NULL)
{
- jvm_generate_push_int_size(p, 1, t -> size);
+ jvm_generate_push_int_size(p, 1, type -> size);
push_expr(p, a);
jvm_generate(p, 2 * cell_size, cell_size, "%cshl", prefix);
}
else
{
- wide = jvm_is_wide_type(t);
ra = oberon_generator_new_var();
rb = oberon_generator_new_var();
- jvm_generate_and_init_local_var(ra, p, wide);
- jvm_generate_and_init_local_var(rb, p, wide);
+ jvm_generate_and_init_local_var(p, ra, type -> gen_type);
+ jvm_generate_and_init_local_var(p, rb, type -> gen_type);
label_else = jvm_new_label_id(p);
label_end = jvm_new_label_id(p);
push_expr(p, a);
- jvm_generate_store(p, t, ra);
+ jvm_generate_store(p, ra);
push_expr(p, b);
- jvm_generate_store(p, t, rb);
+ jvm_generate_store(p, rb);
- jvm_generate_load(p, t, ra);
- jvm_generate_load(p, t, rb);
+ jvm_generate_load(p, ra);
+ jvm_generate_load(p, rb);
jvm_generate(p, 2 * cell_size, 0, "if_%ccmpgt L%i", prefix, label_else);
- jvm_generate_push_int_size(p, 2, t -> size);
- jvm_generate_load(p, t, rb);
+ jvm_generate_push_int_size(p, 2, type -> size);
+ jvm_generate_load(p, rb);
jvm_generate(p, 2 * cell_size, cell_size, "%cshl", prefix);
- jvm_generate_push_int_size(p, 2, t -> size);
- jvm_generate_load(p, t, ra);
+ jvm_generate_push_int_size(p, 2, type -> size);
+ jvm_generate_load(p, ra);
jvm_generate(p, 2 * cell_size, cell_size, "%cshl", prefix);
jvm_generate(p, 2 * cell_size, cell_size, "%csub", prefix);
jvm_generate(p, 0, 0, "goto L%i", label_end);
jvm_generate_label(p, label_else);
- jvm_generate_push_int_size(p, 0, t -> size);
+ jvm_generate_push_int_size(p, 0, type -> size);
jvm_generate_label(p, label_end);
}
else switch(item -> mode)
{
case MODE_VAR:
+ jvm_generate_ldst_prepare(p, item -> var -> gen_var);
push_expr(p, src);
- jvm_generate_store(p, src -> result, item -> var -> gen_var);
+ jvm_generate_store(p, item -> var -> gen_var);
break;
case MODE_INDEX:
;
case MODE_FIELD:
assert(item -> parent -> is_item);
push_item(p, (oberon_item_t *) item -> parent);
+ jvm_generate_ldst_prepare(p, item -> var -> gen_var);
push_expr(p, src);
- jvm_generate_store(p, src -> result, item -> var -> gen_var);
+ jvm_generate_store(p, item -> var -> gen_var);
break;
default:
gen_error("store_expr: unk mode %i", item -> mode);
index 3095a49070d204df2acb0fb2fa7a89ddfc9abc2a..242aa70b10f8f2b17b21926b06de0e9192b7021c 100644 (file)
JVM_STORAGE_UNKNOWN,
JVM_STORAGE_REGISTER,
JVM_STORAGE_STATIC,
- JVM_STORAGE_FIELD
+ JVM_STORAGE_FIELD,
+ JVM_STORAGE_LOCAL,
+ JVM_STORAGE_VARPTR
};
{
int rec_id;
struct gen_class * class;
+
+ bool wide;
+ char prefix;
+ char postfix;
+ char * desc;
+ int cell_size;
};
struct gen_var_t
{
enum gen_storage storage;
+ gen_type_t * type;
int reg;
char * full_name;
- char * desc;
};
struct gen_context_t
diff --git a/src/oberon.c b/src/oberon.c
index e4b9157d151cafa6075c86bbc1a07ebf2e845bef..58eb67c3eb72562294074f972fde2e15f68b5fec 100644 (file)
--- a/src/oberon.c
+++ b/src/oberon.c
{
if(param -> class == OBERON_CLASS_VAR_PARAM)
{
+ if(arg -> result != param -> type)
+ {
+ oberon_error(ctx, "incompatible type");
+ }
if(arg -> read_only)
{
oberon_error(ctx, "assign to read-only var");
}
+ casted[i] = arg;
+ }
+ else
+ {
+ casted[i] = oberon_autocast_to(ctx, arg, param -> type);
}
- casted[i] = oberon_autocast_to(ctx, arg, param -> type);
arg = arg -> next;
param = param -> next;
}
diff --git a/src/test.c b/src/test.c
index dab2914ca12507682c8a29122dd5498aebb221b1..cd28a2109e803224afb6a10ca56baaf18184be64 100644 (file)
--- a/src/test.c
+++ b/src/test.c
"(* Main module *)"
"MODULE Test;"
"IMPORT Out;"
+ ""
"TYPE"
- " R1 = POINTER TO R1Desc;"
- " R1Desc = RECORD a : INTEGER; END;"
- " R2 = POINTER TO R2Desc;"
- " R2Desc = RECORD (R1Desc) b : INTEGER; END;"
- " Y1 = POINTER TO Y1Desc;"
- " Y1Desc = RECORD END;"
+ " R = RECORD iii : INTEGER; END;"
""
"VAR"
- " r1 : R1;"
- " r2 : R2;"
- " y1 : Y1;"
+ " i : INTEGER;"
+ " a : ARRAY 3 OF INTEGER;"
+ " r : R;"
""
+ "PROCEDURE X(VAR x : INTEGER);"
"BEGIN"
- " NEW(r1);"
- " NEW(r2);"
- " NEW(y1);"
- " r1 := r2;"
- " Out.Open;"
- " WITH r1 : R2 DO"
- " r1.b := 666;"
- " Out.String('R2 branch');"
- " | y1 : Y1 DO"
- " Out.String('Y1 branch');"
- " ELSE"
- " Out.String('Something else');"
- " END;"
- " Out.Ln;"
+ " x := x * 666;"
+ "END X;"
+ ""
+ "BEGIN;"
+ " r.iii := 2;"
+ " X(r.iii);"
+ " Out.Int(r.iii, 0); Out.Ln;"
"END Test."
;