index 4b5b9474c0a2f006c99e15c5e4251e37763785b1..dc79ea11cd0cbb656036a37d67d9a512c46517ae 100644 (file)
}
static void
-jvm_generate_new(gen_proc_t * p, oberon_type_t * type, int num);
+jvm_generate_load(gen_proc_t * p, oberon_type_t * src_type, gen_var_t * src)
+{
+ char prefix;
+ int cell_size;
-/*
- * Функция jvm_generate_static_array_initialization генерирует код для
- * статической инициализации массива. На входе массив, на выходе тот же массив.
- * (arrayref -- arrayref)
- */
+ 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_static_array_initialization(gen_proc_t * p, oberon_type_t * type)
+jvm_generate_store(gen_proc_t * p, oberon_type_t * src_type, gen_var_t * dst)
{
- /* 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);
+ char prefix;
+ int cell_size;
- /* 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);
+ cell_size = jvm_cell_size_for_type(src_type);
- int label_start = jvm_new_label_id(p);
- int label_end = jvm_new_label_id(p);
+ 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;
+ }
+}
- /* start: */
- /* if (i >= l) goto end; */
- /* body*/
- /* i += 1;*/
- /* goto start;*/
- /* end: */
- /* push a */
+static void
+jvm_generate_new(gen_proc_t * p, oberon_type_t * type, int num);
- 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);
+/*
+ * Генерирует код для инициализации массива со статическим базовым типом
+ * ( aref -- )
+ */
- if(type -> base -> class == OBERON_TYPE_ARRAY)
+static void
+jvm_generate_array_initialization(gen_proc_t * p, oberon_type_t * arr)
+{
+ 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);
- /* i += 1; */
- /* goto start */
+ /* TODO преределать через jvm_generate_load{{store}} */
- 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);
+ jvm_generate(p, 0, 1, "iconst_0");
+ jvm_generate(p, 1, 0, "istore %i", loop[i].index -> reg);
- /* push(a) */
- jvm_generate(p, 0, 1, "aload %i", reg_a);
+ jvm_generate_load(p, arr, dst);
+ jvm_generate(p, 1, 1, "arraylength");
+ jvm_generate(p, 1, 0, "istore %i", loop[i].length -> reg);
- /* TODO освобождение регистров */
+ /* 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);
+ }
+
+ 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");
+
+ 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
jvm_generate(p, 2, 0, "if_icmpge L%i", loop[i].end);
}
- if(base -> class == OBERON_TYPE_ARRAY)
- {
- // Вся эта шляпа уже должна знать о всех размерностях
- gen_error("jvm_generate_copy_array: wat");
- }
- else if(base -> class == OBERON_TYPE_RECORD)
+ if(base -> class == OBERON_TYPE_RECORD)
{
/* Получаем записи по индексам ( -- dst src ) */
/* смотри oberon_generator_init_record() */
break;
case OBERON_CLASS_VAR:
- /* Локальные заполняются при генерации функции */
+ /* Локальные заполняются при генерации функции */
/* смотри jvm_init_local_object() */
if(var -> local == 0)
{
}
}
+/*
+ * Генерирует код для получения размера измерения массива
+ * Аналог Обероновского LEN(v, n); где n = 0 - первое измерение.
+ * ( aref -- int )
+ */
+
+static void
+jvm_generate_array_len(gen_proc_t * p, int dim)
+{
+ while(dim > 0)
+ {
+ jvm_generate(p, 0, 1, "iconst_0");
+ jvm_generate(p, 2, 1, "aaload");
+ dim -= 1;
+ }
+ jvm_generate(p, 1, 1, "arraylength");
+}
+
+static void
+jvm_generate_array_duplicate_and_replace(gen_proc_t * p, gen_var_t * v, oberon_type_t * arr)
+{
+ 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_array_len(p, dim);
+ dim += 1;
+ }
+ base = base -> base;
+ }
+
+ jvm_generate_new(p, arr, dim);
+ jvm_generate(p, 1, 2, "dup");
+ jvm_generate_load(p, arr, v);
+ jvm_generate_copy_array(p, arr);
+ jvm_generate_store(p, arr, v);
+}
+
+static void
+jvm_generate_record_duplicate_and_replace(gen_proc_t * p, gen_var_t * v, oberon_type_t * rec)
+{
+ jvm_generate_new(p, rec, 0);
+ jvm_generate(p, 1, 2, "dup");
+ jvm_generate_load(p, rec, v);
+ jvm_generate_copy_record(p, rec);
+ jvm_generate_store(p, rec, v);
+}
+
void
oberon_generate_begin_proc(oberon_context_t * ctx, oberon_object_t * proc)
{
p = proc -> gen_proc;
signature = jvm_get_procedure_signature(proc -> type);
-
jvm_generate_function_header(p, "public static", proc -> name, signature);
+ /* Выделение регистров под параметры и переменные */
oberon_object_t * var = proc -> type -> decl;
while(var)
{
jvm_init_local_object(p, var);
var = var -> next;
}
+
+ /* Копирование статических/открытых массивов и записей */
+ var = proc -> type -> decl;
+ while(var)
+ {
+ if(var -> class == OBERON_CLASS_PARAM || var -> class == OBERON_CLASS_VAR_PARAM)
+ {
+ if(var -> type -> class == OBERON_TYPE_ARRAY)
+ {
+ jvm_generate_array_duplicate_and_replace(p, var -> gen_var, var -> type);
+ }
+ else if(var -> type -> class == OBERON_TYPE_RECORD)
+ {
+ jvm_generate_record_duplicate_and_replace(p, var -> gen_var, var -> type);
+ }
+ }
+ var = var -> next;
+ }
}
void