DEADSOFTWARE

JVM: Добавлено копирование массивов
[dsw-obn.git] / src / backends / jvm / generator-jvm.c
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <stdarg.h>
4 #include <stdint.h>
5 #include <stdbool.h>
6 #include <string.h>
7 #include <assert.h>
9 #include <gc.h>
11 #include "../../../include/oberon.h"
12 #include "../../oberon-internals.h"
13 #include "generator-jvm.h"
14 #include "generator-jvm-basic.h"
16 // ==========================================
17 // ==========================================
18 // ==========================================
20 gen_proc_t *
21 jvm_create_proc(struct gen_class * class)
22 {
23 gen_proc_t * p = GC_MALLOC(sizeof *p);
24 memset(p, 0, sizeof *p);
26 struct gen_register_file * rf = GC_MALLOC(sizeof *rf);
27 memset(rf, 0, sizeof *rf);
29 struct gen_stack * stack = GC_MALLOC(sizeof *stack);
30 memset(rf, 0, sizeof *stack);
32 p -> rf = rf;
33 p -> stack = stack;
34 p -> class = class;
35 p -> label_id = 0;
37 return p;
38 }
40 void
41 jvm_generate_function_header(gen_proc_t * p, char * access, char * name, char * signature)
42 {
43 struct gen_class * class;
44 class = p -> class;
46 /* Делаем процедуру текущей в этом классе */
47 assert(class -> p == NULL);
48 class -> p = p;
50 fprintf(class -> fp, ".method %s %s%s\n", access, name, signature);
51 fprintf(class -> fp, " start:\n");
52 }
54 void
55 jvm_generate_function_end(gen_proc_t * p)
56 {
57 struct gen_class * class;
58 class = p -> class;
60 assert(class -> p);
61 class -> p = NULL;
63 int pointer = p -> stack -> pointer;
64 int max_pointer = p -> stack -> max_pointer;
65 int locals = p -> rf -> num_used;
66 int max_locals = p -> rf -> max_used;
68 fprintf(class -> fp, " .limit stack %i \t; current(%i)\n", max_pointer, pointer);
69 fprintf(class -> fp, " .limit locals %i \t; current(%i)\n", max_locals, locals);
70 fprintf(class -> fp, " end:\n");
71 fprintf(class -> fp, ".end method\n\n");
72 }
74 struct gen_class *
75 jvm_create_class(char * full_name)
76 {
77 struct gen_class * class = GC_MALLOC(sizeof *class);
78 memset(class, 0, sizeof *class);
80 char * fname = new_string("%s.j", full_name);
81 class -> full_name = new_string(full_name);
82 class -> fp = fopen(fname, "w");
83 assert(class -> fp);
85 return class;
86 }
88 static void
89 jvm_destroy_class(struct gen_class * class)
90 {
91 assert(class -> p == NULL);
92 fclose(class -> fp);
93 }
95 static void
96 jvm_stack_push(gen_proc_t * p, unsigned size)
97 {
98 p -> stack -> pointer += size;
99 if(p -> stack -> pointer > p -> stack -> max_pointer)
101 p -> stack -> max_pointer = p -> stack -> pointer;
105 static void
106 jvm_stack_pop(gen_proc_t * p, unsigned size)
108 p -> stack -> pointer -= size;
110 if(p -> stack -> pointer < 0)
112 printf("WARING: stack pointer %i\n", p -> stack -> pointer);
116 static void
117 jvm_generate(gen_proc_t * p, unsigned get, unsigned push, char * format, ...)
119 va_list ptr;
120 va_start(ptr, format);
122 jvm_stack_pop(p, get);
123 fprintf(p -> class -> fp, " ");
124 vfprintf(p -> class -> fp, format, ptr);
125 jvm_stack_push(p, push);
126 fprintf(p -> class -> fp, " \t ;>>>> %i -- %i : current_stack(%i)\n", get, push, p -> stack -> pointer);
128 va_end(ptr);
131 static void
132 jvm_generate_push_int(gen_proc_t * p, int64_t i)
134 if(i == -1)
136 jvm_generate(p, 0, 1, "iconst_m1");
138 else if(i >= 0 && i <= 5)
140 jvm_generate(p, 0, 1, "iconst_%li", i);
142 else if(i >= -128 && i <= 127)
144 jvm_generate(p, 0, 1, "bipush %li", i);
146 else if(i >= -32768 && i <= 32767)
148 jvm_generate(p, 0, 1, "sipush %li", i);
150 else if(i >= -2147483648 && i <= 2147483647)
152 jvm_generate(p, 0, 1, "ldc %li", i);
154 else
156 jvm_generate(p, 0, 2, "ldc2 %li", i);
160 static void
161 jvm_generate_push_float(gen_proc_t * p, double f, int size)
163 if(size <= 4)
165 if(f == 0.0)
167 jvm_generate(p, 0, 1, "fconst_0");
169 if(f == 1.0)
171 jvm_generate(p, 0, 1, "fconst_1");
173 if(f == 2.0)
175 jvm_generate(p, 0, 1, "fconst_2");
177 else
179 jvm_generate(p, 0, 1, "ldc %lf", f);
182 else
184 if(f == 0.0)
186 jvm_generate(p, 0, 2, "dconst_0");
188 if(f == 1.0)
190 jvm_generate(p, 0, 2, "dconst_1");
192 else
194 jvm_generate(p, 0, 2, "ldc2 %lf", f);
199 static gen_var_t *
200 oberon_generator_new_var()
202 gen_var_t * v = GC_MALLOC(sizeof *v);
203 memset(v, 0, sizeof *v);
204 return v;
207 static void
208 jvm_generate_and_init_global_var(gen_var_t * v, struct gen_class * class, char * access, char * name, char * desc)
210 assert(class -> p == NULL);
211 fprintf(class -> fp, ".field %s static %s %s\n\n", access, name, desc);
213 v -> storage = JVM_STORAGE_STATIC;
214 v -> full_name = new_string("%s/%s", class -> full_name, name);
215 v -> desc = new_string(desc);
218 static void
219 jvm_generate_and_init_field(gen_var_t * v, struct gen_class * class, char * access, char * name, char * desc)
221 assert(class -> p == NULL);
222 fprintf(class -> fp, ".field %s %s %s\n\n", access, name, desc);
224 v -> storage = JVM_STORAGE_FIELD;
225 v -> full_name = new_string("%s/%s", class -> full_name, name);
226 v -> desc = new_string(desc);
229 static void
230 jvm_generate_and_init_local_var(gen_var_t * v, gen_proc_t * p, bool wide)
232 v -> storage = JVM_STORAGE_REGISTER;
233 v -> reg = jvm_alloc_register_untyped(p -> rf, wide);
236 static void
237 jvm_generate_and_init_named_local_var(gen_var_t * v, gen_proc_t * p, bool wide, char * name, char * desc)
239 jvm_generate_and_init_local_var(v, p, wide);
240 v -> desc = new_string(desc);
241 jvm_generate(p, 0, 0, ".var %i is %s %s from start to end", v -> reg, name, desc);
244 static int
245 jvm_new_label_id(gen_proc_t * p)
247 int label_id = p -> label_id;
248 p -> label_id += 1;
249 return label_id;
252 static char *
253 jvm_get_label_name(int label_id)
255 return new_string("L%i", label_id);
258 static void
259 jvm_generate_label(gen_proc_t * p, int label_id)
261 jvm_generate(p, 0, 0, "L%i:", label_id);
264 static void
265 jvm_generate_new(gen_proc_t * p, oberon_type_t * type, int num);
267 /*
268 * Функция jvm_generate_static_array_initialization генерирует код для
269 * статической инициализации массива. На входе массив, на выходе тот же массив.
270 * (arrayref -- arrayref)
271 */
273 static void
274 jvm_generate_static_array_initialization(gen_proc_t * p, oberon_type_t * type)
276 /* for(int i = 0; i < a.length; i++) */
277 /* a[i] := new(base); */
278 /* init(a[i]) */
280 /* a := pop(array) */
281 gen_var_t * va = oberon_generator_new_var();
282 jvm_generate_and_init_local_var(va, p, false);
283 int reg_a = va -> reg;
284 /* ссылка уже на стеке */
285 jvm_generate(p, 1, 0, "astore %i", reg_a);
287 /* int i = 0; */
288 gen_var_t * vi = oberon_generator_new_var();
289 jvm_generate_and_init_local_var(vi, p, false);
290 int reg_i = vi -> reg;
291 jvm_generate(p, 0, 1, "iconst_0");
292 jvm_generate(p, 1, 0, "istore %i", reg_i);
294 /* int l := a.length */
295 gen_var_t * vl = oberon_generator_new_var();
296 jvm_generate_and_init_local_var(vl, p, false);
297 int reg_l = vl -> reg;
298 jvm_generate(p, 0, 1, "aload %i", reg_a);
299 jvm_generate(p, 1, 1, "arraylength");
300 jvm_generate(p, 1, 0, "istore %i", reg_l);
302 int label_start = jvm_new_label_id(p);
303 int label_end = jvm_new_label_id(p);
305 /* start: */
306 /* if (i >= l) goto end; */
307 /* body*/
308 /* i += 1;*/
309 /* goto start;*/
310 /* end: */
311 /* push a */
313 jvm_generate_label(p, label_start);
314 jvm_generate(p, 0, 1, "iload %i", reg_i);
315 jvm_generate(p, 0, 1, "iload %i", reg_l);
316 jvm_generate(p, 2, 0, "if_icmpge L%i", label_end);
318 if(type -> base -> class == OBERON_TYPE_ARRAY)
320 /* Инициализируем следующую размерность */
321 jvm_generate(p, 0, 1, "aload %i", reg_a);
322 jvm_generate(p, 0, 1, "iload %i", reg_i);
323 jvm_generate(p, 0, 1, "aaload");
324 jvm_generate_static_array_initialization(p, type -> base);
325 jvm_generate(p, 1, 0, "pop");
327 else if(type -> base -> class == OBERON_TYPE_RECORD)
329 jvm_generate(p, 0, 1, "aload %i", reg_a);
330 jvm_generate(p, 0, 1, "iload %i", reg_i);
331 jvm_generate_new(p, type -> base, 0);
332 jvm_generate(p, 3, 0, "aastore");
334 else
336 assert(0);
339 /* i += 1; */
340 /* goto start */
342 jvm_generate(p, 0, 0, "iinc %i %i", reg_i, 1);
343 jvm_generate(p, 0, 0, "goto L%i", label_start);
344 jvm_generate_label(p, label_end);
346 /* push(a) */
347 jvm_generate(p, 0, 1, "aload %i", reg_a);
349 /* TODO освобождение регистров */
352 static void
353 jvm_generate_new(gen_proc_t * p, oberon_type_t * type, int num)
355 int dim;
356 char * cname;
357 char * desc;
358 oberon_type_t * base;
360 switch(type -> class)
362 case OBERON_TYPE_INTEGER:
363 case OBERON_TYPE_BOOLEAN:
364 case OBERON_TYPE_PROCEDURE:
365 case OBERON_TYPE_REAL:
366 case OBERON_TYPE_POINTER:
367 gen_error("jvm_generate_new_static: static alocation not allowed");
368 break;
369 case OBERON_TYPE_RECORD:
370 cname = jvm_get_class_full_name(type);
371 jvm_generate(p, 0, 1, "new %s", cname);
372 jvm_generate(p, 1, 2, "dup");
373 jvm_generate(p, 1, 0, "invokespecial %s/<init>()V", cname);
374 break;
375 case OBERON_TYPE_ARRAY:
376 dim = 0;
377 base = type;
378 desc = jvm_get_descriptor(type);
379 while(base -> class == OBERON_TYPE_ARRAY)
381 if(num > 0)
383 assert(base -> size == 0);
384 num -= 1;
386 else
388 assert(base -> size > 0);
389 jvm_generate_push_int(p, base -> size);
391 dim += 1;
392 base = base -> base;
395 assert(num == 0);
396 jvm_generate(p, dim, 1, "multianewarray %s %i", desc, dim);
398 if(base -> class == OBERON_TYPE_RECORD)
400 jvm_generate_static_array_initialization(p, type);
402 break;
403 default:
404 gen_error("jvm_generate_new_static: unk type class %i", type -> class);
405 break;
409 static void
410 jvm_generate_load(gen_proc_t * p, oberon_type_t * src_type, gen_var_t * src)
412 char prefix;
413 int cell_size;
415 cell_size = jvm_cell_size_for_type(src_type);
417 switch(src -> storage)
419 case JVM_STORAGE_REGISTER:
420 prefix = jvm_get_prefix(src_type);
421 jvm_generate(p, 0, cell_size, "%cload %i", prefix, src -> reg);
422 break;
423 case JVM_STORAGE_STATIC:
424 jvm_generate(p, 0, cell_size, "getstatic %s %s", src -> full_name, src -> desc);
425 break;
426 case JVM_STORAGE_FIELD:
427 jvm_generate(p, 1, cell_size, "getfield %s %s", src -> full_name, src -> desc);
428 break;
429 default:
430 gen_error("jvm_generate_load: unknow storage type %i", src -> storage);
431 break;
435 static void
436 jvm_generate_store(gen_proc_t * p, oberon_type_t * src_type, gen_var_t * dst)
438 char prefix;
439 int cell_size;
441 cell_size = jvm_cell_size_for_type(src_type);
443 switch(dst -> storage)
445 case JVM_STORAGE_REGISTER:
446 prefix = jvm_get_prefix(src_type);
447 jvm_generate(p, cell_size, 0, "%cstore %i", prefix, dst -> reg);
448 break;
449 case JVM_STORAGE_STATIC:
450 jvm_generate(p, cell_size, 0, "putstatic %s %s", dst -> full_name, dst -> desc);
451 break;
452 case JVM_STORAGE_FIELD:
453 jvm_generate(p, 1 + cell_size, 0, "putfield %s %s", dst -> full_name, dst -> desc);
454 break;
455 default:
456 gen_error("jvm_generate_store: unknow storage type %i", dst -> storage);
457 break;
461 /*
462 * Генерирует код для копирования полей из первой записи во вторую.
463 * ( aref_dst aref_src -- )
464 * dst := src;
465 */
467 static void
468 jvm_generate_copy_record(gen_proc_t * p, oberon_type_t * rec)
470 assert(rec -> class == OBERON_TYPE_RECORD);
471 char * desc = jvm_get_descriptor(rec);
472 char * cname = jvm_get_class_full_name(rec);
473 jvm_generate(p, 1 + 1, 0, "invokestatic %s/$COPY$(%s%s)V", cname, desc, desc);
476 /*
477 * Генерирует кода для копирования массивов.
478 * ( aref_dst aref_src -- )
479 * dst := src;
480 */
482 static void
483 jvm_generate_copy_array(gen_proc_t * p, oberon_type_t * arr)
485 int dim = 0;
486 oberon_type_t * base = arr;
487 while(base -> class == OBERON_TYPE_ARRAY)
489 dim += 1;
490 base = base -> base;
493 struct {
494 gen_var_t * index;
495 gen_var_t * length;
496 int start;
497 int end;
498 } loop[dim];
500 gen_var_t * dst = oberon_generator_new_var();
501 gen_var_t * src = oberon_generator_new_var();
502 jvm_generate_and_init_local_var(dst, p, false);
503 jvm_generate_and_init_local_var(src, p, false);
505 jvm_generate_store(p, arr, src);
506 jvm_generate_store(p, arr, dst);
508 /* Входящие параметры заграблены
509 * Теперь генерируем эквивалентный код:
510 * int i = 0;
511 * int len = dst.length
512 * while(i < len)
513 * {
514 * ...
515 * {
516 * copy from src[i, ...] to dst[i, ...];
517 * }
518 * ...
519 * i += 1;
520 * }
521 * Где "..." такой же код (начало и конец) для следующей размерности.
522 */
524 for(int i = 0; i < dim; i++)
526 loop[i].index = oberon_generator_new_var();
527 loop[i].length = oberon_generator_new_var();
528 loop[i].start = jvm_new_label_id(p);
529 loop[i].end = jvm_new_label_id(p);
530 jvm_generate_and_init_local_var(loop[i].index, p, false);
531 jvm_generate_and_init_local_var(loop[i].length, p, false);
533 /* TODO преределать через jvm_generate_load{{store}} */
535 jvm_generate(p, 0, 1, "iconst_0");
536 jvm_generate(p, 1, 0, "istore %i", loop[i].index -> reg);
538 jvm_generate_load(p, arr, dst);
539 jvm_generate(p, 1, 1, "arraylength");
540 jvm_generate(p, 1, 0, "istore %i", loop[i].length -> reg);
542 /* if(i >= len) goto end; */
543 jvm_generate_label(p, loop[i].start);
544 jvm_generate(p, 0, 1, "iload %i", loop[i].index -> reg);
545 jvm_generate(p, 0, 1, "iload %i", loop[i].length -> reg);
546 jvm_generate(p, 2, 0, "if_icmpge L%i", loop[i].end);
549 if(base -> class == OBERON_TYPE_ARRAY)
551 // Вся эта шляпа уже должна знать о всех размерностях
552 gen_error("jvm_generate_copy_array: wat");
554 else if(base -> class == OBERON_TYPE_RECORD)
556 /* Получаем записи по индексам ( -- dst src ) */
558 jvm_generate_load(p, arr, dst);
559 for(int i = 0; i < dim; i++)
561 jvm_generate(p, 0, 1, "iload %i", loop[i].index -> reg);
562 jvm_generate(p, 2, 1, "aaload");
565 jvm_generate_load(p, arr, src);
566 for(int i = 0; i < dim; i++)
568 jvm_generate(p, 0, 1, "iload %i", loop[i].index -> reg);
569 jvm_generate(p, 2, 1, "aaload");
572 /* Копируем записи ( dst src -- ) */
573 jvm_generate_copy_record(p, base);
575 else
577 char postfix = jvm_get_postfix(base);
578 int cell_size = jvm_cell_size_for_postfix(postfix);
580 /* Получаем массивы и индексы ( -- dst i src i ) */
582 jvm_generate_load(p, arr, dst);
583 jvm_generate(p, 0, 1, "iload %i", loop[0].index -> reg);
584 for(int i = 1; i < dim; i++)
586 jvm_generate(p, 2, 1, "aaload");
587 jvm_generate(p, 0, 1, "iload %i", loop[i].index -> reg);
590 jvm_generate_load(p, arr, src);
591 jvm_generate(p, 0, 1, "iload %i", loop[0].index -> reg);
592 for(int i = 1; i < dim; i++)
594 jvm_generate(p, 2, 1, "aaload");
595 jvm_generate(p, 0, 1, "iload %i", loop[i].index -> reg);
598 /* Копируем значения ( dst i src i -- ) */
599 jvm_generate(p, 2, cell_size, "%caload", postfix);
600 jvm_generate(p, 2 + cell_size, 0, "%castore", postfix);
603 for(int i = dim - 1; i >= 0; i--)
605 jvm_generate(p, 0, 0, "iinc %i 1", loop[i].index -> reg);
606 jvm_generate(p, 0, 0, "goto L%i", loop[i].start);
607 jvm_generate_label(p, loop[i].end);
611 // ==========================================
612 // ==========================================
613 // ==========================================
615 void
616 oberon_generator_init_context(oberon_context_t * ctx)
618 gen_context_t * gen_context = GC_MALLOC(sizeof *gen_context);
619 memset(gen_context, 0, sizeof *gen_context);
621 ctx -> gen_context = gen_context;
624 void
625 oberon_generator_destroy_context(oberon_context_t * ctx)
629 static void
630 oberon_generate_procedure_class(oberon_type_t * proc)
632 FILE * fp;
633 char * cname;
634 char * signature;
635 struct gen_class * class;
637 cname = jvm_get_class_full_name(proc);
638 class = jvm_create_class(cname);
639 fp = class -> fp;
641 fprintf(fp, ".source SYSTEM\n");
642 fprintf(fp, ".class public abstract %s\n", cname);
643 fprintf(fp, ".super java/lang/Object\n\n");
645 fprintf(fp, ".method public <init>()V\n");
646 fprintf(fp, " aload_0\n");
647 fprintf(fp, " invokespecial java/lang/Object/<init>()V\n");
648 fprintf(fp, " return\n");
649 fprintf(fp, ".end method\n\n");
651 signature = jvm_get_procedure_signature(proc);
653 fprintf(fp, ".method public abstract invoke%s\n", signature);
654 fprintf(fp, ".end method\n\n");
656 jvm_destroy_class(class);
659 static void
660 oberon_generate_record_class(gen_module_t * m, oberon_type_t * rec)
662 char * cname;
663 struct gen_class * class;
665 /* Устанавливаем новоый id */
666 rec -> gen_type -> rec_id = m -> rec_id;
667 m -> rec_id += 1;
669 cname = jvm_get_class_full_name(rec);
670 class = jvm_create_class(cname);
672 fprintf(class -> fp, ".source %s\n", rec -> module -> name);
673 fprintf(class -> fp, ".class public %s\n", cname);
674 fprintf(class -> fp, ".super java/lang/Object\n\n");
676 rec -> gen_type -> class = class;
679 void
680 oberon_generator_init_type(oberon_context_t * ctx, oberon_type_t * type)
682 gen_type_t * t = GC_MALLOC(sizeof *t);
683 memset(t, 0, sizeof *t);
684 type -> gen_type = t;
686 switch(type -> class)
688 case OBERON_TYPE_VOID:
689 case OBERON_TYPE_INTEGER:
690 case OBERON_TYPE_BOOLEAN:
691 case OBERON_TYPE_ARRAY:
692 case OBERON_TYPE_REAL:
693 break;
694 case OBERON_TYPE_RECORD:
696 gen_module_t * m;
697 m = type -> module -> gen_mod;
698 oberon_generate_record_class(m, type);
699 break;
700 case OBERON_TYPE_PROCEDURE:
701 oberon_generate_procedure_class(type);
702 break;
703 case OBERON_TYPE_POINTER:
704 break;
705 default:
706 gen_error("oberon_generator_init_type: unk calss %i", type -> class);
707 break;
711 void
712 oberon_generator_init_record(oberon_context_t * ctx, oberon_type_t * rec)
714 struct gen_class * class;
715 class = rec -> gen_type -> class;
717 int num = rec -> num_decl;
718 oberon_object_t * field = rec -> decl;
719 for(int i = 0; i < num; i++)
721 gen_var_t * v = field -> gen_var;
722 char * name = field -> name;
723 char * desc = jvm_get_descriptor(field -> type);
724 jvm_generate_and_init_field(v, class, "public", name, desc);
725 field = field -> next;
728 /* Стандартный конструктор класса */
729 /* Инициализирует внутренние статические записи и массивы */
730 gen_proc_t * p = jvm_create_proc(class);
731 jvm_generate_function_header(p, "public", "<init>", "()V");
732 jvm_alloc_register_untyped(p -> rf, false);
733 jvm_generate(p, 0, 1, "aload_0");
734 jvm_generate(p, 1, 0, "invokespecial java/lang/Object/<init>()V");
735 num = rec -> num_decl;
736 field = rec -> decl;
737 for(int i = 0; i < num; i++)
739 if(field -> type -> class == OBERON_TYPE_RECORD
740 || field -> type -> class == OBERON_TYPE_ARRAY)
742 jvm_generate(p, 0, 1, "aload_0");
743 jvm_generate_new(p, field -> type, 0);
744 jvm_generate_store(p, field -> type, field -> gen_var);
746 field = field -> next;
748 jvm_generate(p, 0, 0, "return");
749 jvm_generate_function_end(p);
751 /* Метод для копирования полей класса */
752 /* reg0 == src -> reg1 == dst */
753 p = jvm_create_proc(class);
754 gen_var_t * copy_dst = oberon_generator_new_var();
755 gen_var_t * copy_src = oberon_generator_new_var();
756 char * desc = jvm_get_descriptor(rec);
757 char * signature = new_string("(%s%s)V", desc, desc);
758 jvm_generate_function_header(p, "public static", "$COPY$", signature);
759 jvm_generate_and_init_named_local_var(copy_dst, p, false, "dst", desc);
760 jvm_generate_and_init_named_local_var(copy_src, p, false, "src", desc);
761 num = rec -> num_decl;
762 field = rec -> decl;
763 for(int i = 0; i < num; i++)
765 if(field -> type -> class == OBERON_TYPE_RECORD)
767 jvm_generate_load(p, rec, copy_dst);
768 jvm_generate_load(p, field -> type, field -> gen_var);
769 jvm_generate_load(p, rec, copy_src);
770 jvm_generate_load(p, field -> type, field -> gen_var);
771 jvm_generate_copy_record(p, field -> type);
773 else if(field -> type -> class == OBERON_TYPE_ARRAY)
775 jvm_generate_load(p, rec, copy_dst);
776 jvm_generate_load(p, field -> type, field -> gen_var);
777 jvm_generate_load(p, rec, copy_src);
778 jvm_generate_load(p, field -> type, field -> gen_var);
779 jvm_generate_copy_array(p, field -> type);
781 else
783 jvm_generate_load(p, rec, copy_dst);
784 jvm_generate_load(p, rec, copy_src);
785 jvm_generate_load(p, field -> type, field -> gen_var);
786 jvm_generate_store(p, field -> type, field -> gen_var);
788 field = field -> next;
790 jvm_generate(p, 0, 0, "return");
791 jvm_generate_function_end(p);
793 jvm_destroy_class(class);
796 void
797 oberon_generator_init_var(oberon_context_t * ctx, oberon_object_t * var)
799 gen_var_t * v = oberon_generator_new_var();
800 var -> gen_var = v;
802 gen_module_t * m;
803 m = ctx -> mod -> gen_mod;
805 struct gen_class * class;
806 class = m -> class;
808 char * desc;
809 switch(var -> class)
811 case OBERON_CLASS_VAR_PARAM:
812 gen_error("generator: VAR-parameters not implemented");
813 break;
814 case OBERON_CLASS_PARAM:
815 /* Заполняется при генерации функции */
816 /* смотри jvm_init_local_object() */
817 break;
818 case OBERON_CLASS_FIELD:
819 /* Заполняются при инициализации структуры */
820 /* смотри oberon_generator_init_record() */
821 break;
822 case OBERON_CLASS_VAR:
823 /* Локальные заполняются при генерации функции */
824 /* смотри jvm_init_local_object() */
825 if(var -> local == 0)
827 desc = jvm_get_descriptor(var -> type);
828 jvm_generate_and_init_global_var(v, class, "public", var -> name, desc);
830 break;
831 default:
832 gen_error("oberon_generator_init_var: unk var class %i", var -> class);
833 break;
837 void
838 oberon_generator_init_proc(oberon_context_t * ctx, oberon_object_t * proc)
840 struct gen_class * class = proc -> module -> gen_mod -> class;
841 proc -> gen_proc = jvm_create_proc(class);
843 if(proc -> local)
845 gen_error("generator: local procedures not implemented");
849 void
850 oberon_generator_init_module(oberon_context_t * ctx, oberon_module_t * mod)
852 gen_module_t * m = GC_MALLOC(sizeof *m);
853 memset(m, 0, sizeof *m);
854 mod -> gen_mod = m;
856 struct gen_class * class;
857 class = jvm_create_class(mod -> name);
859 fprintf(class -> fp, ".source %s\n", mod -> name);
860 fprintf(class -> fp, ".class %s\n", mod -> name);
861 fprintf(class -> fp, ".super java/lang/Object\n\n");
863 m -> class = class;
865 ctx -> gen_context -> current_m = m;
868 void
869 oberon_generator_fini_module(oberon_module_t * mod)
871 jvm_destroy_class(mod -> gen_mod -> class);
874 static void
875 push_expr(gen_proc_t * p, oberon_expr_t * expr);
877 void
878 oberon_generate_begin_module(oberon_context_t * ctx)
880 struct gen_class * class = ctx -> mod -> gen_mod -> class;
881 gen_proc_t * p = jvm_create_proc(class);
883 jvm_generate_function_header(p, "public", "<init>", "()V");
884 jvm_alloc_register_untyped(p -> rf, false);
885 jvm_generate(p, 0, 1, "aload_0");
886 jvm_generate(p, 1, 0, "invokespecial java/lang/Object/<init>()V");
888 /* Инициализация переменных объявленных в модуле */
889 oberon_object_t * x = ctx -> mod -> decl -> list -> next;
890 while(x != NULL)
892 if(x -> class == OBERON_CLASS_VAR)
894 if(x -> type -> class == OBERON_TYPE_ARRAY
895 || x -> type -> class == OBERON_TYPE_RECORD)
897 jvm_generate_new(p, x -> type, 0);
898 jvm_generate_store(p, x -> type, x -> gen_var);
901 x = x -> next;
905 void
906 oberon_generate_end_module(oberon_context_t * ctx)
908 struct gen_class * class = ctx -> mod -> gen_mod -> class;
909 gen_proc_t * p = class -> p;
911 jvm_generate(p, 0, 0, "return");
912 jvm_generate_function_end(class -> p);
915 static void
916 jvm_init_local_object(gen_proc_t * p, oberon_object_t * x)
918 gen_var_t * v;
919 bool wide;
920 char * desc;
921 struct gen_class * class;
923 v = x -> gen_var;
924 class = p -> class;
925 wide = jvm_is_wide_type(x -> type);
926 desc = jvm_get_descriptor(x -> type);
928 // Убеждаемся что сейчас находимся в функции
929 assert(class -> p);
930 assert(x -> local);
932 switch(x -> class)
934 case OBERON_CLASS_VAR:
935 case OBERON_CLASS_PARAM:
936 jvm_generate_and_init_named_local_var(v, p, wide, x -> name, desc);
937 break;
938 default:
939 gen_error("jvm_init_local_object: wat");
940 break;
944 void
945 oberon_generate_begin_proc(oberon_context_t * ctx, oberon_object_t * proc)
947 gen_proc_t * p;
948 char * signature;
950 p = proc -> gen_proc;
952 signature = jvm_get_procedure_signature(proc -> type);
954 jvm_generate_function_header(p, "public static", proc -> name, signature);
956 oberon_object_t * var = proc -> type -> decl;
957 while(var)
959 jvm_init_local_object(p, var);
960 var = var -> next;
964 void
965 oberon_generate_end_proc(oberon_context_t * ctx)
967 gen_module_t * m;
968 gen_proc_t * p;
970 m = ctx -> mod -> gen_mod;
971 p = m -> class -> p;
973 jvm_generate_function_end(p);
976 static void
977 jvm_generate_call_proc(gen_proc_t * p, oberon_expr_t * desig)
979 assert(desig -> is_item);
980 assert(desig -> item.mode == MODE_CALL);
982 oberon_object_t * proc;
983 char * fullname;
984 char * signature;
986 proc = desig -> item.var;
987 fullname = jvm_get_field_full_name(proc);
988 signature = jvm_get_procedure_signature(proc -> type);
990 int args_cells = 0;
991 int result_cells = jvm_cell_size_for_type(proc -> type -> base);
993 int num = desig -> item.num_args;
994 oberon_expr_t * arg = desig -> item.args;
995 for(int i = 0; i < num; i++)
997 args_cells += jvm_cell_size_for_type(arg -> result);
998 push_expr(p, arg);
999 arg = arg -> next;
1002 jvm_generate(p, args_cells, result_cells, "invokestatic %s%s", fullname, signature);
1005 void
1006 oberon_generate_call_proc(oberon_context_t * ctx, oberon_expr_t * desig)
1008 jvm_generate_call_proc(ctx -> gen_context -> current_m -> class -> p, desig);
1011 void
1012 oberon_generate_return(oberon_context_t * ctx, oberon_expr_t * expr)
1014 gen_module_t * m;
1015 gen_proc_t * p;
1016 char prefix;
1017 int cell_size;
1019 m = ctx -> mod -> gen_mod;
1020 p = m -> class -> p;
1022 if(expr)
1024 push_expr(p, expr);
1025 prefix = jvm_get_prefix(expr -> result);
1026 cell_size = jvm_cell_size_for_type(expr -> result);
1027 jvm_generate(p, cell_size, 0, "%creturn", prefix);
1029 else
1031 jvm_generate(p, 0, 0, "return");
1035 static void
1036 jvm_generate_expr_new_pointer(gen_proc_t * p, oberon_type_t * type, int num, oberon_expr_t * arg)
1038 assert(type -> class == OBERON_TYPE_POINTER);
1040 for(int i = 0; i < num; i++)
1042 push_expr(p, arg);
1043 arg = arg -> next;
1046 jvm_generate_new(p, type -> base, num);
1049 static void
1050 push_item(gen_proc_t * p, oberon_item_t * item)
1052 switch(item -> mode)
1054 case MODE_VAR:
1055 jvm_generate_load(p, item -> result, item -> var -> gen_var);
1056 break;
1057 case MODE_INTEGER:
1058 jvm_generate_push_int(p, item -> integer);
1059 break;
1060 case MODE_BOOLEAN:
1061 jvm_generate_push_int(p, item -> boolean);
1062 break;
1063 case MODE_CALL:
1064 jvm_generate_call_proc(p, (oberon_expr_t *) item);
1065 break;
1066 case MODE_INDEX:
1068 char postfix = jvm_get_postfix(item -> result);
1069 int cell_size = jvm_cell_size_for_postfix(postfix);
1070 push_item(p, item -> parent);
1071 push_expr(p, item -> args);
1072 jvm_generate(p, 1 + 1, cell_size, "%caload", postfix);
1073 break;
1074 case MODE_FIELD:
1075 push_item(p, item -> parent);
1076 jvm_generate_load(p, item -> result, item -> var -> gen_var);
1077 break;
1078 case MODE_DEREF:
1079 /* Все объекты в jvm представляются как указатели */
1080 push_item(p, item -> parent);
1081 break;
1082 case MODE_NIL:
1083 jvm_generate(p, 0, 1, "aconst_null");
1084 break;
1085 case MODE_NEW:
1086 jvm_generate_expr_new_pointer(p, item -> result, item -> num_args, item -> args);
1087 break;
1088 case MODE_REAL:
1089 jvm_generate_push_float(p, item -> real, item -> result -> size);
1090 break;
1091 default:
1092 gen_error("push_item: unk mode %i", item -> mode);
1093 break;
1097 static void
1098 jvm_generate_logical_not(gen_proc_t * p)
1100 int label_done = jvm_new_label_id(p);
1101 int label_false = jvm_new_label_id(p);
1102 char * label_name_done = jvm_get_label_name(label_done);
1103 char * label_name_false = jvm_get_label_name(label_false);
1105 jvm_generate(p, 1, 0, "ifne %s", label_name_false);
1106 jvm_generate(p, 0, 1, "iconst_1");
1107 jvm_generate(p, 0, 0, "goto %s", label_name_done);
1108 jvm_generate_label(p, label_false);
1109 jvm_generate(p, 0, 1, "iconst_0");
1110 jvm_generate_label(p, label_done);
1113 static void
1114 jvm_generate_abs(gen_proc_t * p, char prefix)
1116 char t = jvm_get_type_of_prefix(prefix);
1117 int cell_size = jvm_cell_size_for_postfix(prefix);
1118 jvm_generate(p, cell_size, cell_size, "invokestatic java/lang/Math/abs(%c)%c", t, t);
1121 static void
1122 jvm_generate_compare_op(gen_proc_t * p, char prefix, int op)
1124 int label_true = jvm_new_label_id(p);
1125 int label_done = jvm_new_label_id(p);
1126 char * label_name_true = jvm_get_label_name(label_true);
1127 char * label_name_done = jvm_get_label_name(label_done);
1128 int cell_size = 2 * jvm_cell_size_for_postfix(prefix);
1130 assert(prefix == 'i' || prefix == 'a');
1132 const char * cmpop = "";
1133 switch(op)
1135 case OP_EQ:
1136 cmpop = "eq";
1137 break;
1138 case OP_NEQ:
1139 cmpop = "ne";
1140 break;
1141 case OP_LSS:
1142 cmpop = "lt";
1143 break;
1144 case OP_LEQ:
1145 cmpop = "le";
1146 break;
1147 case OP_GRT:
1148 cmpop = "gt";
1149 break;
1150 case OP_GEQ:
1151 cmpop = "ge";
1152 break;
1153 default:
1154 gen_error("jvm_generate_compare_op: wat");
1155 break;
1158 jvm_generate(p, cell_size, 0, "if_%ccmp%s %s", prefix, cmpop, label_name_true);
1159 jvm_generate(p, 0, 1, "iconst_0");
1160 jvm_generate(p, 0, 0, "goto %s", label_name_done);
1161 jvm_generate_label(p, label_true);
1162 jvm_generate(p, 0, 1, "iconst_1");
1163 jvm_generate_label(p, label_done);
1166 static void
1167 jvm_generate_operator(gen_proc_t * p, char prefix, int op)
1169 int cell_size = jvm_cell_size_for_postfix(prefix);
1170 switch(op)
1172 case OP_UNARY_MINUS:
1173 jvm_generate(p, cell_size, cell_size, "%cneg", prefix);
1174 break;
1175 case OP_BITWISE_NOT:
1176 jvm_generate_push_int(p, -1);
1177 jvm_generate(p, 2 * cell_size, cell_size, "%cxor", prefix);
1178 break;
1179 case OP_LOGIC_NOT:
1180 jvm_generate_logical_not(p);
1181 break;
1182 case OP_ABS:
1183 jvm_generate_abs(p, prefix);
1184 break;
1186 case OP_ADD:
1187 jvm_generate(p, 2 * cell_size, cell_size, "%cadd", prefix);
1188 break;
1189 case OP_SUB:
1190 jvm_generate(p, 2 * cell_size, cell_size, "%csub", prefix);
1191 break;
1192 case OP_MUL:
1193 jvm_generate(p, 2 * cell_size, cell_size, "%cmul", prefix);
1194 break;
1195 case OP_DIV:
1196 jvm_generate(p, 2 * cell_size, cell_size, "%cdiv", prefix);
1197 break;
1198 case OP_MOD:
1199 jvm_generate(p, 2 * cell_size, cell_size, "%crem", prefix);
1200 break;
1201 case OP_BITWISE_AND:
1202 jvm_generate(p, 2 * cell_size, cell_size, "%cand", prefix);
1203 break;
1204 case OP_BITWISE_XOR:
1205 jvm_generate(p, 2 * cell_size, cell_size, "%cxor", prefix);
1206 break;
1207 case OP_BITWISE_OR:
1208 jvm_generate(p, 2 * cell_size, cell_size, "%cor", prefix);
1209 break;
1211 case OP_EQ:
1212 case OP_NEQ:
1213 case OP_LSS:
1214 case OP_LEQ:
1215 case OP_GRT:
1216 case OP_GEQ:
1217 jvm_generate_compare_op(p, prefix, op);
1218 break;
1219 default:
1220 gen_error("jvm_generate_operator: unk op %i", op);
1221 break;
1222 }
1225 static void
1226 jvm_generate_logical_or(gen_proc_t * p, oberon_expr_t * a, oberon_expr_t * b)
1228 int label_calc_b = jvm_new_label_id(p);
1229 int label_done = jvm_new_label_id(p);
1230 char * label_name_calc_b = jvm_get_label_name(label_calc_b);
1231 char * label_name_done = jvm_get_label_name(label_done);
1233 /* a OR b -- если a, то TRUE, иначе b */
1235 push_expr(p, a);
1236 jvm_generate(p, 1, 0, "ifne %s", label_name_calc_b);
1237 jvm_generate(p, 0, 1, "iconst_1");
1238 jvm_generate(p, 0, 0, "goto %s", label_name_done);
1239 jvm_generate_label(p, label_calc_b);
1240 push_expr(p, b);
1241 jvm_generate_label(p, label_done);
1244 static void
1245 jvm_generate_logical_and(gen_proc_t * p, oberon_expr_t * a, oberon_expr_t * b)
1247 int label_false = jvm_new_label_id(p);
1248 int label_done = jvm_new_label_id(p);
1249 char * label_name_false = jvm_get_label_name(label_false);
1250 char * label_name_done = jvm_get_label_name(label_done);
1252 /* a AND b -- если a, то b, иначе FALSE */
1254 push_expr(p, a);
1255 jvm_generate(p, 1, 0, "ifne %s", label_name_false);
1256 push_expr(p, b);
1257 jvm_generate(p, 0, 0, "goto %s", label_name_done);
1258 jvm_generate_label(p, label_false);
1259 jvm_generate(p, 0, 1, "iconst_0");
1260 jvm_generate_label(p, label_done);
1263 static void
1264 push_operator(gen_proc_t * p, oberon_oper_t * oper)
1266 char prefix = jvm_get_prefix(oper -> result);
1267 int op = oper -> op;
1268 switch(op)
1270 case OP_UNARY_MINUS:
1271 case OP_BITWISE_NOT:
1272 case OP_LOGIC_NOT:
1273 case OP_ABS:
1274 push_expr(p, oper -> left);
1275 jvm_generate_operator(p, prefix, op);
1276 break;
1278 case OP_ADD:
1279 case OP_SUB:
1280 case OP_MUL:
1281 case OP_DIV:
1282 case OP_MOD:
1283 case OP_BITWISE_AND:
1284 case OP_BITWISE_XOR:
1285 case OP_BITWISE_OR:
1287 case OP_EQ:
1288 case OP_NEQ:
1289 case OP_LSS:
1290 case OP_LEQ:
1291 case OP_GRT:
1292 case OP_GEQ:
1293 push_expr(p, oper -> left);
1294 push_expr(p, oper -> right);
1295 jvm_generate_operator(p, prefix, op);
1296 break;
1298 case OP_LOGIC_OR:
1299 jvm_generate_logical_or(p, oper -> left, oper -> right);
1300 break;
1301 case OP_LOGIC_AND:
1302 jvm_generate_logical_and(p, oper -> left, oper -> right);
1303 break;
1304 default:
1305 gen_error("push_oper: unk op %i", op);
1306 break;
1310 static void
1311 push_expr(gen_proc_t * p, oberon_expr_t * expr)
1313 if(expr -> is_item)
1315 push_item(p, (oberon_item_t *) expr);
1317 else
1319 push_operator(p, (oberon_oper_t *) expr);
1323 static void
1324 store_expr(gen_proc_t * p, oberon_expr_t * dst, oberon_expr_t * src)
1326 assert(dst -> is_item);
1327 oberon_item_t * item = (oberon_item_t *) dst;
1329 if(dst -> result -> class == OBERON_TYPE_ARRAY
1330 || src -> result -> class == OBERON_TYPE_ARRAY)
1332 push_expr(p, dst);
1333 push_expr(p, src);
1334 jvm_generate_copy_array(p, dst -> result);
1336 else if(dst -> result -> class == OBERON_TYPE_RECORD
1337 || src -> result -> class == OBERON_TYPE_RECORD)
1339 push_expr(p, dst);
1340 push_expr(p, src);
1341 jvm_generate_copy_record(p, dst -> result);
1343 else switch(item -> mode)
1345 case MODE_VAR:
1346 push_expr(p, src);
1347 jvm_generate_store(p, src -> result, item -> var -> gen_var);
1348 break;
1349 case MODE_INDEX:
1351 char postfix = jvm_get_postfix(src -> result);
1352 int cell_size = jvm_cell_size_for_postfix(postfix);
1353 push_item(p, item -> parent);
1354 push_expr(p, item -> args);
1355 push_expr(p, src);
1356 jvm_generate(p, 1 + 1 + cell_size, 0, "%castore", postfix);
1357 break;
1358 case MODE_FIELD:
1359 push_item(p, item -> parent);
1360 push_expr(p, src);
1361 jvm_generate_store(p, src -> result, item -> var -> gen_var);
1362 break;
1363 default:
1364 gen_error("store_expr: unk mode %i", item -> mode);
1365 break;
1369 void
1370 oberon_generate_assign(oberon_context_t * ctx, oberon_expr_t * src, oberon_expr_t * dst)
1372 gen_module_t * m;
1373 gen_proc_t * p;
1375 m = ctx -> mod -> gen_mod;
1376 p = m -> class -> p;
1378 store_expr(p, dst, src);
1381 void
1382 oberon_generate_code(oberon_context_t * ctx)
1384 printf("generate code\n");
1387 void
1388 oberon_generator_dump(oberon_context_t * ctx, char * path)
1390 printf("jit: dump code\n");
1393 void *
1394 oberon_generator_get_procedure(oberon_context_t * ctx, const char * name)
1396 printf("jit: get pointer to procedure %s\n", name);
1397 return NULL;
1400 void *
1401 oberon_generator_get_var(oberon_context_t * ctx, const char * name)
1403 printf("jit: get pointer to var %s\n", name);
1404 return NULL;