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_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 * Теперь генерируем эквивалентный код:
355 * int i = 0;
356 * int len = dst.length
357 * while(i < len)
358 * {
359 * ...
360 * {
361 * dst[i, ...] = new record;
362 * }
363 * ...
364 * i += 1;
365 * }
366 * Где "..." такой же код (начало и конец) для следующей размерности.
367 */
369 for(int i = 0; i < dim; i++)
371 loop[i].index = oberon_generator_new_var();
372 loop[i].length = oberon_generator_new_var();
373 loop[i].start = jvm_new_label_id(p);
374 loop[i].end = jvm_new_label_id(p);
375 jvm_generate_and_init_local_var(loop[i].index, p, false);
376 jvm_generate_and_init_local_var(loop[i].length, p, false);
378 /* TODO преределать через jvm_generate_load{{store}} */
380 jvm_generate(p, 0, 1, "iconst_0");
381 jvm_generate(p, 1, 0, "istore %i", loop[i].index -> reg);
383 jvm_generate_load(p, arr, dst);
384 jvm_generate(p, 1, 1, "arraylength");
385 jvm_generate(p, 1, 0, "istore %i", loop[i].length -> reg);
387 /* if(i >= len) goto end; */
388 jvm_generate_label(p, loop[i].start);
389 jvm_generate(p, 0, 1, "iload %i", loop[i].index -> reg);
390 jvm_generate(p, 0, 1, "iload %i", loop[i].length -> reg);
391 jvm_generate(p, 2, 0, "if_icmpge L%i", loop[i].end);
394 jvm_generate_load(p, arr, dst);
395 jvm_generate(p, 0, 1, "iload %i", loop[0].index -> reg);
396 for(int i = 1; i < dim; i++)
398 jvm_generate(p, 2, 1, "aaload");
399 jvm_generate(p, 0, 1, "iload %i", loop[i].index -> reg);
401 jvm_generate_new(p, base, 0);
402 jvm_generate(p, 3, 0, "aastore");
404 for(int i = dim - 1; i >= 0; i--)
406 jvm_generate(p, 0, 0, "iinc %i 1", loop[i].index -> reg);
407 jvm_generate(p, 0, 0, "goto L%i", loop[i].start);
408 jvm_generate_label(p, loop[i].end);
412 static void
413 jvm_generate_new(gen_proc_t * p, oberon_type_t * type, int num)
415 int dim;
416 char * cname;
417 char * desc;
418 oberon_type_t * base;
420 switch(type -> class)
422 case OBERON_TYPE_INTEGER:
423 case OBERON_TYPE_BOOLEAN:
424 case OBERON_TYPE_PROCEDURE:
425 case OBERON_TYPE_REAL:
426 case OBERON_TYPE_POINTER:
427 gen_error("jvm_generate_new_static: static alocation not allowed");
428 break;
429 case OBERON_TYPE_RECORD:
430 assert(num == 0);
431 cname = jvm_get_class_full_name(type);
432 jvm_generate(p, 0, 1, "new %s", cname);
433 jvm_generate(p, 1, 2, "dup");
434 jvm_generate(p, 1, 0, "invokespecial %s/<init>()V", cname);
435 break;
436 case OBERON_TYPE_ARRAY:
437 dim = 0;
438 base = type;
439 desc = jvm_get_descriptor(type);
440 while(base -> class == OBERON_TYPE_ARRAY)
442 if(num > 0)
444 assert(base -> size == 0);
445 num -= 1;
447 else
449 assert(base -> size > 0);
450 jvm_generate_push_int(p, base -> size);
452 dim += 1;
453 base = base -> base;
456 assert(num == 0);
457 jvm_generate(p, dim, 1, "multianewarray %s %i", desc, dim);
458 jvm_generate(p, 1, 2, "dup");
459 jvm_generate_array_initialization(p, type);
460 break;
461 default:
462 gen_error("jvm_generate_new_static: unk type class %i", type -> class);
463 break;
467 /*
468 * Генерирует код для копирования полей из первой записи во вторую.
469 * ( aref_dst aref_src -- )
470 * dst := src;
471 */
473 static void
474 jvm_generate_copy_record(gen_proc_t * p, oberon_type_t * rec)
476 assert(rec -> class == OBERON_TYPE_RECORD);
477 char * desc = jvm_get_descriptor(rec);
478 char * cname = jvm_get_class_full_name(rec);
479 jvm_generate(p, 1 + 1, 0, "invokestatic %s/$COPY$(%s%s)V", cname, desc, desc);
482 /*
483 * Генерирует кода для копирования массивов.
484 * ( aref_dst aref_src -- )
485 * dst := src;
486 */
488 static void
489 jvm_generate_copy_array(gen_proc_t * p, oberon_type_t * arr)
491 int dim = 0;
492 oberon_type_t * base = arr;
493 while(base -> class == OBERON_TYPE_ARRAY)
495 dim += 1;
496 base = base -> base;
499 struct {
500 gen_var_t * index;
501 gen_var_t * length;
502 int start;
503 int end;
504 } loop[dim];
506 gen_var_t * dst = oberon_generator_new_var();
507 gen_var_t * src = oberon_generator_new_var();
508 jvm_generate_and_init_local_var(dst, p, false);
509 jvm_generate_and_init_local_var(src, p, false);
511 jvm_generate_store(p, arr, src);
512 jvm_generate_store(p, arr, dst);
514 /*
515 * Входящие параметры заграблены.
516 * Теперь генерируем эквивалентный код:
517 * int i = 0;
518 * int len = dst.length
519 * while(i < len)
520 * {
521 * ...
522 * {
523 * copy from src[i, ...] to dst[i, ...];
524 * }
525 * ...
526 * i += 1;
527 * }
528 * Где "..." такой же код (начало и конец) для следующей размерности.
529 */
531 for(int i = 0; i < dim; i++)
533 loop[i].index = oberon_generator_new_var();
534 loop[i].length = oberon_generator_new_var();
535 loop[i].start = jvm_new_label_id(p);
536 loop[i].end = jvm_new_label_id(p);
537 jvm_generate_and_init_local_var(loop[i].index, p, false);
538 jvm_generate_and_init_local_var(loop[i].length, p, false);
540 /* TODO преределать через jvm_generate_load{{store}} */
542 jvm_generate(p, 0, 1, "iconst_0");
543 jvm_generate(p, 1, 0, "istore %i", loop[i].index -> reg);
545 jvm_generate_load(p, arr, dst);
546 jvm_generate(p, 1, 1, "arraylength");
547 jvm_generate(p, 1, 0, "istore %i", loop[i].length -> reg);
549 /* if(i >= len) goto end; */
550 jvm_generate_label(p, loop[i].start);
551 jvm_generate(p, 0, 1, "iload %i", loop[i].index -> reg);
552 jvm_generate(p, 0, 1, "iload %i", loop[i].length -> reg);
553 jvm_generate(p, 2, 0, "if_icmpge L%i", loop[i].end);
556 if(base -> class == OBERON_TYPE_RECORD)
558 /* Получаем записи по индексам ( -- dst src ) */
560 jvm_generate_load(p, arr, dst);
561 for(int i = 0; i < dim; i++)
563 jvm_generate(p, 0, 1, "iload %i", loop[i].index -> reg);
564 jvm_generate(p, 2, 1, "aaload");
567 jvm_generate_load(p, arr, src);
568 for(int i = 0; i < dim; i++)
570 jvm_generate(p, 0, 1, "iload %i", loop[i].index -> reg);
571 jvm_generate(p, 2, 1, "aaload");
574 /* Копируем записи ( dst src -- ) */
575 jvm_generate_copy_record(p, base);
577 else
579 char postfix = jvm_get_postfix(base);
580 int cell_size = jvm_cell_size_for_postfix(postfix);
582 /* Получаем массивы и индексы ( -- dst i src i ) */
584 jvm_generate_load(p, arr, dst);
585 jvm_generate(p, 0, 1, "iload %i", loop[0].index -> reg);
586 for(int i = 1; i < dim; i++)
588 jvm_generate(p, 2, 1, "aaload");
589 jvm_generate(p, 0, 1, "iload %i", loop[i].index -> reg);
592 jvm_generate_load(p, arr, src);
593 jvm_generate(p, 0, 1, "iload %i", loop[0].index -> reg);
594 for(int i = 1; i < dim; i++)
596 jvm_generate(p, 2, 1, "aaload");
597 jvm_generate(p, 0, 1, "iload %i", loop[i].index -> reg);
600 /* Копируем значения ( dst i src i -- ) */
601 jvm_generate(p, 2, cell_size, "%caload", postfix);
602 jvm_generate(p, 2 + cell_size, 0, "%castore", postfix);
605 for(int i = dim - 1; i >= 0; i--)
607 jvm_generate(p, 0, 0, "iinc %i 1", loop[i].index -> reg);
608 jvm_generate(p, 0, 0, "goto L%i", loop[i].start);
609 jvm_generate_label(p, loop[i].end);
613 static void
614 jvm_generate_push_procedure_pointer(gen_proc_t * p, oberon_object_t * proc)
616 char * full_name = jvm_get_field_full_name_safe(proc);
617 char * desc = jvm_get_descriptor(proc -> type);
618 jvm_generate(p, 0, 1, "getstatic %s/pointer %s", full_name, desc);
621 // ==========================================
622 // ==========================================
623 // ==========================================
625 void
626 oberon_generator_init_context(oberon_context_t * ctx)
628 gen_context_t * gen_context = GC_MALLOC(sizeof *gen_context);
629 memset(gen_context, 0, sizeof *gen_context);
631 ctx -> gen_context = gen_context;
634 void
635 oberon_generator_destroy_context(oberon_context_t * ctx)
639 static void
640 oberon_generate_procedure_class(oberon_type_t * proc)
642 FILE * fp;
643 char * cname;
644 char * signature;
645 struct gen_class * class;
647 cname = jvm_get_class_full_name(proc);
648 class = jvm_create_class(cname);
649 fp = class -> fp;
651 fprintf(fp, ".source SYSTEM\n");
652 fprintf(fp, ".class public abstract %s\n", cname);
653 fprintf(fp, ".super java/lang/Object\n\n");
655 fprintf(fp, ".method <init>()V\n");
656 fprintf(fp, " aload_0\n");
657 fprintf(fp, " invokespecial java/lang/Object/<init>()V\n");
658 fprintf(fp, " return\n");
659 fprintf(fp, ".end method\n\n");
661 signature = jvm_get_procedure_signature(proc);
663 fprintf(fp, ".method public abstract invoke%s\n", signature);
664 fprintf(fp, ".end method\n\n");
666 jvm_destroy_class(class);
669 static void
670 oberon_generate_procedure_pointer_class(oberon_object_t * proc)
672 FILE * fp;
673 char * cname;
674 char * abscname;
675 char * absdesc;
676 char * signature;
677 struct gen_class * class;
679 cname = jvm_get_field_full_name_safe(proc);
680 class = jvm_create_class(cname);
681 abscname = jvm_get_class_full_name(proc -> type);
682 absdesc = jvm_get_descriptor(proc -> type);
683 fp = class -> fp;
685 fprintf(fp, ".source %s\n", proc -> module -> name);
686 fprintf(fp, ".class public %s\n", cname);
687 fprintf(fp, ".super %s\n\n", abscname);
689 fprintf(fp, ".field public static pointer %s\n\n", absdesc);
691 fprintf(fp, ".method <init>()V\n");
692 fprintf(fp, " aload_0\n");
693 fprintf(fp, " invokespecial %s/<init>()V\n", abscname);
694 fprintf(fp, " aload_0\n");
695 fprintf(fp, " putstatic %s/pointer %s\n", cname, absdesc);
696 fprintf(fp, " return\n");
697 fprintf(fp, ".end method\n\n");
699 signature = jvm_get_procedure_signature(proc -> type);
701 gen_proc_t * p;
702 gen_var_t * this_v;
704 p = jvm_create_proc(class);
705 jvm_generate_function_header(p, "public", "invoke", signature);
707 this_v = oberon_generator_new_var();
708 jvm_generate_and_init_local_var(this_v, p, false);
710 gen_var_t * v;
711 int use_size = 0;
712 int num = proc -> type -> num_decl;
713 oberon_object_t * arg = proc -> type -> decl;
714 for(int i = 0; i < num; i++)
716 v = oberon_generator_new_var();
717 bool wide = jvm_is_wide_type(arg -> type);
718 char * desc = jvm_get_descriptor(arg -> type);
719 jvm_generate_and_init_named_local_var(v, p, wide, arg -> name, desc);
721 jvm_generate_load(p, arg -> type, v);
723 use_size += (wide) ? (2) : (1);
725 arg = arg -> next;
728 char * full_name = jvm_get_field_full_name(proc);
729 int cell_size = jvm_cell_size_for_type(proc -> type -> base);
731 jvm_generate(p, use_size, cell_size, "invokestatic %s%s", full_name, signature);
733 if(proc -> type -> base -> class == OBERON_TYPE_VOID)
735 jvm_generate(p, 0, 0, "return");
737 else
739 char prefix = jvm_get_prefix(proc -> type -> base);
740 jvm_generate(p, cell_size, 0, "%creturn", prefix);
743 jvm_generate_function_end(p);
745 jvm_destroy_class(class);
748 static void
749 oberon_generate_record_class(gen_module_t * m, oberon_type_t * rec)
751 char * cname;
752 struct gen_class * class;
754 /* Устанавливаем новоый id */
755 rec -> gen_type -> rec_id = m -> rec_id;
756 m -> rec_id += 1;
758 cname = jvm_get_class_full_name(rec);
759 class = jvm_create_class(cname);
761 fprintf(class -> fp, ".source %s\n", rec -> module -> name);
762 fprintf(class -> fp, ".class public %s\n", cname);
763 fprintf(class -> fp, ".super java/lang/Object\n\n");
765 rec -> gen_type -> class = class;
768 void
769 oberon_generator_init_type(oberon_context_t * ctx, oberon_type_t * type)
771 gen_type_t * t = GC_MALLOC(sizeof *t);
772 memset(t, 0, sizeof *t);
773 type -> gen_type = t;
775 switch(type -> class)
777 case OBERON_TYPE_VOID:
778 case OBERON_TYPE_INTEGER:
779 case OBERON_TYPE_BOOLEAN:
780 case OBERON_TYPE_ARRAY:
781 case OBERON_TYPE_REAL:
782 break;
783 case OBERON_TYPE_RECORD:
785 gen_module_t * m;
786 m = type -> module -> gen_mod;
787 oberon_generate_record_class(m, type);
788 break;
789 case OBERON_TYPE_PROCEDURE:
790 oberon_generate_procedure_class(type);
791 break;
792 case OBERON_TYPE_POINTER:
793 break;
794 default:
795 gen_error("oberon_generator_init_type: unk calss %i", type -> class);
796 break;
800 void
801 oberon_generator_init_record(oberon_context_t * ctx, oberon_type_t * rec)
803 struct gen_class * class;
804 class = rec -> gen_type -> class;
806 int num = rec -> num_decl;
807 oberon_object_t * field = rec -> decl;
808 for(int i = 0; i < num; i++)
810 gen_var_t * v = field -> gen_var;
811 char * name = field -> name;
812 char * desc = jvm_get_descriptor(field -> type);
813 jvm_generate_and_init_field(v, class, "public", name, desc);
814 field = field -> next;
817 /* Стандартный конструктор класса */
818 /* Инициализирует внутренние статические записи и массивы */
819 gen_proc_t * p = jvm_create_proc(class);
820 jvm_generate_function_header(p, "public", "<init>", "()V");
821 jvm_alloc_register_untyped(p -> rf, false);
822 jvm_generate(p, 0, 1, "aload_0");
823 jvm_generate(p, 1, 0, "invokespecial java/lang/Object/<init>()V");
824 num = rec -> num_decl;
825 field = rec -> decl;
826 for(int i = 0; i < num; i++)
828 if(field -> type -> class == OBERON_TYPE_RECORD
829 || field -> type -> class == OBERON_TYPE_ARRAY)
831 jvm_generate(p, 0, 1, "aload_0");
832 jvm_generate_new(p, field -> type, 0);
833 jvm_generate_store(p, field -> type, field -> gen_var);
835 field = field -> next;
837 jvm_generate(p, 0, 0, "return");
838 jvm_generate_function_end(p);
840 /* Метод для копирования полей класса */
841 /* reg0 == src -> reg1 == dst */
842 p = jvm_create_proc(class);
843 gen_var_t * copy_dst = oberon_generator_new_var();
844 gen_var_t * copy_src = oberon_generator_new_var();
845 char * desc = jvm_get_descriptor(rec);
846 char * signature = new_string("(%s%s)V", desc, desc);
847 jvm_generate_function_header(p, "public static", "$COPY$", signature);
848 jvm_generate_and_init_named_local_var(copy_dst, p, false, "dst", desc);
849 jvm_generate_and_init_named_local_var(copy_src, p, false, "src", desc);
850 num = rec -> num_decl;
851 field = rec -> decl;
852 for(int i = 0; i < num; i++)
854 if(field -> type -> class == OBERON_TYPE_RECORD)
856 jvm_generate_load(p, rec, copy_dst);
857 jvm_generate_load(p, field -> type, field -> gen_var);
858 jvm_generate_load(p, rec, copy_src);
859 jvm_generate_load(p, field -> type, field -> gen_var);
860 jvm_generate_copy_record(p, field -> type);
862 else if(field -> type -> class == OBERON_TYPE_ARRAY)
864 jvm_generate_load(p, rec, copy_dst);
865 jvm_generate_load(p, field -> type, field -> gen_var);
866 jvm_generate_load(p, rec, copy_src);
867 jvm_generate_load(p, field -> type, field -> gen_var);
868 jvm_generate_copy_array(p, field -> type);
870 else
872 jvm_generate_load(p, rec, copy_dst);
873 jvm_generate_load(p, rec, copy_src);
874 jvm_generate_load(p, field -> type, field -> gen_var);
875 jvm_generate_store(p, field -> type, field -> gen_var);
877 field = field -> next;
879 jvm_generate(p, 0, 0, "return");
880 jvm_generate_function_end(p);
882 jvm_destroy_class(class);
885 void
886 oberon_generator_init_var(oberon_context_t * ctx, oberon_object_t * var)
888 gen_var_t * v = oberon_generator_new_var();
889 var -> gen_var = v;
891 gen_module_t * m;
892 m = ctx -> mod -> gen_mod;
894 struct gen_class * class;
895 class = m -> class;
897 char * desc;
898 switch(var -> class)
900 case OBERON_CLASS_VAR_PARAM:
901 gen_error("generator: VAR-parameters not implemented");
902 break;
903 case OBERON_CLASS_PARAM:
904 /* Заполняется при генерации функции */
905 /* смотри jvm_init_local_object() */
906 break;
907 case OBERON_CLASS_FIELD:
908 /* Заполняются при инициализации структуры */
909 /* смотри oberon_generator_init_record() */
910 break;
911 case OBERON_CLASS_VAR:
912 /* Локальные заполняются при генерации функции */
913 /* смотри jvm_init_local_object() */
914 if(var -> local == 0)
916 desc = jvm_get_descriptor(var -> type);
917 jvm_generate_and_init_global_var(v, class, "public", var -> name, desc);
919 break;
920 default:
921 gen_error("oberon_generator_init_var: unk var class %i", var -> class);
922 break;
926 void
927 oberon_generator_init_proc(oberon_context_t * ctx, oberon_object_t * proc)
929 struct gen_class * class = proc -> module -> gen_mod -> class;
930 proc -> gen_proc = jvm_create_proc(class);
932 if(proc -> local)
934 gen_error("generator: local procedures not implemented");
937 oberon_generate_procedure_pointer_class(proc);
940 void
941 oberon_generator_init_module(oberon_context_t * ctx, oberon_module_t * mod)
943 gen_module_t * m = GC_MALLOC(sizeof *m);
944 memset(m, 0, sizeof *m);
945 mod -> gen_mod = m;
947 struct gen_class * class;
948 class = jvm_create_class(mod -> name);
950 fprintf(class -> fp, ".source %s\n", mod -> name);
951 fprintf(class -> fp, ".class %s\n", mod -> name);
952 fprintf(class -> fp, ".super java/lang/Object\n\n");
954 m -> class = class;
956 ctx -> gen_context -> current_m = m;
959 void
960 oberon_generator_fini_module(oberon_module_t * mod)
962 jvm_destroy_class(mod -> gen_mod -> class);
965 static void
966 push_expr(gen_proc_t * p, oberon_expr_t * expr);
968 void
969 oberon_generate_begin_module(oberon_context_t * ctx)
971 struct gen_class * class = ctx -> mod -> gen_mod -> class;
972 gen_proc_t * p = jvm_create_proc(class);
974 jvm_generate_function_header(p, "public", "<init>", "()V");
975 jvm_alloc_register_untyped(p -> rf, false);
976 jvm_generate(p, 0, 1, "aload_0");
977 jvm_generate(p, 1, 0, "invokespecial java/lang/Object/<init>()V");
979 /* Инициализация переменных объявленных в модуле */
980 oberon_object_t * x = ctx -> mod -> decl -> list -> next;
981 while(x != NULL)
983 if(x -> class == OBERON_CLASS_VAR)
985 if(x -> type -> class == OBERON_TYPE_ARRAY
986 || x -> type -> class == OBERON_TYPE_RECORD)
988 jvm_generate_new(p, x -> type, 0);
989 jvm_generate_store(p, x -> type, x -> gen_var);
992 else if(x -> class == OBERON_CLASS_PROC)
994 char * cname = jvm_get_field_full_name_safe(x);
995 jvm_generate(p, 0, 1, "new %s", cname);
996 jvm_generate(p, 1, 0, "invokespecial %s/<init>()V", cname);
999 x = x -> next;
1003 void
1004 oberon_generate_end_module(oberon_context_t * ctx)
1006 struct gen_class * class = ctx -> mod -> gen_mod -> class;
1007 gen_proc_t * p = class -> p;
1009 jvm_generate(p, 0, 0, "return");
1010 jvm_generate_function_end(class -> p);
1013 static void
1014 jvm_init_local_object(gen_proc_t * p, oberon_object_t * x)
1016 gen_var_t * v;
1017 bool wide;
1018 char * desc;
1019 struct gen_class * class;
1021 v = x -> gen_var;
1022 class = p -> class;
1023 wide = jvm_is_wide_type(x -> type);
1024 desc = jvm_get_descriptor(x -> type);
1026 // Убеждаемся что сейчас находимся в функции
1027 assert(class -> p);
1028 assert(x -> local);
1030 switch(x -> class)
1032 case OBERON_CLASS_VAR:
1033 case OBERON_CLASS_PARAM:
1034 jvm_generate_and_init_named_local_var(v, p, wide, x -> name, desc);
1035 break;
1036 default:
1037 gen_error("jvm_init_local_object: wat");
1038 break;
1042 /*
1043 * Генерирует код для получения размера измерения массива
1044 * Аналог Обероновского LEN(v, n); где n = 0 - первое измерение.
1045 * ( aref -- int )
1046 */
1048 static void
1049 jvm_generate_array_len(gen_proc_t * p, int dim)
1051 while(dim > 0)
1053 jvm_generate(p, 0, 1, "iconst_0");
1054 jvm_generate(p, 2, 1, "aaload");
1055 dim -= 1;
1057 jvm_generate(p, 1, 1, "arraylength");
1060 static void
1061 jvm_generate_array_duplicate_and_replace(gen_proc_t * p, gen_var_t * v, oberon_type_t * arr)
1063 int dim = 0;
1064 oberon_type_t * base = arr;
1065 while(base -> class == OBERON_TYPE_ARRAY)
1067 if(base -> size == 0)
1069 jvm_generate_load(p, arr, v);
1070 jvm_generate_array_len(p, dim);
1071 dim += 1;
1073 base = base -> base;
1076 jvm_generate_new(p, arr, dim);
1077 jvm_generate(p, 1, 2, "dup");
1078 jvm_generate_load(p, arr, v);
1079 jvm_generate_copy_array(p, arr);
1080 jvm_generate_store(p, arr, v);
1083 static void
1084 jvm_generate_record_duplicate_and_replace(gen_proc_t * p, gen_var_t * v, oberon_type_t * rec)
1086 jvm_generate_new(p, rec, 0);
1087 jvm_generate(p, 1, 2, "dup");
1088 jvm_generate_load(p, rec, v);
1089 jvm_generate_copy_record(p, rec);
1090 jvm_generate_store(p, rec, v);
1093 void
1094 oberon_generate_begin_proc(oberon_context_t * ctx, oberon_object_t * proc)
1096 gen_proc_t * p;
1097 char * signature;
1099 p = proc -> gen_proc;
1101 signature = jvm_get_procedure_signature(proc -> type);
1102 jvm_generate_function_header(p, "public static", proc -> name, signature);
1104 /* Выделение регистров под параметры и переменные */
1105 oberon_object_t * var = proc -> type -> decl;
1106 while(var)
1108 jvm_init_local_object(p, var);
1109 var = var -> next;
1112 /* Копирование статических/открытых массивов и записей */
1113 var = proc -> type -> decl;
1114 while(var)
1116 if(var -> class == OBERON_CLASS_PARAM || var -> class == OBERON_CLASS_VAR_PARAM)
1118 if(var -> type -> class == OBERON_TYPE_ARRAY)
1120 jvm_generate_array_duplicate_and_replace(p, var -> gen_var, var -> type);
1122 else if(var -> type -> class == OBERON_TYPE_RECORD)
1123 {
1124 jvm_generate_record_duplicate_and_replace(p, var -> gen_var, var -> type);
1127 var = var -> next;
1128 }
1131 void
1132 oberon_generate_end_proc(oberon_context_t * ctx)
1134 gen_module_t * m;
1135 gen_proc_t * p;
1137 m = ctx -> mod -> gen_mod;
1138 p = m -> class -> p;
1140 jvm_generate_function_end(p);
1143 static void
1144 jvm_generate_call_proc(gen_proc_t * p, oberon_expr_t * desig)
1146 assert(desig -> is_item);
1147 assert(desig -> item.mode == MODE_CALL);
1149 oberon_object_t * proc;
1150 char * fullname;
1151 char * signature;
1153 proc = desig -> item.var;
1154 fullname = jvm_get_field_full_name(proc);
1155 signature = jvm_get_procedure_signature(proc -> type);
1157 if(proc -> class != OBERON_CLASS_PROC)
1159 /* Загружаем указатель на процедуру */
1160 jvm_generate_load(p, proc -> type, proc -> gen_var);
1163 int args_cells = 0;
1164 int result_cells = jvm_cell_size_for_type(proc -> type -> base);
1166 int num = desig -> item.num_args;
1167 oberon_expr_t * arg = desig -> item.args;
1168 for(int i = 0; i < num; i++)
1170 args_cells += jvm_cell_size_for_type(arg -> result);
1171 push_expr(p, arg);
1172 arg = arg -> next;
1175 if(proc -> class == OBERON_CLASS_PROC)
1177 /* Обычная статическая процедура */
1178 jvm_generate(p, args_cells, result_cells, "invokestatic %s%s", fullname, signature);
1180 else
1182 /* Процедура-переменная */
1183 char * class = jvm_get_class_full_name(proc -> type);
1184 jvm_generate(p, 1 + args_cells, result_cells, "invokevirtual %s/invoke%s", class, signature);
1188 void
1189 oberon_generate_call_proc(oberon_context_t * ctx, oberon_expr_t * desig)
1191 jvm_generate_call_proc(ctx -> gen_context -> current_m -> class -> p, desig);
1194 void
1195 oberon_generate_return(oberon_context_t * ctx, oberon_expr_t * expr)
1197 gen_module_t * m;
1198 gen_proc_t * p;
1199 char prefix;
1200 int cell_size;
1202 m = ctx -> mod -> gen_mod;
1203 p = m -> class -> p;
1205 if(expr)
1207 push_expr(p, expr);
1208 prefix = jvm_get_prefix(expr -> result);
1209 cell_size = jvm_cell_size_for_type(expr -> result);
1210 jvm_generate(p, cell_size, 0, "%creturn", prefix);
1212 else
1214 jvm_generate(p, 0, 0, "return");
1218 static void
1219 jvm_generate_expr_new_pointer(gen_proc_t * p, oberon_type_t * type, int num, oberon_expr_t * arg)
1221 assert(type -> class == OBERON_TYPE_POINTER);
1223 for(int i = 0; i < num; i++)
1225 push_expr(p, arg);
1226 arg = arg -> next;
1229 jvm_generate_new(p, type -> base, num);
1232 static void
1233 push_item(gen_proc_t * p, oberon_item_t * item)
1235 switch(item -> mode)
1237 case MODE_VAR:
1238 if(item -> var -> class == OBERON_CLASS_PROC)
1240 jvm_generate_push_procedure_pointer(p, item -> var);
1242 else
1244 jvm_generate_load(p, item -> result, item -> var -> gen_var);
1246 break;
1247 case MODE_INTEGER:
1248 jvm_generate_push_int(p, item -> integer);
1249 break;
1250 case MODE_BOOLEAN:
1251 jvm_generate_push_int(p, item -> boolean);
1252 break;
1253 case MODE_CALL:
1254 jvm_generate_call_proc(p, (oberon_expr_t *) item);
1255 break;
1256 case MODE_INDEX:
1258 char postfix = jvm_get_postfix(item -> result);
1259 int cell_size = jvm_cell_size_for_postfix(postfix);
1260 push_item(p, item -> parent);
1261 push_expr(p, item -> args);
1262 jvm_generate(p, 1 + 1, cell_size, "%caload", postfix);
1263 break;
1264 case MODE_FIELD:
1265 push_item(p, item -> parent);
1266 jvm_generate_load(p, item -> result, item -> var -> gen_var);
1267 break;
1268 case MODE_DEREF:
1269 /* Все объекты в jvm представляются как указатели */
1270 push_item(p, item -> parent);
1271 break;
1272 case MODE_NIL:
1273 jvm_generate(p, 0, 1, "aconst_null");
1274 break;
1275 case MODE_NEW:
1276 jvm_generate_expr_new_pointer(p, item -> result, item -> num_args, item -> args);
1277 break;
1278 case MODE_REAL:
1279 jvm_generate_push_float(p, item -> real, item -> result -> size);
1280 break;
1281 default:
1282 gen_error("push_item: unk mode %i", item -> mode);
1283 break;
1287 static void
1288 jvm_generate_logical_not(gen_proc_t * p)
1290 int label_done = jvm_new_label_id(p);
1291 int label_false = jvm_new_label_id(p);
1292 char * label_name_done = jvm_get_label_name(label_done);
1293 char * label_name_false = jvm_get_label_name(label_false);
1295 jvm_generate(p, 1, 0, "ifne %s", label_name_false);
1296 jvm_generate(p, 0, 1, "iconst_1");
1297 jvm_generate(p, 0, 0, "goto %s", label_name_done);
1298 jvm_generate_label(p, label_false);
1299 jvm_generate(p, 0, 1, "iconst_0");
1300 jvm_generate_label(p, label_done);
1303 static void
1304 jvm_generate_abs(gen_proc_t * p, char prefix)
1306 char t = jvm_get_type_of_prefix(prefix);
1307 int cell_size = jvm_cell_size_for_postfix(prefix);
1308 jvm_generate(p, cell_size, cell_size, "invokestatic java/lang/Math/abs(%c)%c", t, t);
1311 static void
1312 jvm_generate_compare_op(gen_proc_t * p, char prefix, int op)
1314 int label_true = jvm_new_label_id(p);
1315 int label_done = jvm_new_label_id(p);
1316 char * label_name_true = jvm_get_label_name(label_true);
1317 char * label_name_done = jvm_get_label_name(label_done);
1318 int cell_size = 2 * jvm_cell_size_for_postfix(prefix);
1320 assert(prefix == 'i' || prefix == 'a');
1322 const char * cmpop = "";
1323 switch(op)
1325 case OP_EQ:
1326 cmpop = "eq";
1327 break;
1328 case OP_NEQ:
1329 cmpop = "ne";
1330 break;
1331 case OP_LSS:
1332 cmpop = "lt";
1333 break;
1334 case OP_LEQ:
1335 cmpop = "le";
1336 break;
1337 case OP_GRT:
1338 cmpop = "gt";
1339 break;
1340 case OP_GEQ:
1341 cmpop = "ge";
1342 break;
1343 default:
1344 gen_error("jvm_generate_compare_op: wat");
1345 break;
1348 jvm_generate(p, cell_size, 0, "if_%ccmp%s %s", prefix, cmpop, label_name_true);
1349 jvm_generate(p, 0, 1, "iconst_0");
1350 jvm_generate(p, 0, 0, "goto %s", label_name_done);
1351 jvm_generate_label(p, label_true);
1352 jvm_generate(p, 0, 1, "iconst_1");
1353 jvm_generate_label(p, label_done);
1356 static void
1357 jvm_generate_operator(gen_proc_t * p, char prefix, int op)
1359 int cell_size = jvm_cell_size_for_postfix(prefix);
1360 switch(op)
1362 case OP_UNARY_MINUS:
1363 jvm_generate(p, cell_size, cell_size, "%cneg", prefix);
1364 break;
1365 case OP_BITWISE_NOT:
1366 jvm_generate_push_int(p, -1);
1367 jvm_generate(p, 2 * cell_size, cell_size, "%cxor", prefix);
1368 break;
1369 case OP_LOGIC_NOT:
1370 jvm_generate_logical_not(p);
1371 break;
1372 case OP_ABS:
1373 jvm_generate_abs(p, prefix);
1374 break;
1376 case OP_ADD:
1377 jvm_generate(p, 2 * cell_size, cell_size, "%cadd", prefix);
1378 break;
1379 case OP_SUB:
1380 jvm_generate(p, 2 * cell_size, cell_size, "%csub", prefix);
1381 break;
1382 case OP_MUL:
1383 jvm_generate(p, 2 * cell_size, cell_size, "%cmul", prefix);
1384 break;
1385 case OP_DIV:
1386 jvm_generate(p, 2 * cell_size, cell_size, "%cdiv", prefix);
1387 break;
1388 case OP_MOD:
1389 jvm_generate(p, 2 * cell_size, cell_size, "%crem", prefix);
1390 break;
1391 case OP_BITWISE_AND:
1392 jvm_generate(p, 2 * cell_size, cell_size, "%cand", prefix);
1393 break;
1394 case OP_BITWISE_XOR:
1395 jvm_generate(p, 2 * cell_size, cell_size, "%cxor", prefix);
1396 break;
1397 case OP_BITWISE_OR:
1398 jvm_generate(p, 2 * cell_size, cell_size, "%cor", prefix);
1399 break;
1401 case OP_EQ:
1402 case OP_NEQ:
1403 case OP_LSS:
1404 case OP_LEQ:
1405 case OP_GRT:
1406 case OP_GEQ:
1407 jvm_generate_compare_op(p, prefix, op);
1408 break;
1409 default:
1410 gen_error("jvm_generate_operator: unk op %i", op);
1411 break;
1412 }
1415 static void
1416 jvm_generate_logical_or(gen_proc_t * p, oberon_expr_t * a, oberon_expr_t * b)
1418 int label_calc_b = jvm_new_label_id(p);
1419 int label_done = jvm_new_label_id(p);
1420 char * label_name_calc_b = jvm_get_label_name(label_calc_b);
1421 char * label_name_done = jvm_get_label_name(label_done);
1423 /* a OR b -- если a, то TRUE, иначе b */
1425 push_expr(p, a);
1426 jvm_generate(p, 1, 0, "ifne %s", label_name_calc_b);
1427 jvm_generate(p, 0, 1, "iconst_1");
1428 jvm_generate(p, 0, 0, "goto %s", label_name_done);
1429 jvm_generate_label(p, label_calc_b);
1430 push_expr(p, b);
1431 jvm_generate_label(p, label_done);
1434 static void
1435 jvm_generate_logical_and(gen_proc_t * p, oberon_expr_t * a, oberon_expr_t * b)
1437 int label_false = jvm_new_label_id(p);
1438 int label_done = jvm_new_label_id(p);
1439 char * label_name_false = jvm_get_label_name(label_false);
1440 char * label_name_done = jvm_get_label_name(label_done);
1442 /* a AND b -- если a, то b, иначе FALSE */
1444 push_expr(p, a);
1445 jvm_generate(p, 1, 0, "ifne %s", label_name_false);
1446 push_expr(p, b);
1447 jvm_generate(p, 0, 0, "goto %s", label_name_done);
1448 jvm_generate_label(p, label_false);
1449 jvm_generate(p, 0, 1, "iconst_0");
1450 jvm_generate_label(p, label_done);
1453 static void
1454 push_operator(gen_proc_t * p, oberon_oper_t * oper)
1456 char prefix = jvm_get_prefix(oper -> result);
1457 int op = oper -> op;
1458 switch(op)
1460 case OP_UNARY_MINUS:
1461 case OP_BITWISE_NOT:
1462 case OP_LOGIC_NOT:
1463 case OP_ABS:
1464 push_expr(p, oper -> left);
1465 jvm_generate_operator(p, prefix, op);
1466 break;
1468 case OP_ADD:
1469 case OP_SUB:
1470 case OP_MUL:
1471 case OP_DIV:
1472 case OP_MOD:
1473 case OP_BITWISE_AND:
1474 case OP_BITWISE_XOR:
1475 case OP_BITWISE_OR:
1477 case OP_EQ:
1478 case OP_NEQ:
1479 case OP_LSS:
1480 case OP_LEQ:
1481 case OP_GRT:
1482 case OP_GEQ:
1483 push_expr(p, oper -> left);
1484 push_expr(p, oper -> right);
1485 jvm_generate_operator(p, prefix, op);
1486 break;
1488 case OP_LOGIC_OR:
1489 jvm_generate_logical_or(p, oper -> left, oper -> right);
1490 break;
1491 case OP_LOGIC_AND:
1492 jvm_generate_logical_and(p, oper -> left, oper -> right);
1493 break;
1494 default:
1495 gen_error("push_oper: unk op %i", op);
1496 break;
1500 static void
1501 push_expr(gen_proc_t * p, oberon_expr_t * expr)
1503 if(expr -> is_item)
1505 push_item(p, (oberon_item_t *) expr);
1507 else
1509 push_operator(p, (oberon_oper_t *) expr);
1513 static void
1514 store_expr(gen_proc_t * p, oberon_expr_t * dst, oberon_expr_t * src)
1516 assert(dst -> is_item);
1517 oberon_item_t * item = (oberon_item_t *) dst;
1519 if(dst -> result -> class == OBERON_TYPE_ARRAY
1520 || src -> result -> class == OBERON_TYPE_ARRAY)
1522 push_expr(p, dst);
1523 push_expr(p, src);
1524 jvm_generate_copy_array(p, dst -> result);
1526 else if(dst -> result -> class == OBERON_TYPE_RECORD
1527 || src -> result -> class == OBERON_TYPE_RECORD)
1529 push_expr(p, dst);
1530 push_expr(p, src);
1531 jvm_generate_copy_record(p, dst -> result);
1533 else switch(item -> mode)
1535 case MODE_VAR:
1536 push_expr(p, src);
1537 jvm_generate_store(p, src -> result, item -> var -> gen_var);
1538 break;
1539 case MODE_INDEX:
1541 char postfix = jvm_get_postfix(src -> result);
1542 int cell_size = jvm_cell_size_for_postfix(postfix);
1543 push_item(p, item -> parent);
1544 push_expr(p, item -> args);
1545 push_expr(p, src);
1546 jvm_generate(p, 1 + 1 + cell_size, 0, "%castore", postfix);
1547 break;
1548 case MODE_FIELD:
1549 push_item(p, item -> parent);
1550 push_expr(p, src);
1551 jvm_generate_store(p, src -> result, item -> var -> gen_var);
1552 break;
1553 default:
1554 gen_error("store_expr: unk mode %i", item -> mode);
1555 break;
1559 void
1560 oberon_generate_assign(oberon_context_t * ctx, oberon_expr_t * src, oberon_expr_t * dst)
1562 gen_module_t * m;
1563 gen_proc_t * p;
1565 m = ctx -> mod -> gen_mod;
1566 p = m -> class -> p;
1568 store_expr(p, dst, src);
1571 void
1572 oberon_generate_code(oberon_context_t * ctx)
1574 printf("generate code\n");
1577 void
1578 oberon_generator_dump(oberon_context_t * ctx, char * path)
1580 printf("jit: dump code\n");
1583 void *
1584 oberon_generator_get_procedure(oberon_context_t * ctx, const char * name)
1586 printf("jit: get pointer to procedure %s\n", name);
1587 return NULL;
1590 void *
1591 oberon_generator_get_var(oberon_context_t * ctx, const char * name)
1593 printf("jit: get pointer to var %s\n", name);
1594 return NULL;