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 }
53 void
54 jvm_generate_function_end(gen_proc_t * p)
55 {
56 struct gen_class * class;
57 class = p -> class;
59 assert(class -> p);
60 class -> p = NULL;
62 fprintf(class -> fp, " .limit stack %i\n", p -> stack -> max_pointer);
63 fprintf(class -> fp, " .limit locals %i\n", p -> rf -> max_used);
64 fprintf(class -> fp, ".end method\n\n");
65 }
67 struct gen_class *
68 jvm_create_class(char * full_name)
69 {
70 struct gen_class * class = GC_MALLOC(sizeof *class);
71 memset(class, 0, sizeof *class);
73 char * fname = new_string("%s.j", full_name);
74 class -> fp = fopen(fname, "w");
75 assert(class -> fp);
77 return class;
78 }
80 static void
81 jvm_destroy_class(struct gen_class * class)
82 {
83 assert(class -> p == NULL);
84 fclose(class -> fp);
85 }
87 static void
88 jvm_generate_field(struct gen_class * class, char * access, char * name, char * desc)
89 {
90 assert(class -> p == NULL);
91 fprintf(class -> fp, ".field %s %s %s\n\n", access, name, desc);
92 }
94 static void
95 jvm_stack_push(gen_proc_t * p, unsigned size)
96 {
97 p -> stack -> pointer += size;
98 if(p -> stack -> pointer > p -> stack -> max_pointer)
99 {
100 p -> stack -> max_pointer = p -> stack -> pointer;
104 static void
105 jvm_stack_pop(gen_proc_t * p, unsigned size)
107 p -> stack -> pointer -= size;
108 assert(p -> stack -> pointer >= 0);
111 static void
112 jvm_generate(gen_proc_t * p, unsigned get, unsigned push, char * format, ...)
114 va_list ptr;
115 va_start(ptr, format);
117 jvm_stack_pop(p, get);
118 fprintf(p -> class -> fp, " ");
119 vfprintf(p -> class -> fp, format, ptr);
120 fprintf(p -> class -> fp, "\n");
121 jvm_stack_push(p, push);
123 va_end(ptr);
126 static void
127 jvm_generate_push_int(gen_proc_t * p, int64_t i)
129 if(i == -1)
131 jvm_generate(p, 0, 1, "iconst_m1");
133 else if(i >= 0 && i <= 5)
135 jvm_generate(p, 0, 1, "iconst_%li", i);
137 else if(i >= -128 && i <= 127)
139 jvm_generate(p, 0, 1, "bipush %li", i);
141 else if(i >= -32768 && i <= 32767)
143 jvm_generate(p, 0, 1, "sipush %li", i);
145 else if(i >= -2147483648 && i <= 2147483647)
147 jvm_generate(p, 0, 1, "ldc %li", i);
149 else
151 jvm_generate(p, 0, 2, "ldc2 %li", i);
155 static void
156 jvm_generate_push_float(gen_proc_t * p, double f, int size)
158 if(size <= 4)
160 if(f == 0.0)
162 jvm_generate(p, 0, 1, "fconst_0");
164 if(f == 1.0)
166 jvm_generate(p, 0, 1, "fconst_1");
168 if(f == 2.0)
170 jvm_generate(p, 0, 1, "fconst_2");
172 else
174 jvm_generate(p, 0, 1, "ldc %lf", f);
177 else
179 if(f == 0.0)
181 jvm_generate(p, 0, 2, "dconst_0");
183 if(f == 1.0)
185 jvm_generate(p, 0, 2, "dconst_1");
187 else
189 jvm_generate(p, 0, 2, "ldc2 %lf", f);
194 static int
195 jvm_new_label_id(gen_proc_t * p)
197 int label_id = p -> label_id;
198 p -> label_id += 1;
199 return label_id;
202 static char *
203 jvm_get_label_name(int label_id)
205 return new_string("L%i", label_id);
208 static void
209 jvm_generate_label(gen_proc_t * p, int label_id)
211 jvm_generate(p, 0, 0, "L%i:", label_id);
214 // ==========================================
215 // ==========================================
216 // ==========================================
218 void
219 oberon_generator_init_context(oberon_context_t * ctx)
221 gen_context_t * gen_context = GC_MALLOC(sizeof *gen_context);
222 memset(gen_context, 0, sizeof *gen_context);
224 ctx -> gen_context = gen_context;
227 void
228 oberon_generator_destroy_context(oberon_context_t * ctx)
232 static void
233 oberon_generate_procedure_class(oberon_type_t * proc)
235 FILE * fp;
236 char * cname;
237 char * signature;
238 struct gen_class * class;
240 cname = jvm_get_class_full_name(proc);
241 class = jvm_create_class(cname);
242 fp = class -> fp;
244 fprintf(fp, ".source SYSTEM\n");
245 fprintf(fp, ".class public abstract %s\n", cname);
246 fprintf(fp, ".super java/lang/Object\n\n");
248 fprintf(fp, ".method public <init>()V\n");
249 fprintf(fp, " aload_0\n");
250 fprintf(fp, " invokespecial java/lang/Object/<init>()V\n");
251 fprintf(fp, " return\n");
252 fprintf(fp, ".end method\n\n");
254 signature = jvm_get_procedure_signature(proc);
256 fprintf(fp, ".method public abstract invoke%s\n", signature);
257 fprintf(fp, ".end method\n\n");
259 jvm_destroy_class(class);
262 static void
263 oberon_generate_record_class(gen_module_t * m, oberon_type_t * rec)
265 char * cname;
266 struct gen_class * class;
268 /* Устанавливаем новоый id */
269 rec -> gen_type -> rec_id = m -> rec_id;
270 m -> rec_id += 1;
272 cname = jvm_get_class_full_name(rec);
273 class = jvm_create_class(cname);
275 fprintf(class -> fp, ".source %s\n", rec -> module -> name);
276 fprintf(class -> fp, ".class public %s\n", cname);
277 fprintf(class -> fp, ".super java/lang/Object\n\n");
279 rec -> gen_type -> class = class;
282 void
283 oberon_generator_init_type(oberon_context_t * ctx, oberon_type_t * type)
285 gen_type_t * t = GC_MALLOC(sizeof *t);
286 memset(t, 0, sizeof *t);
287 type -> gen_type = t;
289 switch(type -> class)
291 case OBERON_TYPE_VOID:
292 case OBERON_TYPE_INTEGER:
293 case OBERON_TYPE_BOOLEAN:
294 case OBERON_TYPE_ARRAY:
295 case OBERON_TYPE_REAL:
296 break;
297 case OBERON_TYPE_RECORD:
299 gen_module_t * m;
300 m = type -> module -> gen_mod;
301 oberon_generate_record_class(m, type);
302 break;
303 case OBERON_TYPE_PROCEDURE:
304 oberon_generate_procedure_class(type);
305 break;
306 case OBERON_TYPE_POINTER:
307 break;
308 default:
309 gen_error("oberon_generator_init_type: unk calss %i", type -> class);
310 break;
314 static void
315 jvm_generate_object(struct gen_class * class, oberon_object_t * x)
317 char * name;
318 char * desc;
320 name = x -> name;
321 desc = jvm_get_descriptor(x -> type);
322 switch(x -> class)
324 case OBERON_CLASS_VAR:
325 if(x -> local == 0)
327 jvm_generate_field(class, "public static", name, desc);
329 else
331 gen_error("jvm_generate_object: local variable as class field? wat");
333 break;
334 case OBERON_CLASS_FIELD:
335 jvm_generate_field(class, "public", name, desc);
336 break;
337 default:
338 gen_error("jvm_generate_object: unk class %i", x -> class);
339 break;
343 void
344 oberon_generator_init_record(oberon_context_t * ctx, oberon_type_t * rec)
346 struct gen_class * class;
347 class = rec -> gen_type -> class;
349 int num = rec -> num_decl;
350 oberon_object_t * field = rec -> decl;
351 for(int i = 0; i < num; i++)
353 jvm_generate_object(class, field);
354 field = field -> next;
357 fprintf(class -> fp, ".method public <init>()V\n");
358 fprintf(class -> fp, " aload_0\n");
359 fprintf(class -> fp, " invokespecial java/lang/Object/<init>()V\n");
360 fprintf(class -> fp, " return\n");
361 fprintf(class -> fp, ".end method\n");
363 jvm_destroy_class(class);
366 void
367 oberon_generator_init_var(oberon_context_t * ctx, oberon_object_t * var)
369 gen_var_t * v = GC_MALLOC(sizeof *v);
370 memset(v, 0, sizeof *v);
371 var -> gen_var = v;
373 gen_module_t * m;
374 m = ctx -> mod -> gen_mod;
376 struct gen_class * class;
377 class = m -> class;
379 switch(var -> class)
381 case OBERON_CLASS_VAR_PARAM:
382 gen_error("generator: VAR-parameters not implemented");
383 break;
384 case OBERON_CLASS_PARAM:
385 case OBERON_CLASS_FIELD:
386 break;
387 case OBERON_CLASS_VAR:
388 jvm_generate_object(class, var);
389 break;
390 default:
391 gen_error("oberon_generator_init_var: unk var class %i", var -> class);
392 break;
396 void
397 oberon_generator_init_proc(oberon_context_t * ctx, oberon_object_t * proc)
399 struct gen_class * class = proc -> module -> gen_mod -> class;
400 proc -> gen_proc = jvm_create_proc(class);
402 if(proc -> local)
404 gen_error("generator: local procedures not implemented");
408 void
409 oberon_generator_init_module(oberon_context_t * ctx, oberon_module_t * mod)
411 gen_module_t * m = GC_MALLOC(sizeof *m);
412 memset(m, 0, sizeof *m);
413 mod -> gen_mod = m;
415 struct gen_class * class;
416 class = jvm_create_class(mod -> name);
418 fprintf(class -> fp, ".source %s\n", mod -> name);
419 fprintf(class -> fp, ".class %s\n", mod -> name);
420 fprintf(class -> fp, ".super java/lang/Object\n\n");
422 m -> class = class;
424 ctx -> gen_context -> current_m = m;
427 void
428 oberon_generator_fini_module(oberon_module_t * mod)
430 jvm_destroy_class(mod -> gen_mod -> class);
433 static void
434 push_expr(gen_proc_t * p, oberon_expr_t * expr);
436 void
437 oberon_generate_begin_module(oberon_context_t * ctx)
439 struct gen_class * class = ctx -> mod -> gen_mod -> class;
440 gen_proc_t * p = jvm_create_proc(class);
442 jvm_generate_function_header(p, "public", "<init>", "()V");
443 jvm_alloc_register_untyped(p -> rf, false);
444 jvm_generate(p, 0, 1, "aload_0");
445 jvm_generate(p, 1, 0, "invokespecial java/lang/Object/<init>()V");
448 void
449 oberon_generate_end_module(oberon_context_t * ctx)
451 struct gen_class * class = ctx -> mod -> gen_mod -> class;
452 gen_proc_t * p = class -> p;
454 jvm_generate(p, 0, 0, "return");
455 jvm_generate_function_end(class -> p);
458 static void
459 jvm_init_local_object(gen_proc_t * p, oberon_object_t * x)
461 gen_var_t * v;
462 char * desc;
463 struct gen_class * class;
465 v = x -> gen_var;
466 class = p -> class;
467 desc = jvm_get_descriptor(x -> type);
469 // Убеждаемся что сейчас находимся в функции
470 assert(class -> p);
471 assert(x -> local);
473 switch(x -> class)
475 case OBERON_CLASS_VAR:
476 case OBERON_CLASS_PARAM:
477 v -> reg = jvm_alloc_register(p -> rf, x -> type);
478 fprintf(class -> fp, ".var %i is %s %s from start to end\n", v -> reg, x -> name, desc);
479 break;
480 default:
481 gen_error("jvm_init_local_object: wat");
482 break;
486 void
487 oberon_generate_begin_proc(oberon_context_t * ctx, oberon_object_t * proc)
489 gen_proc_t * p;
490 char * signature;
492 p = proc -> gen_proc;
494 signature = jvm_get_procedure_signature(proc -> type);
496 jvm_generate_function_header(p, "public static", proc -> name, signature);
498 oberon_object_t * var = proc -> type -> decl;
499 while(var)
501 jvm_init_local_object(p, var);
502 var = var -> next;
506 void
507 oberon_generate_end_proc(oberon_context_t * ctx)
509 gen_module_t * m;
510 gen_proc_t * p;
512 m = ctx -> mod -> gen_mod;
513 p = m -> class -> p;
515 jvm_generate_function_end(p);
518 static void
519 jvm_generate_call_proc(gen_proc_t * p, oberon_expr_t * desig)
521 assert(desig -> is_item);
522 assert(desig -> item.mode == MODE_CALL);
524 oberon_object_t * proc;
525 char * fullname;
526 char * signature;
528 proc = desig -> item.var;
529 fullname = jvm_get_field_full_name(proc);
530 signature = jvm_get_procedure_signature(proc -> type);
532 int args_cells = 0;
533 int result_cells = jvm_cell_size_for_type(proc -> type -> base);
535 int num = desig -> item.num_args;
536 oberon_expr_t * arg = desig -> item.args;
537 for(int i = 0; i < num; i++)
539 args_cells += jvm_cell_size_for_type(arg -> result);
540 push_expr(p, arg);
541 arg = arg -> next;
544 jvm_generate(p, args_cells, result_cells, "invokestatic %s%s", fullname, signature);
547 void
548 oberon_generate_call_proc(oberon_context_t * ctx, oberon_expr_t * desig)
550 jvm_generate_call_proc(ctx -> gen_context -> current_m -> class -> p, desig);
553 void
554 oberon_generate_return(oberon_context_t * ctx, oberon_expr_t * expr)
556 gen_module_t * m;
557 gen_proc_t * p;
558 char prefix;
559 int cell_size;
561 m = ctx -> mod -> gen_mod;
562 p = m -> class -> p;
564 if(expr)
566 push_expr(p, expr);
567 prefix = jvm_get_prefix(expr -> result);
568 cell_size = jvm_cell_size_for_type(expr -> result);
569 jvm_generate(p, cell_size, 0, "%creturn", prefix);
571 else
573 jvm_generate(p, 0, 0, "return");
577 static void
578 jvm_push_var(gen_proc_t * p, oberon_object_t * var)
580 int cell_size = jvm_cell_size_for_type(var -> type);
582 if(var -> local)
584 int reg = var -> gen_var -> reg;
585 char prefix = jvm_get_prefix(var -> type);
586 jvm_generate(p, 0, cell_size, "%cload %i", prefix, reg);
588 else
590 char * fullname = jvm_get_field_full_name(var);
591 char * desc = jvm_get_descriptor(var -> type);
592 jvm_generate(p, 0, cell_size, "getstatic %s %s", fullname, desc);
596 static void
597 jvm_generate_new_static(gen_proc_t * p, oberon_type_t * type, int num, oberon_expr_t * arg)
599 //char * desc;
600 char * cname;
601 //desc = jvm_get_descriptor(type);
602 cname = jvm_get_class_full_name(type);
604 switch(type -> class)
606 case OBERON_TYPE_INTEGER:
607 case OBERON_TYPE_BOOLEAN:
608 case OBERON_TYPE_PROCEDURE:
609 case OBERON_TYPE_REAL:
610 case OBERON_TYPE_POINTER:
611 /* ничего не надо делать при статической инициализации */
612 break;
613 case OBERON_TYPE_RECORD:
614 jvm_generate(p, 0, 1, "new %s", cname);
615 jvm_generate(p, 1, 2, "dup");
616 jvm_generate(p, 1, 0, "invokespecial %s/<init>()V", cname);
617 break;
618 case OBERON_TYPE_ARRAY:
619 gen_error("jvm_generate_new_static: TODO array");
620 break;
621 default:
622 gen_error("jvm_generate_new_static: unk type class %i", type -> class);
623 break;
627 static void
628 jvm_generate_new_pointer(gen_proc_t * p, oberon_type_t * type, int num, oberon_expr_t * arg)
630 assert(type -> class == OBERON_TYPE_POINTER);
631 jvm_generate_new_static(p, type -> base, num, arg);
634 static void
635 push_item(gen_proc_t * p, oberon_item_t * item)
637 switch(item -> mode)
639 case MODE_VAR:
640 jvm_push_var(p, item -> var);
641 break;
642 case MODE_INTEGER:
643 jvm_generate_push_int(p, item -> integer);
644 break;
645 case MODE_BOOLEAN:
646 jvm_generate_push_int(p, item -> boolean);
647 break;
648 case MODE_CALL:
649 jvm_generate_call_proc(p, (oberon_expr_t *) item);
650 break;
651 case MODE_INDEX:
652 gen_error("push_item: TODO index");
653 break;
654 case MODE_FIELD:
655 push_item(p, item -> parent);
656 char * field = jvm_get_field_full_name(item -> var);
657 char * desc = jvm_get_descriptor(item -> var -> type);
658 jvm_generate(p, 1, 1, "getfield %s %s", field, desc);
659 break;
660 case MODE_DEREF:
661 /* Все объекты представляются как увказатели */
662 push_item(p, item -> parent);
663 break;
664 case MODE_NIL:
665 jvm_generate(p, 0, 1, "aconst_null");
666 break;
667 case MODE_NEW:
668 jvm_generate_new_pointer(p, item -> result, item -> num_args, item -> args);
669 break;
670 case MODE_REAL:
671 jvm_generate_push_float(p, item -> real, item -> result -> size);
672 break;
673 default:
674 gen_error("push_item: unk mode %i", item -> mode);
675 break;
679 static void
680 jvm_generate_logical_not(gen_proc_t * p)
682 int label_done = jvm_new_label_id(p);
683 int label_false = jvm_new_label_id(p);
684 char * label_name_done = jvm_get_label_name(label_done);
685 char * label_name_false = jvm_get_label_name(label_false);
687 jvm_generate(p, 1, 0, "ifne %s", label_name_false);
688 jvm_generate(p, 0, 1, "iconst_1");
689 jvm_generate(p, 0, 0, "goto %s", label_name_done);
690 jvm_generate_label(p, label_false);
691 jvm_generate(p, 0, 1, "iconst_0");
692 jvm_generate_label(p, label_done);
695 static void
696 jvm_generate_abs(gen_proc_t * p, char prefix)
698 char t = jvm_get_type_of_prefix(prefix);
699 int cell_size = jvm_cell_size_for_prefix(prefix);
700 jvm_generate(p, cell_size, cell_size, "invokestatic java/lang/Math/abs(%c)%c", t, t);
703 static void
704 jvm_generate_compare_op(gen_proc_t * p, char prefix, int op)
706 int label_true = jvm_new_label_id(p);
707 int label_done = jvm_new_label_id(p);
708 char * label_name_true = jvm_get_label_name(label_true);
709 char * label_name_done = jvm_get_label_name(label_done);
710 int cell_size = 2 * jvm_cell_size_for_prefix(prefix);
712 assert(prefix == 'i' || prefix == 'a');
714 const char * cmpop = "";
715 switch(op)
717 case OP_EQ:
718 cmpop = "eq";
719 break;
720 case OP_NEQ:
721 cmpop = "ne";
722 break;
723 case OP_LSS:
724 cmpop = "lt";
725 break;
726 case OP_LEQ:
727 cmpop = "le";
728 break;
729 case OP_GRT:
730 cmpop = "gt";
731 break;
732 case OP_GEQ:
733 cmpop = "ge";
734 break;
735 default:
736 gen_error("jvm_generate_compare_op: wat");
737 break;
740 jvm_generate(p, cell_size, 0, "if_%ccmp%s %s", prefix, cmpop, label_name_true);
741 jvm_generate(p, 0, 1, "iconst_0");
742 jvm_generate(p, 0, 0, "goto %s", label_name_done);
743 jvm_generate_label(p, label_true);
744 jvm_generate(p, 0, 1, "iconst_1");
745 jvm_generate_label(p, label_done);
748 static void
749 jvm_generate_operator(gen_proc_t * p, char prefix, int op)
751 int cell_size = jvm_cell_size_for_prefix(prefix);
752 switch(op)
754 case OP_UNARY_MINUS:
755 jvm_generate(p, cell_size, cell_size, "%cneg", prefix);
756 break;
757 case OP_BITWISE_NOT:
758 jvm_generate_push_int(p, -1);
759 jvm_generate(p, 2 * cell_size, cell_size, "%cxor", prefix);
760 break;
761 case OP_LOGIC_NOT:
762 jvm_generate_logical_not(p);
763 break;
764 case OP_ABS:
765 jvm_generate_abs(p, prefix);
766 break;
768 case OP_ADD:
769 jvm_generate(p, 2 * cell_size, cell_size, "%cadd", prefix);
770 break;
771 case OP_SUB:
772 jvm_generate(p, 2 * cell_size, cell_size, "%csub", prefix);
773 break;
774 case OP_MUL:
775 jvm_generate(p, 2 * cell_size, cell_size, "%cmul", prefix);
776 break;
777 case OP_DIV:
778 jvm_generate(p, 2 * cell_size, cell_size, "%cdiv", prefix);
779 break;
780 case OP_MOD:
781 jvm_generate(p, 2 * cell_size, cell_size, "%crem", prefix);
782 break;
783 case OP_BITWISE_AND:
784 jvm_generate(p, 2 * cell_size, cell_size, "%cand", prefix);
785 break;
786 case OP_BITWISE_XOR:
787 jvm_generate(p, 2 * cell_size, cell_size, "%cxor", prefix);
788 break;
789 case OP_BITWISE_OR:
790 jvm_generate(p, 2 * cell_size, cell_size, "%cor", prefix);
791 break;
793 case OP_EQ:
794 case OP_NEQ:
795 case OP_LSS:
796 case OP_LEQ:
797 case OP_GRT:
798 case OP_GEQ:
799 jvm_generate_compare_op(p, prefix, op);
800 break;
801 default:
802 gen_error("jvm_generate_operator: unk op %i", op);
803 break;
804 }
807 static void
808 jvm_generate_logical_or(gen_proc_t * p, oberon_expr_t * a, oberon_expr_t * b)
810 int label_calc_b = jvm_new_label_id(p);
811 int label_done = jvm_new_label_id(p);
812 char * label_name_calc_b = jvm_get_label_name(label_calc_b);
813 char * label_name_done = jvm_get_label_name(label_done);
815 /* a OR b -- если a, то TRUE, иначе b */
817 push_expr(p, a);
818 jvm_generate(p, 1, 0, "ifne %s", label_name_calc_b);
819 jvm_generate(p, 0, 1, "iconst_1");
820 jvm_generate(p, 0, 0, "goto %s", label_name_done);
821 jvm_generate_label(p, label_calc_b);
822 push_expr(p, b);
823 jvm_generate_label(p, label_done);
826 static void
827 jvm_generate_logical_and(gen_proc_t * p, oberon_expr_t * a, oberon_expr_t * b)
829 int label_false = jvm_new_label_id(p);
830 int label_done = jvm_new_label_id(p);
831 char * label_name_false = jvm_get_label_name(label_false);
832 char * label_name_done = jvm_get_label_name(label_done);
834 /* a AND b -- если a, то b, иначе FALSE */
836 push_expr(p, a);
837 jvm_generate(p, 1, 0, "ifne %s", label_name_false);
838 push_expr(p, b);
839 jvm_generate(p, 0, 0, "goto %s", label_name_done);
840 jvm_generate_label(p, label_false);
841 jvm_generate(p, 0, 1, "iconst_0");
842 jvm_generate_label(p, label_done);
845 static void
846 push_operator(gen_proc_t * p, oberon_oper_t * oper)
848 char prefix = jvm_get_prefix(oper -> result);
849 int op = oper -> op;
850 switch(op)
852 case OP_UNARY_MINUS:
853 case OP_BITWISE_NOT:
854 case OP_LOGIC_NOT:
855 case OP_ABS:
856 push_expr(p, oper -> left);
857 jvm_generate_operator(p, prefix, op);
858 break;
860 case OP_ADD:
861 case OP_SUB:
862 case OP_MUL:
863 case OP_DIV:
864 case OP_MOD:
865 case OP_BITWISE_AND:
866 case OP_BITWISE_XOR:
867 case OP_BITWISE_OR:
869 case OP_EQ:
870 case OP_NEQ:
871 case OP_LSS:
872 case OP_LEQ:
873 case OP_GRT:
874 case OP_GEQ:
875 push_expr(p, oper -> left);
876 push_expr(p, oper -> right);
877 jvm_generate_operator(p, prefix, op);
878 break;
880 case OP_LOGIC_OR:
881 jvm_generate_logical_or(p, oper -> left, oper -> right);
882 break;
883 case OP_LOGIC_AND:
884 jvm_generate_logical_and(p, oper -> left, oper -> right);
885 break;
886 default:
887 gen_error("push_oper: unk op %i", op);
888 break;
892 static void
893 push_expr(gen_proc_t * p, oberon_expr_t * expr)
895 if(expr -> is_item)
897 push_item(p, (oberon_item_t *) expr);
899 else
901 push_operator(p, (oberon_oper_t *) expr);
905 static void
906 store_expr(gen_proc_t * p, oberon_expr_t * dst, oberon_expr_t * src)
908 assert(dst -> is_item);
909 oberon_item_t * item = (oberon_item_t *) dst;
911 int cell_size = jvm_cell_size_for_type(src -> result);
913 char prefix;
914 switch(item -> mode)
916 case MODE_VAR:
917 push_expr(p, src);
918 if(item -> var -> local)
920 int reg = item -> var -> gen_var -> reg;
921 prefix = jvm_get_prefix(item -> result);
922 jvm_generate(p, cell_size, 0, "%cstore %i", prefix, reg);
924 else
926 char * fullname = jvm_get_field_full_name(item -> var);
927 char * desc = jvm_get_descriptor(item -> result);
928 jvm_generate(p, cell_size, 0, "putstatic %s %s", fullname, desc);
930 break;
931 case MODE_INDEX:
932 gen_error("store_expr: TODO index");
933 break;
934 case MODE_FIELD:
936 char * fullname = jvm_get_field_full_name(item -> var);
937 char * desc = jvm_get_descriptor(item -> result);
938 push_item(p, item -> parent);
939 push_expr(p, src);
940 jvm_generate(p, 1 + cell_size, 0, "putfield %s %s", fullname, desc);
942 break;
943 default:
944 gen_error("store_expr: unk mode %i", item -> mode);
945 break;
949 void
950 oberon_generate_assign(oberon_context_t * ctx, oberon_expr_t * src, oberon_expr_t * dst)
952 gen_module_t * m;
953 gen_proc_t * p;
955 m = ctx -> mod -> gen_mod;
956 p = m -> class -> p;
958 store_expr(p, dst, src);
961 void
962 oberon_generate_code(oberon_context_t * ctx)
964 printf("generate code\n");
967 void
968 oberon_generator_dump(oberon_context_t * ctx, char * path)
970 printf("jit: dump code\n");
973 void *
974 oberon_generator_get_procedure(oberon_context_t * ctx, const char * name)
976 printf("jit: get pointer to procedure %s\n", name);
977 return NULL;
980 void *
981 oberon_generator_get_var(oberon_context_t * ctx, const char * name)
983 printf("jit: get pointer to var %s\n", name);
984 return NULL;