DEADSOFTWARE

895a5ae3e524c2ef30063d1de38a316b2e3d23b1
[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_load(gen_proc_t * p, oberon_type_t * src_type, gen_var_t * src)
267 char prefix;
268 int cell_size;
270 cell_size = jvm_cell_size_for_type(src_type);
272 switch(src -> storage)
274 case JVM_STORAGE_REGISTER:
275 prefix = jvm_get_prefix(src_type);
276 jvm_generate(p, 0, cell_size, "%cload %i", prefix, src -> reg);
277 break;
278 case JVM_STORAGE_STATIC:
279 jvm_generate(p, 0, cell_size, "getstatic %s %s", src -> full_name, src -> desc);
280 break;
281 case JVM_STORAGE_FIELD:
282 jvm_generate(p, 1, cell_size, "getfield %s %s", src -> full_name, src -> desc);
283 break;
284 default:
285 gen_error("jvm_generate_load: unknow storage type %i", src -> storage);
286 break;
290 static void
291 jvm_generate_store(gen_proc_t * p, oberon_type_t * src_type, gen_var_t * dst)
293 char prefix;
294 int cell_size;
296 cell_size = jvm_cell_size_for_type(src_type);
298 switch(dst -> storage)
300 case JVM_STORAGE_REGISTER:
301 prefix = jvm_get_prefix(src_type);
302 jvm_generate(p, cell_size, 0, "%cstore %i", prefix, dst -> reg);
303 break;
304 case JVM_STORAGE_STATIC:
305 jvm_generate(p, cell_size, 0, "putstatic %s %s", dst -> full_name, dst -> desc);
306 break;
307 case JVM_STORAGE_FIELD:
308 jvm_generate(p, 1 + cell_size, 0, "putfield %s %s", dst -> full_name, dst -> desc);
309 break;
310 default:
311 gen_error("jvm_generate_store: unknow storage type %i", dst -> storage);
312 break;
316 static void
317 jvm_generate_new(gen_proc_t * p, oberon_type_t * type, int num);
319 /*
320 * Генерирует код для инициализации массива со статическим базовым типом
321 * ( aref -- )
322 */
324 static void
325 jvm_generate_array_initialization(gen_proc_t * p, oberon_type_t * arr)
327 int dim = 0;
328 oberon_type_t * base = arr;
329 while(base -> class == OBERON_TYPE_ARRAY)
331 dim += 1;
332 base = base -> base;
335 if(base -> class != OBERON_TYPE_RECORD)
337 jvm_generate(p, 1, 0, "pop");
338 return;
341 struct {
342 gen_var_t * index;
343 gen_var_t * length;
344 int start;
345 int end;
346 } loop[dim];
348 gen_var_t * dst = oberon_generator_new_var();
349 jvm_generate_and_init_local_var(dst, p, false);
350 jvm_generate_store(p, arr, dst);
352 /* Входящие параметры заграблены.
353 * Теперь генерируем эквивалентный код:
354 * int i = 0;
355 * int len = dst.length
356 * while(i < len)
357 * {
358 * ...
359 * {
360 * dst[i, ...] = new record;
361 * }
362 * ...
363 * i += 1;
364 * }
365 * Где "..." такой же код (начало и конец) для следующей размерности.
366 */
368 for(int i = 0; i < dim; i++)
370 loop[i].index = oberon_generator_new_var();
371 loop[i].length = oberon_generator_new_var();
372 loop[i].start = jvm_new_label_id(p);
373 loop[i].end = jvm_new_label_id(p);
374 jvm_generate_and_init_local_var(loop[i].index, p, false);
375 jvm_generate_and_init_local_var(loop[i].length, p, false);
377 /* TODO преределать через jvm_generate_load{{store}} */
379 jvm_generate(p, 0, 1, "iconst_0");
380 jvm_generate(p, 1, 0, "istore %i", loop[i].index -> reg);
382 jvm_generate_load(p, arr, dst);
383 jvm_generate(p, 1, 1, "arraylength");
384 jvm_generate(p, 1, 0, "istore %i", loop[i].length -> reg);
386 /* if(i >= len) goto end; */
387 jvm_generate_label(p, loop[i].start);
388 jvm_generate(p, 0, 1, "iload %i", loop[i].index -> reg);
389 jvm_generate(p, 0, 1, "iload %i", loop[i].length -> reg);
390 jvm_generate(p, 2, 0, "if_icmpge L%i", loop[i].end);
393 jvm_generate_load(p, arr, dst);
394 jvm_generate(p, 0, 1, "iload %i", loop[0].index -> reg);
395 for(int i = 1; i < dim; i++)
397 jvm_generate(p, 2, 1, "aaload");
398 jvm_generate(p, 0, 1, "iload %i", loop[i].index -> reg);
400 jvm_generate_new(p, base, 0);
401 jvm_generate(p, 3, 0, "aastore");
403 for(int i = dim - 1; i >= 0; i--)
405 jvm_generate(p, 0, 0, "iinc %i 1", loop[i].index -> reg);
406 jvm_generate(p, 0, 0, "goto L%i", loop[i].start);
407 jvm_generate_label(p, loop[i].end);
411 static void
412 jvm_generate_new(gen_proc_t * p, oberon_type_t * type, int num)
414 int dim;
415 char * cname;
416 char * desc;
417 oberon_type_t * base;
419 switch(type -> class)
421 case OBERON_TYPE_INTEGER:
422 case OBERON_TYPE_BOOLEAN:
423 case OBERON_TYPE_PROCEDURE:
424 case OBERON_TYPE_REAL:
425 case OBERON_TYPE_POINTER:
426 gen_error("jvm_generate_new_static: static alocation not allowed");
427 break;
428 case OBERON_TYPE_RECORD:
429 assert(num == 0);
430 cname = jvm_get_class_full_name(type);
431 jvm_generate(p, 0, 1, "new %s", cname);
432 jvm_generate(p, 1, 2, "dup");
433 jvm_generate(p, 1, 0, "invokespecial %s/<init>()V", cname);
434 break;
435 case OBERON_TYPE_ARRAY:
436 dim = 0;
437 base = type;
438 desc = jvm_get_descriptor(type);
439 while(base -> class == OBERON_TYPE_ARRAY)
441 if(num > 0)
443 assert(base -> size == 0);
444 num -= 1;
446 else
448 assert(base -> size > 0);
449 jvm_generate_push_int(p, base -> size);
451 dim += 1;
452 base = base -> base;
455 assert(num == 0);
456 jvm_generate(p, dim, 1, "multianewarray %s %i", desc, dim);
457 jvm_generate(p, 1, 2, "dup");
458 jvm_generate_array_initialization(p, type);
459 break;
460 default:
461 gen_error("jvm_generate_new_static: unk type class %i", type -> class);
462 break;
466 /*
467 * Генерирует код для копирования полей из первой записи во вторую.
468 * ( aref_dst aref_src -- )
469 * dst := src;
470 */
472 static void
473 jvm_generate_copy_record(gen_proc_t * p, oberon_type_t * rec)
475 assert(rec -> class == OBERON_TYPE_RECORD);
476 char * desc = jvm_get_descriptor(rec);
477 char * cname = jvm_get_class_full_name(rec);
478 jvm_generate(p, 1 + 1, 0, "invokestatic %s/$COPY$(%s%s)V", cname, desc, desc);
481 /*
482 * Генерирует кода для копирования массивов.
483 * ( aref_dst aref_src -- )
484 * dst := src;
485 */
487 static void
488 jvm_generate_copy_array(gen_proc_t * p, oberon_type_t * arr)
490 int dim = 0;
491 oberon_type_t * base = arr;
492 while(base -> class == OBERON_TYPE_ARRAY)
494 dim += 1;
495 base = base -> base;
498 struct {
499 gen_var_t * index;
500 gen_var_t * length;
501 int start;
502 int end;
503 } loop[dim];
505 gen_var_t * dst = oberon_generator_new_var();
506 gen_var_t * src = oberon_generator_new_var();
507 jvm_generate_and_init_local_var(dst, p, false);
508 jvm_generate_and_init_local_var(src, p, false);
510 jvm_generate_store(p, arr, src);
511 jvm_generate_store(p, arr, dst);
513 /* Входящие параметры заграблены.
514 * Теперь генерируем эквивалентный код:
515 * int i = 0;
516 * int len = dst.length
517 * while(i < len)
518 * {
519 * ...
520 * {
521 * copy from src[i, ...] to dst[i, ...];
522 * }
523 * ...
524 * i += 1;
525 * }
526 * Где "..." такой же код (начало и конец) для следующей размерности.
527 */
529 for(int i = 0; i < dim; i++)
531 loop[i].index = oberon_generator_new_var();
532 loop[i].length = oberon_generator_new_var();
533 loop[i].start = jvm_new_label_id(p);
534 loop[i].end = jvm_new_label_id(p);
535 jvm_generate_and_init_local_var(loop[i].index, p, false);
536 jvm_generate_and_init_local_var(loop[i].length, p, false);
538 /* TODO преределать через jvm_generate_load{{store}} */
540 jvm_generate(p, 0, 1, "iconst_0");
541 jvm_generate(p, 1, 0, "istore %i", loop[i].index -> reg);
543 jvm_generate_load(p, arr, dst);
544 jvm_generate(p, 1, 1, "arraylength");
545 jvm_generate(p, 1, 0, "istore %i", loop[i].length -> reg);
547 /* if(i >= len) goto end; */
548 jvm_generate_label(p, loop[i].start);
549 jvm_generate(p, 0, 1, "iload %i", loop[i].index -> reg);
550 jvm_generate(p, 0, 1, "iload %i", loop[i].length -> reg);
551 jvm_generate(p, 2, 0, "if_icmpge L%i", loop[i].end);
554 if(base -> class == OBERON_TYPE_ARRAY)
556 // Вся эта шляпа уже должна знать о всех размерностях
557 gen_error("jvm_generate_copy_array: wat");
559 else if(base -> class == OBERON_TYPE_RECORD)
561 /* Получаем записи по индексам ( -- dst src ) */
563 jvm_generate_load(p, arr, dst);
564 for(int i = 0; i < dim; i++)
566 jvm_generate(p, 0, 1, "iload %i", loop[i].index -> reg);
567 jvm_generate(p, 2, 1, "aaload");
570 jvm_generate_load(p, arr, src);
571 for(int i = 0; i < dim; i++)
573 jvm_generate(p, 0, 1, "iload %i", loop[i].index -> reg);
574 jvm_generate(p, 2, 1, "aaload");
577 /* Копируем записи ( dst src -- ) */
578 jvm_generate_copy_record(p, base);
580 else
582 char postfix = jvm_get_postfix(base);
583 int cell_size = jvm_cell_size_for_postfix(postfix);
585 /* Получаем массивы и индексы ( -- dst i src i ) */
587 jvm_generate_load(p, arr, dst);
588 jvm_generate(p, 0, 1, "iload %i", loop[0].index -> reg);
589 for(int i = 1; i < dim; i++)
591 jvm_generate(p, 2, 1, "aaload");
592 jvm_generate(p, 0, 1, "iload %i", loop[i].index -> reg);
595 jvm_generate_load(p, arr, src);
596 jvm_generate(p, 0, 1, "iload %i", loop[0].index -> reg);
597 for(int i = 1; i < dim; i++)
599 jvm_generate(p, 2, 1, "aaload");
600 jvm_generate(p, 0, 1, "iload %i", loop[i].index -> reg);
603 /* Копируем значения ( dst i src i -- ) */
604 jvm_generate(p, 2, cell_size, "%caload", postfix);
605 jvm_generate(p, 2 + cell_size, 0, "%castore", postfix);
608 for(int i = dim - 1; i >= 0; i--)
610 jvm_generate(p, 0, 0, "iinc %i 1", loop[i].index -> reg);
611 jvm_generate(p, 0, 0, "goto L%i", loop[i].start);
612 jvm_generate_label(p, loop[i].end);
616 // ==========================================
617 // ==========================================
618 // ==========================================
620 void
621 oberon_generator_init_context(oberon_context_t * ctx)
623 gen_context_t * gen_context = GC_MALLOC(sizeof *gen_context);
624 memset(gen_context, 0, sizeof *gen_context);
626 ctx -> gen_context = gen_context;
629 void
630 oberon_generator_destroy_context(oberon_context_t * ctx)
634 static void
635 oberon_generate_procedure_class(oberon_type_t * proc)
637 FILE * fp;
638 char * cname;
639 char * signature;
640 struct gen_class * class;
642 cname = jvm_get_class_full_name(proc);
643 class = jvm_create_class(cname);
644 fp = class -> fp;
646 fprintf(fp, ".source SYSTEM\n");
647 fprintf(fp, ".class public abstract %s\n", cname);
648 fprintf(fp, ".super java/lang/Object\n\n");
650 fprintf(fp, ".method public <init>()V\n");
651 fprintf(fp, " aload_0\n");
652 fprintf(fp, " invokespecial java/lang/Object/<init>()V\n");
653 fprintf(fp, " return\n");
654 fprintf(fp, ".end method\n\n");
656 signature = jvm_get_procedure_signature(proc);
658 fprintf(fp, ".method public abstract invoke%s\n", signature);
659 fprintf(fp, ".end method\n\n");
661 jvm_destroy_class(class);
664 static void
665 oberon_generate_record_class(gen_module_t * m, oberon_type_t * rec)
667 char * cname;
668 struct gen_class * class;
670 /* Устанавливаем новоый id */
671 rec -> gen_type -> rec_id = m -> rec_id;
672 m -> rec_id += 1;
674 cname = jvm_get_class_full_name(rec);
675 class = jvm_create_class(cname);
677 fprintf(class -> fp, ".source %s\n", rec -> module -> name);
678 fprintf(class -> fp, ".class public %s\n", cname);
679 fprintf(class -> fp, ".super java/lang/Object\n\n");
681 rec -> gen_type -> class = class;
684 void
685 oberon_generator_init_type(oberon_context_t * ctx, oberon_type_t * type)
687 gen_type_t * t = GC_MALLOC(sizeof *t);
688 memset(t, 0, sizeof *t);
689 type -> gen_type = t;
691 switch(type -> class)
693 case OBERON_TYPE_VOID:
694 case OBERON_TYPE_INTEGER:
695 case OBERON_TYPE_BOOLEAN:
696 case OBERON_TYPE_ARRAY:
697 case OBERON_TYPE_REAL:
698 break;
699 case OBERON_TYPE_RECORD:
701 gen_module_t * m;
702 m = type -> module -> gen_mod;
703 oberon_generate_record_class(m, type);
704 break;
705 case OBERON_TYPE_PROCEDURE:
706 oberon_generate_procedure_class(type);
707 break;
708 case OBERON_TYPE_POINTER:
709 break;
710 default:
711 gen_error("oberon_generator_init_type: unk calss %i", type -> class);
712 break;
716 void
717 oberon_generator_init_record(oberon_context_t * ctx, oberon_type_t * rec)
719 struct gen_class * class;
720 class = rec -> gen_type -> class;
722 int num = rec -> num_decl;
723 oberon_object_t * field = rec -> decl;
724 for(int i = 0; i < num; i++)
726 gen_var_t * v = field -> gen_var;
727 char * name = field -> name;
728 char * desc = jvm_get_descriptor(field -> type);
729 jvm_generate_and_init_field(v, class, "public", name, desc);
730 field = field -> next;
733 /* Стандартный конструктор класса */
734 /* Инициализирует внутренние статические записи и массивы */
735 gen_proc_t * p = jvm_create_proc(class);
736 jvm_generate_function_header(p, "public", "<init>", "()V");
737 jvm_alloc_register_untyped(p -> rf, false);
738 jvm_generate(p, 0, 1, "aload_0");
739 jvm_generate(p, 1, 0, "invokespecial java/lang/Object/<init>()V");
740 num = rec -> num_decl;
741 field = rec -> decl;
742 for(int i = 0; i < num; i++)
744 if(field -> type -> class == OBERON_TYPE_RECORD
745 || field -> type -> class == OBERON_TYPE_ARRAY)
747 jvm_generate(p, 0, 1, "aload_0");
748 jvm_generate_new(p, field -> type, 0);
749 jvm_generate_store(p, field -> type, field -> gen_var);
751 field = field -> next;
753 jvm_generate(p, 0, 0, "return");
754 jvm_generate_function_end(p);
756 /* Метод для копирования полей класса */
757 /* reg0 == src -> reg1 == dst */
758 p = jvm_create_proc(class);
759 gen_var_t * copy_dst = oberon_generator_new_var();
760 gen_var_t * copy_src = oberon_generator_new_var();
761 char * desc = jvm_get_descriptor(rec);
762 char * signature = new_string("(%s%s)V", desc, desc);
763 jvm_generate_function_header(p, "public static", "$COPY$", signature);
764 jvm_generate_and_init_named_local_var(copy_dst, p, false, "dst", desc);
765 jvm_generate_and_init_named_local_var(copy_src, p, false, "src", desc);
766 num = rec -> num_decl;
767 field = rec -> decl;
768 for(int i = 0; i < num; i++)
770 if(field -> type -> class == OBERON_TYPE_RECORD)
772 jvm_generate_load(p, rec, copy_dst);
773 jvm_generate_load(p, field -> type, field -> gen_var);
774 jvm_generate_load(p, rec, copy_src);
775 jvm_generate_load(p, field -> type, field -> gen_var);
776 jvm_generate_copy_record(p, field -> type);
778 else if(field -> type -> class == OBERON_TYPE_ARRAY)
780 jvm_generate_load(p, rec, copy_dst);
781 jvm_generate_load(p, field -> type, field -> gen_var);
782 jvm_generate_load(p, rec, copy_src);
783 jvm_generate_load(p, field -> type, field -> gen_var);
784 jvm_generate_copy_array(p, field -> type);
786 else
788 jvm_generate_load(p, rec, copy_dst);
789 jvm_generate_load(p, rec, copy_src);
790 jvm_generate_load(p, field -> type, field -> gen_var);
791 jvm_generate_store(p, field -> type, field -> gen_var);
793 field = field -> next;
795 jvm_generate(p, 0, 0, "return");
796 jvm_generate_function_end(p);
798 jvm_destroy_class(class);
801 void
802 oberon_generator_init_var(oberon_context_t * ctx, oberon_object_t * var)
804 gen_var_t * v = oberon_generator_new_var();
805 var -> gen_var = v;
807 gen_module_t * m;
808 m = ctx -> mod -> gen_mod;
810 struct gen_class * class;
811 class = m -> class;
813 char * desc;
814 switch(var -> class)
816 case OBERON_CLASS_VAR_PARAM:
817 gen_error("generator: VAR-parameters not implemented");
818 break;
819 case OBERON_CLASS_PARAM:
820 /* Заполняется при генерации функции */
821 /* смотри jvm_init_local_object() */
822 break;
823 case OBERON_CLASS_FIELD:
824 /* Заполняются при инициализации структуры */
825 /* смотри oberon_generator_init_record() */
826 break;
827 case OBERON_CLASS_VAR:
828 /* Локальные заполняются при генерации функции */
829 /* смотри jvm_init_local_object() */
830 if(var -> local == 0)
832 desc = jvm_get_descriptor(var -> type);
833 jvm_generate_and_init_global_var(v, class, "public", var -> name, desc);
835 break;
836 default:
837 gen_error("oberon_generator_init_var: unk var class %i", var -> class);
838 break;
842 void
843 oberon_generator_init_proc(oberon_context_t * ctx, oberon_object_t * proc)
845 struct gen_class * class = proc -> module -> gen_mod -> class;
846 proc -> gen_proc = jvm_create_proc(class);
848 if(proc -> local)
850 gen_error("generator: local procedures not implemented");
854 void
855 oberon_generator_init_module(oberon_context_t * ctx, oberon_module_t * mod)
857 gen_module_t * m = GC_MALLOC(sizeof *m);
858 memset(m, 0, sizeof *m);
859 mod -> gen_mod = m;
861 struct gen_class * class;
862 class = jvm_create_class(mod -> name);
864 fprintf(class -> fp, ".source %s\n", mod -> name);
865 fprintf(class -> fp, ".class %s\n", mod -> name);
866 fprintf(class -> fp, ".super java/lang/Object\n\n");
868 m -> class = class;
870 ctx -> gen_context -> current_m = m;
873 void
874 oberon_generator_fini_module(oberon_module_t * mod)
876 jvm_destroy_class(mod -> gen_mod -> class);
879 static void
880 push_expr(gen_proc_t * p, oberon_expr_t * expr);
882 void
883 oberon_generate_begin_module(oberon_context_t * ctx)
885 struct gen_class * class = ctx -> mod -> gen_mod -> class;
886 gen_proc_t * p = jvm_create_proc(class);
888 jvm_generate_function_header(p, "public", "<init>", "()V");
889 jvm_alloc_register_untyped(p -> rf, false);
890 jvm_generate(p, 0, 1, "aload_0");
891 jvm_generate(p, 1, 0, "invokespecial java/lang/Object/<init>()V");
893 /* Инициализация переменных объявленных в модуле */
894 oberon_object_t * x = ctx -> mod -> decl -> list -> next;
895 while(x != NULL)
897 if(x -> class == OBERON_CLASS_VAR)
899 if(x -> type -> class == OBERON_TYPE_ARRAY
900 || x -> type -> class == OBERON_TYPE_RECORD)
902 jvm_generate_new(p, x -> type, 0);
903 jvm_generate_store(p, x -> type, x -> gen_var);
906 x = x -> next;
910 void
911 oberon_generate_end_module(oberon_context_t * ctx)
913 struct gen_class * class = ctx -> mod -> gen_mod -> class;
914 gen_proc_t * p = class -> p;
916 jvm_generate(p, 0, 0, "return");
917 jvm_generate_function_end(class -> p);
920 static void
921 jvm_init_local_object(gen_proc_t * p, oberon_object_t * x)
923 gen_var_t * v;
924 bool wide;
925 char * desc;
926 struct gen_class * class;
928 v = x -> gen_var;
929 class = p -> class;
930 wide = jvm_is_wide_type(x -> type);
931 desc = jvm_get_descriptor(x -> type);
933 // Убеждаемся что сейчас находимся в функции
934 assert(class -> p);
935 assert(x -> local);
937 switch(x -> class)
939 case OBERON_CLASS_VAR:
940 case OBERON_CLASS_PARAM:
941 jvm_generate_and_init_named_local_var(v, p, wide, x -> name, desc);
942 break;
943 default:
944 gen_error("jvm_init_local_object: wat");
945 break;
949 void
950 oberon_generate_begin_proc(oberon_context_t * ctx, oberon_object_t * proc)
952 gen_proc_t * p;
953 char * signature;
955 p = proc -> gen_proc;
957 signature = jvm_get_procedure_signature(proc -> type);
959 jvm_generate_function_header(p, "public static", proc -> name, signature);
961 oberon_object_t * var = proc -> type -> decl;
962 while(var)
964 jvm_init_local_object(p, var);
965 var = var -> next;
969 void
970 oberon_generate_end_proc(oberon_context_t * ctx)
972 gen_module_t * m;
973 gen_proc_t * p;
975 m = ctx -> mod -> gen_mod;
976 p = m -> class -> p;
978 jvm_generate_function_end(p);
981 static void
982 jvm_generate_call_proc(gen_proc_t * p, oberon_expr_t * desig)
984 assert(desig -> is_item);
985 assert(desig -> item.mode == MODE_CALL);
987 oberon_object_t * proc;
988 char * fullname;
989 char * signature;
991 proc = desig -> item.var;
992 fullname = jvm_get_field_full_name(proc);
993 signature = jvm_get_procedure_signature(proc -> type);
995 int args_cells = 0;
996 int result_cells = jvm_cell_size_for_type(proc -> type -> base);
998 int num = desig -> item.num_args;
999 oberon_expr_t * arg = desig -> item.args;
1000 for(int i = 0; i < num; i++)
1002 args_cells += jvm_cell_size_for_type(arg -> result);
1003 push_expr(p, arg);
1004 arg = arg -> next;
1007 jvm_generate(p, args_cells, result_cells, "invokestatic %s%s", fullname, signature);
1010 void
1011 oberon_generate_call_proc(oberon_context_t * ctx, oberon_expr_t * desig)
1013 jvm_generate_call_proc(ctx -> gen_context -> current_m -> class -> p, desig);
1016 void
1017 oberon_generate_return(oberon_context_t * ctx, oberon_expr_t * expr)
1019 gen_module_t * m;
1020 gen_proc_t * p;
1021 char prefix;
1022 int cell_size;
1024 m = ctx -> mod -> gen_mod;
1025 p = m -> class -> p;
1027 if(expr)
1029 push_expr(p, expr);
1030 prefix = jvm_get_prefix(expr -> result);
1031 cell_size = jvm_cell_size_for_type(expr -> result);
1032 jvm_generate(p, cell_size, 0, "%creturn", prefix);
1034 else
1036 jvm_generate(p, 0, 0, "return");
1040 static void
1041 jvm_generate_expr_new_pointer(gen_proc_t * p, oberon_type_t * type, int num, oberon_expr_t * arg)
1043 assert(type -> class == OBERON_TYPE_POINTER);
1045 for(int i = 0; i < num; i++)
1047 push_expr(p, arg);
1048 arg = arg -> next;
1051 jvm_generate_new(p, type -> base, num);
1054 static void
1055 push_item(gen_proc_t * p, oberon_item_t * item)
1057 switch(item -> mode)
1059 case MODE_VAR:
1060 jvm_generate_load(p, item -> result, item -> var -> gen_var);
1061 break;
1062 case MODE_INTEGER:
1063 jvm_generate_push_int(p, item -> integer);
1064 break;
1065 case MODE_BOOLEAN:
1066 jvm_generate_push_int(p, item -> boolean);
1067 break;
1068 case MODE_CALL:
1069 jvm_generate_call_proc(p, (oberon_expr_t *) item);
1070 break;
1071 case MODE_INDEX:
1073 char postfix = jvm_get_postfix(item -> result);
1074 int cell_size = jvm_cell_size_for_postfix(postfix);
1075 push_item(p, item -> parent);
1076 push_expr(p, item -> args);
1077 jvm_generate(p, 1 + 1, cell_size, "%caload", postfix);
1078 break;
1079 case MODE_FIELD:
1080 push_item(p, item -> parent);
1081 jvm_generate_load(p, item -> result, item -> var -> gen_var);
1082 break;
1083 case MODE_DEREF:
1084 /* Все объекты в jvm представляются как указатели */
1085 push_item(p, item -> parent);
1086 break;
1087 case MODE_NIL:
1088 jvm_generate(p, 0, 1, "aconst_null");
1089 break;
1090 case MODE_NEW:
1091 jvm_generate_expr_new_pointer(p, item -> result, item -> num_args, item -> args);
1092 break;
1093 case MODE_REAL:
1094 jvm_generate_push_float(p, item -> real, item -> result -> size);
1095 break;
1096 default:
1097 gen_error("push_item: unk mode %i", item -> mode);
1098 break;
1102 static void
1103 jvm_generate_logical_not(gen_proc_t * p)
1105 int label_done = jvm_new_label_id(p);
1106 int label_false = jvm_new_label_id(p);
1107 char * label_name_done = jvm_get_label_name(label_done);
1108 char * label_name_false = jvm_get_label_name(label_false);
1110 jvm_generate(p, 1, 0, "ifne %s", label_name_false);
1111 jvm_generate(p, 0, 1, "iconst_1");
1112 jvm_generate(p, 0, 0, "goto %s", label_name_done);
1113 jvm_generate_label(p, label_false);
1114 jvm_generate(p, 0, 1, "iconst_0");
1115 jvm_generate_label(p, label_done);
1118 static void
1119 jvm_generate_abs(gen_proc_t * p, char prefix)
1121 char t = jvm_get_type_of_prefix(prefix);
1122 int cell_size = jvm_cell_size_for_postfix(prefix);
1123 jvm_generate(p, cell_size, cell_size, "invokestatic java/lang/Math/abs(%c)%c", t, t);
1126 static void
1127 jvm_generate_compare_op(gen_proc_t * p, char prefix, int op)
1129 int label_true = jvm_new_label_id(p);
1130 int label_done = jvm_new_label_id(p);
1131 char * label_name_true = jvm_get_label_name(label_true);
1132 char * label_name_done = jvm_get_label_name(label_done);
1133 int cell_size = 2 * jvm_cell_size_for_postfix(prefix);
1135 assert(prefix == 'i' || prefix == 'a');
1137 const char * cmpop = "";
1138 switch(op)
1140 case OP_EQ:
1141 cmpop = "eq";
1142 break;
1143 case OP_NEQ:
1144 cmpop = "ne";
1145 break;
1146 case OP_LSS:
1147 cmpop = "lt";
1148 break;
1149 case OP_LEQ:
1150 cmpop = "le";
1151 break;
1152 case OP_GRT:
1153 cmpop = "gt";
1154 break;
1155 case OP_GEQ:
1156 cmpop = "ge";
1157 break;
1158 default:
1159 gen_error("jvm_generate_compare_op: wat");
1160 break;
1163 jvm_generate(p, cell_size, 0, "if_%ccmp%s %s", prefix, cmpop, label_name_true);
1164 jvm_generate(p, 0, 1, "iconst_0");
1165 jvm_generate(p, 0, 0, "goto %s", label_name_done);
1166 jvm_generate_label(p, label_true);
1167 jvm_generate(p, 0, 1, "iconst_1");
1168 jvm_generate_label(p, label_done);
1171 static void
1172 jvm_generate_operator(gen_proc_t * p, char prefix, int op)
1174 int cell_size = jvm_cell_size_for_postfix(prefix);
1175 switch(op)
1177 case OP_UNARY_MINUS:
1178 jvm_generate(p, cell_size, cell_size, "%cneg", prefix);
1179 break;
1180 case OP_BITWISE_NOT:
1181 jvm_generate_push_int(p, -1);
1182 jvm_generate(p, 2 * cell_size, cell_size, "%cxor", prefix);
1183 break;
1184 case OP_LOGIC_NOT:
1185 jvm_generate_logical_not(p);
1186 break;
1187 case OP_ABS:
1188 jvm_generate_abs(p, prefix);
1189 break;
1191 case OP_ADD:
1192 jvm_generate(p, 2 * cell_size, cell_size, "%cadd", prefix);
1193 break;
1194 case OP_SUB:
1195 jvm_generate(p, 2 * cell_size, cell_size, "%csub", prefix);
1196 break;
1197 case OP_MUL:
1198 jvm_generate(p, 2 * cell_size, cell_size, "%cmul", prefix);
1199 break;
1200 case OP_DIV:
1201 jvm_generate(p, 2 * cell_size, cell_size, "%cdiv", prefix);
1202 break;
1203 case OP_MOD:
1204 jvm_generate(p, 2 * cell_size, cell_size, "%crem", prefix);
1205 break;
1206 case OP_BITWISE_AND:
1207 jvm_generate(p, 2 * cell_size, cell_size, "%cand", prefix);
1208 break;
1209 case OP_BITWISE_XOR:
1210 jvm_generate(p, 2 * cell_size, cell_size, "%cxor", prefix);
1211 break;
1212 case OP_BITWISE_OR:
1213 jvm_generate(p, 2 * cell_size, cell_size, "%cor", prefix);
1214 break;
1216 case OP_EQ:
1217 case OP_NEQ:
1218 case OP_LSS:
1219 case OP_LEQ:
1220 case OP_GRT:
1221 case OP_GEQ:
1222 jvm_generate_compare_op(p, prefix, op);
1223 break;
1224 default:
1225 gen_error("jvm_generate_operator: unk op %i", op);
1226 break;
1227 }
1230 static void
1231 jvm_generate_logical_or(gen_proc_t * p, oberon_expr_t * a, oberon_expr_t * b)
1233 int label_calc_b = jvm_new_label_id(p);
1234 int label_done = jvm_new_label_id(p);
1235 char * label_name_calc_b = jvm_get_label_name(label_calc_b);
1236 char * label_name_done = jvm_get_label_name(label_done);
1238 /* a OR b -- если a, то TRUE, иначе b */
1240 push_expr(p, a);
1241 jvm_generate(p, 1, 0, "ifne %s", label_name_calc_b);
1242 jvm_generate(p, 0, 1, "iconst_1");
1243 jvm_generate(p, 0, 0, "goto %s", label_name_done);
1244 jvm_generate_label(p, label_calc_b);
1245 push_expr(p, b);
1246 jvm_generate_label(p, label_done);
1249 static void
1250 jvm_generate_logical_and(gen_proc_t * p, oberon_expr_t * a, oberon_expr_t * b)
1252 int label_false = jvm_new_label_id(p);
1253 int label_done = jvm_new_label_id(p);
1254 char * label_name_false = jvm_get_label_name(label_false);
1255 char * label_name_done = jvm_get_label_name(label_done);
1257 /* a AND b -- если a, то b, иначе FALSE */
1259 push_expr(p, a);
1260 jvm_generate(p, 1, 0, "ifne %s", label_name_false);
1261 push_expr(p, b);
1262 jvm_generate(p, 0, 0, "goto %s", label_name_done);
1263 jvm_generate_label(p, label_false);
1264 jvm_generate(p, 0, 1, "iconst_0");
1265 jvm_generate_label(p, label_done);
1268 static void
1269 push_operator(gen_proc_t * p, oberon_oper_t * oper)
1271 char prefix = jvm_get_prefix(oper -> result);
1272 int op = oper -> op;
1273 switch(op)
1275 case OP_UNARY_MINUS:
1276 case OP_BITWISE_NOT:
1277 case OP_LOGIC_NOT:
1278 case OP_ABS:
1279 push_expr(p, oper -> left);
1280 jvm_generate_operator(p, prefix, op);
1281 break;
1283 case OP_ADD:
1284 case OP_SUB:
1285 case OP_MUL:
1286 case OP_DIV:
1287 case OP_MOD:
1288 case OP_BITWISE_AND:
1289 case OP_BITWISE_XOR:
1290 case OP_BITWISE_OR:
1292 case OP_EQ:
1293 case OP_NEQ:
1294 case OP_LSS:
1295 case OP_LEQ:
1296 case OP_GRT:
1297 case OP_GEQ:
1298 push_expr(p, oper -> left);
1299 push_expr(p, oper -> right);
1300 jvm_generate_operator(p, prefix, op);
1301 break;
1303 case OP_LOGIC_OR:
1304 jvm_generate_logical_or(p, oper -> left, oper -> right);
1305 break;
1306 case OP_LOGIC_AND:
1307 jvm_generate_logical_and(p, oper -> left, oper -> right);
1308 break;
1309 default:
1310 gen_error("push_oper: unk op %i", op);
1311 break;
1315 static void
1316 push_expr(gen_proc_t * p, oberon_expr_t * expr)
1318 if(expr -> is_item)
1320 push_item(p, (oberon_item_t *) expr);
1322 else
1324 push_operator(p, (oberon_oper_t *) expr);
1328 static void
1329 store_expr(gen_proc_t * p, oberon_expr_t * dst, oberon_expr_t * src)
1331 assert(dst -> is_item);
1332 oberon_item_t * item = (oberon_item_t *) dst;
1334 if(dst -> result -> class == OBERON_TYPE_ARRAY
1335 || src -> result -> class == OBERON_TYPE_ARRAY)
1337 push_expr(p, dst);
1338 push_expr(p, src);
1339 jvm_generate_copy_array(p, dst -> result);
1341 else if(dst -> result -> class == OBERON_TYPE_RECORD
1342 || src -> result -> class == OBERON_TYPE_RECORD)
1344 push_expr(p, dst);
1345 push_expr(p, src);
1346 jvm_generate_copy_record(p, dst -> result);
1348 else switch(item -> mode)
1350 case MODE_VAR:
1351 push_expr(p, src);
1352 jvm_generate_store(p, src -> result, item -> var -> gen_var);
1353 break;
1354 case MODE_INDEX:
1356 char postfix = jvm_get_postfix(src -> result);
1357 int cell_size = jvm_cell_size_for_postfix(postfix);
1358 push_item(p, item -> parent);
1359 push_expr(p, item -> args);
1360 push_expr(p, src);
1361 jvm_generate(p, 1 + 1 + cell_size, 0, "%castore", postfix);
1362 break;
1363 case MODE_FIELD:
1364 push_item(p, item -> parent);
1365 push_expr(p, src);
1366 jvm_generate_store(p, src -> result, item -> var -> gen_var);
1367 break;
1368 default:
1369 gen_error("store_expr: unk mode %i", item -> mode);
1370 break;
1374 void
1375 oberon_generate_assign(oberon_context_t * ctx, oberon_expr_t * src, oberon_expr_t * dst)
1377 gen_module_t * m;
1378 gen_proc_t * p;
1380 m = ctx -> mod -> gen_mod;
1381 p = m -> class -> p;
1383 store_expr(p, dst, src);
1386 void
1387 oberon_generate_code(oberon_context_t * ctx)
1389 printf("generate code\n");
1392 void
1393 oberon_generator_dump(oberon_context_t * ctx, char * path)
1395 printf("jit: dump code\n");
1398 void *
1399 oberon_generator_get_procedure(oberon_context_t * ctx, const char * name)
1401 printf("jit: get pointer to procedure %s\n", name);
1402 return NULL;
1405 void *
1406 oberon_generator_get_var(oberon_context_t * ctx, const char * name)
1408 printf("jit: get pointer to var %s\n", name);
1409 return NULL;