summary | shortlog | log | commit | commitdiff | tree
raw | patch | inline | side by side (parent: 5f233e3)
raw | patch | inline | side by side (parent: 5f233e3)
author | DeaDDooMER <deaddoomer@deadsoftware.ru> | |
Sat, 29 Jul 2017 13:44:38 +0000 (16:44 +0300) | ||
committer | DeaDDooMER <deaddoomer@deadsoftware.ru> | |
Sat, 29 Jul 2017 13:44:38 +0000 (16:44 +0300) |
src/backends/jvm/generator-jvm.c | patch | blob | history | |
src/test.c | patch | blob | history |
index 4b5b9474c0a2f006c99e15c5e4251e37763785b1..895a5ae3e524c2ef30063d1de38a316b2e3d23b1 100644 (file)
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;
+ }
+}
+
static void
jvm_generate_new(gen_proc_t * p, oberon_type_t * type, int num);
/*
- * Функция jvm_generate_static_array_initialization генерирует код для
- * статической инициализации массива. На входе массив, на выходе тот же массив.
- * (arrayref -- arrayref)
+ * Генерирует код для инициализации массива со статическим базовым типом
+ * ( aref -- )
*/
static void
-jvm_generate_static_array_initialization(gen_proc_t * p, oberon_type_t * type)
+jvm_generate_array_initialization(gen_proc_t * p, oberon_type_t * arr)
{
- /* for(int i = 0; i < a.length; i++) */
- /* a[i] := new(base); */
- /* init(a[i]) */
-
- /* a := pop(array) */
- gen_var_t * va = oberon_generator_new_var();
- jvm_generate_and_init_local_var(va, p, false);
- int reg_a = va -> reg;
- /* ссылка уже на стеке */
- jvm_generate(p, 1, 0, "astore %i", reg_a);
-
- /* int i = 0; */
- gen_var_t * vi = oberon_generator_new_var();
- jvm_generate_and_init_local_var(vi, p, false);
- int reg_i = vi -> reg;
- jvm_generate(p, 0, 1, "iconst_0");
- jvm_generate(p, 1, 0, "istore %i", reg_i);
-
- /* int l := a.length */
- gen_var_t * vl = oberon_generator_new_var();
- jvm_generate_and_init_local_var(vl, p, false);
- int reg_l = vl -> reg;
- jvm_generate(p, 0, 1, "aload %i", reg_a);
- jvm_generate(p, 1, 1, "arraylength");
- jvm_generate(p, 1, 0, "istore %i", reg_l);
-
- int label_start = jvm_new_label_id(p);
- int label_end = jvm_new_label_id(p);
-
- /* start: */
- /* if (i >= l) goto end; */
- /* body*/
- /* i += 1;*/
- /* goto start;*/
- /* end: */
- /* push a */
-
- jvm_generate_label(p, label_start);
- jvm_generate(p, 0, 1, "iload %i", reg_i);
- jvm_generate(p, 0, 1, "iload %i", reg_l);
- jvm_generate(p, 2, 0, "if_icmpge L%i", label_end);
-
- if(type -> base -> class == OBERON_TYPE_ARRAY)
+ int dim = 0;
+ oberon_type_t * base = arr;
+ while(base -> class == OBERON_TYPE_ARRAY)
{
- /* Инициализируем следующую размерность */
- jvm_generate(p, 0, 1, "aload %i", reg_a);
- jvm_generate(p, 0, 1, "iload %i", reg_i);
- jvm_generate(p, 0, 1, "aaload");
- jvm_generate_static_array_initialization(p, type -> base);
- jvm_generate(p, 1, 0, "pop");
+ dim += 1;
+ base = base -> base;
}
- else if(type -> base -> class == OBERON_TYPE_RECORD)
+
+ if(base -> class != OBERON_TYPE_RECORD)
{
- jvm_generate(p, 0, 1, "aload %i", reg_a);
- jvm_generate(p, 0, 1, "iload %i", reg_i);
- jvm_generate_new(p, type -> base, 0);
- jvm_generate(p, 3, 0, "aastore");
+ jvm_generate(p, 1, 0, "pop");
+ return;
}
- else
+
+ struct {
+ gen_var_t * index;
+ gen_var_t * 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 i = 0;
+ * int len = dst.length
+ * while(i < len)
+ * {
+ * ...
+ * {
+ * dst[i, ...] = new record;
+ * }
+ * ...
+ * i += 1;
+ * }
+ * Где "..." такой же код (начало и конец) для следующей размерности.
+ */
+
+ for(int i = 0; i < dim; i++)
{
- assert(0);
- }
+ loop[i].index = oberon_generator_new_var();
+ loop[i].length = oberon_generator_new_var();
+ 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);
- /* i += 1; */
- /* goto start */
+ jvm_generate_load(p, arr, dst);
+ jvm_generate(p, 1, 1, "arraylength");
+ jvm_generate(p, 1, 0, "istore %i", loop[i].length -> reg);
- jvm_generate(p, 0, 0, "iinc %i %i", reg_i, 1);
- jvm_generate(p, 0, 0, "goto L%i", label_start);
- jvm_generate_label(p, label_end);
+ /* 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, 2, 0, "if_icmpge L%i", loop[i].end);
+ }
- /* push(a) */
- jvm_generate(p, 0, 1, "aload %i", reg_a);
+ jvm_generate_load(p, arr, dst);
+ jvm_generate(p, 0, 1, "iload %i", loop[0].index -> reg);
+ 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_new(p, base, 0);
+ jvm_generate(p, 3, 0, "aastore");
- /* TODO освобождение регистров */
+ 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, "goto L%i", loop[i].start);
+ jvm_generate_label(p, loop[i].end);
+ }
}
static void
gen_error("jvm_generate_new_static: static alocation not allowed");
break;
case OBERON_TYPE_RECORD:
+ assert(num == 0);
cname = jvm_get_class_full_name(type);
jvm_generate(p, 0, 1, "new %s", cname);
jvm_generate(p, 1, 2, "dup");
assert(num == 0);
jvm_generate(p, dim, 1, "multianewarray %s %i", desc, dim);
-
- if(base -> class == OBERON_TYPE_RECORD)
- {
- jvm_generate_static_array_initialization(p, type);
- }
+ jvm_generate(p, 1, 2, "dup");
+ jvm_generate_array_initialization(p, type);
break;
default:
gen_error("jvm_generate_new_static: unk type class %i", type -> class);
}
}
-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;
- }
-}
-
/*
* Генерирует код для копирования полей из первой записи во вторую.
* ( aref_dst aref_src -- )
jvm_generate_store(p, arr, src);
jvm_generate_store(p, arr, dst);
- /* Входящие параметры заграблены
+ /* Входящие параметры заграблены.
* Теперь генерируем эквивалентный код:
* int i = 0;
* int len = dst.length
diff --git a/src/test.c b/src/test.c
index df0ff8041e00d95bae0f2b1827ac74da2fa4d8e3..6282321069c7d32b23e1a5139fe71985762c8e80 100644 (file)
--- a/src/test.c
+++ b/src/test.c
"MODULE Test;"
"TYPE"
" RecDesc = RECORD a : ARRAY 3, 5 OF INTEGER; END;"
- ""
"VAR"
" a, b : ARRAY 3, 6 OF RecDesc;"
- ""
"BEGIN"
" a := b;"
"END Test."