DEADSOFTWARE

JVM: Реализован доступ к полям записей и NEW для записей(без инициализации полей)
[dsw-obn.git] / src / backends / jvm / generator-jvm.c
1 #include <stdio.h>
2 #include <stdarg.h>
3 #include <stdbool.h>
4 #include <string.h>
5 #include <assert.h>
7 #include <gc.h>
9 #include "../../../include/oberon.h"
10 #include "../../oberon-internals.h"
11 #include "generator-jvm.h"
13 char *
14 new_string(const char * format, ...)
15 {
16 va_list ptr;
17 va_start(ptr, format);
19 char buf[1024];
20 vsnprintf(buf, 1024, format, ptr);
22 va_end(ptr);
24 char * result;
25 int size;
27 size = strlen(buf);
28 result = GC_MALLOC(size + 1);
29 memset(result, 0, size);
30 strncpy(result, buf, size);
32 return result;
33 }
35 void
36 oberon_generator_init_context(oberon_context_t * ctx)
37 {
38 gen_context_t * gen_context = GC_MALLOC(sizeof *gen_context);
39 memset(gen_context, 0, sizeof *gen_context);
41 ctx -> gen_context = gen_context;
42 }
44 void
45 oberon_generator_destroy_context(oberon_context_t * ctx)
46 {
47 ctx -> gen_context = NULL;
48 }
50 static char * get_class_full_name(oberon_context_t * ctx, oberon_type_t * type);
52 static char *
53 get_descriptor(oberon_context_t * ctx, oberon_type_t * type)
54 {
55 char * desc;
57 switch(type -> class)
58 {
59 case OBERON_TYPE_VOID:
60 return new_string("V");
61 break;
62 case OBERON_TYPE_INTEGER:
63 switch(type -> size)
64 {
65 case 1:
66 return new_string("B");
67 break;
68 case 2:
69 return new_string("S");
70 break;
71 case 4:
72 return new_string("I");
73 break;
74 case 8:
75 return new_string("J");
76 break;
77 default:
78 oberon_error(ctx, "get_descriptor: unsupported int size %i", type -> size);
79 break;
80 }
81 break;
82 case OBERON_TYPE_REAL:
83 switch(type -> size)
84 {
85 case 4:
86 return new_string("F");
87 break;
88 case 8:
89 return new_string("D");
90 break;
91 default:
92 oberon_error(ctx, "get_descriptor: unsupported float size %i", type -> size);
93 break;
94 }
95 break;
96 case OBERON_TYPE_BOOLEAN:
97 return new_string("Z");
98 break;
99 case OBERON_TYPE_POINTER:
100 return get_descriptor(ctx, type -> base);
101 break;
102 case OBERON_TYPE_PROCEDURE:
103 case OBERON_TYPE_RECORD:
104 desc = get_class_full_name(ctx, type);
105 return new_string("L%s;", desc);
106 break;
107 case OBERON_TYPE_ARRAY:
108 desc = get_descriptor(ctx, type -> base);
109 return new_string("[%s", desc);
110 break;
111 default:
112 oberon_error(ctx, "print_descriptor: unsupported type class %i", type -> class);
113 break;
116 return NULL;
119 static char
120 get_prefix(oberon_context_t * ctx, oberon_type_t * type)
122 int size = type -> size;
123 switch(type -> class)
125 case OBERON_TYPE_BOOLEAN:
126 case OBERON_TYPE_INTEGER:
127 return (size <= 4) ? ('i') : ('l');
128 break;
129 case OBERON_TYPE_PROCEDURE:
130 case OBERON_TYPE_ARRAY:
131 case OBERON_TYPE_RECORD:
132 case OBERON_TYPE_POINTER:
133 return 'a';
134 break;
135 case OBERON_TYPE_REAL:
136 return (size <= 4) ? ('f') : ('d');
137 break;
140 oberon_error(ctx, "get_prefix: wat");
141 return '!';
144 static char *
145 get_field_full_name(oberon_context_t * ctx, oberon_object_t * x)
147 switch(x -> class)
149 case OBERON_CLASS_VAR:
150 return new_string("%s/%s", x -> module -> name, x -> name);
151 case OBERON_CLASS_FIELD:;
152 char * rec_name = get_class_full_name(ctx, x -> parent_type);
153 return new_string("%s/%s", rec_name, x -> name);
154 case OBERON_CLASS_MODULE:
155 return new_string(x -> module -> name);
156 default:
157 oberon_error(ctx, "get_field_full_name: wat");
158 break;
161 return NULL;
164 static char *
165 get_class_full_name(oberon_context_t * ctx, oberon_type_t * type)
167 int rec_id;
168 char * name = NULL;
170 switch(type -> class)
172 case OBERON_TYPE_PROCEDURE:
173 name = new_string("SYSTEM$PROCEDURE");
175 char * desc;
176 desc = get_descriptor(ctx, type -> base);
177 name = new_string("%s$%s", name, desc);
179 int num = type -> num_decl;
180 oberon_object_t * arg = type -> decl;
181 for(int i = 0; i < num; i++)
183 desc = get_descriptor(ctx, arg -> type);
184 name = new_string("%s%s", name, desc);
185 arg = arg -> next;
188 break;
189 case OBERON_TYPE_RECORD:
190 rec_id = type -> gen_type -> rec_id;
191 name = new_string("%s$RECORD%i", type -> module -> name, rec_id);
192 break;
193 default:
194 oberon_error(ctx, "get_record_full_name: unk type class %i", type -> class);
195 break;
198 return name;
201 static char *
202 get_procedure_signature(oberon_context_t * ctx, oberon_type_t * proc)
204 char * signature;
205 char * desc;
207 signature = new_string("(");
209 int num = proc -> num_decl;
210 oberon_object_t * arg = proc -> decl;
211 for(int i = 0; i < num; i++)
213 desc = get_descriptor(ctx, arg -> type);
214 signature = new_string("%s%s", signature, desc);
215 arg = arg -> next;
218 desc = get_descriptor(ctx, proc -> base);
219 signature = new_string("%s)%s", signature, desc);
221 return signature;
224 static void
225 oberon_generate_procedure_class(oberon_context_t * ctx, oberon_type_t * proc)
227 FILE * fp;
228 char * cname;
229 char * fname;
230 char * signature;
232 cname = get_class_full_name(ctx, proc);
233 fname = new_string("%s.j", cname);
235 fp = fopen(fname, "w");
237 fprintf(fp, ".source SYSTEM\n");
238 fprintf(fp, ".class public abstract %s\n", cname);
239 fprintf(fp, ".super java/lang/Object\n\n");
241 signature = get_procedure_signature(ctx, proc);
243 fprintf(fp, ".method public <init>()V\n");
244 fprintf(fp, " aload_0\n");
245 fprintf(fp, " invokespecial java/lang/Object/<init>()V\n");
246 fprintf(fp, " return\n");
247 fprintf(fp, ".end method\n\n");
249 fprintf(fp, ".method public abstract invoke%s\n", signature);
250 fprintf(fp, ".end method\n\n");
252 fclose(fp);
255 static void
256 oberon_generate_record_class(oberon_context_t * ctx, oberon_type_t * rec)
258 FILE * fp;
259 char * cname;
260 char * fname;
262 /* Устанавливаем новоый id */
263 rec -> gen_type -> rec_id = rec -> module -> gen_mod -> rec_id;
264 rec -> module -> gen_mod -> rec_id += 1;
266 cname = get_class_full_name(ctx, rec);
267 fname = new_string("%s.j", cname);
269 fp = fopen(fname, "w");
271 fprintf(fp, ".source %s\n", rec -> module -> name);
272 fprintf(fp, ".class public %s\n", cname);
273 fprintf(fp, ".super java/lang/Object\n\n");
275 rec -> gen_type -> fp = fp;
278 void
279 oberon_generator_init_type(oberon_context_t * ctx, oberon_type_t * type)
281 gen_type_t * t = GC_MALLOC(sizeof *t);
282 memset(t, 0, sizeof *t);
283 type -> gen_type = t;
285 switch(type -> class)
287 case OBERON_TYPE_VOID:
288 case OBERON_TYPE_INTEGER:
289 case OBERON_TYPE_BOOLEAN:
290 case OBERON_TYPE_ARRAY:
291 case OBERON_TYPE_REAL:
292 break;
293 case OBERON_TYPE_RECORD:
294 oberon_generate_record_class(ctx, type);
295 break;
296 case OBERON_TYPE_PROCEDURE:
297 oberon_generate_procedure_class(ctx, type);
298 break;
299 case OBERON_TYPE_POINTER:
300 break;
301 default:
302 oberon_error(ctx, "oberon_generator_init_type: unk calss %i", type -> class);
303 break;
307 static void
308 oberon_generate_object(oberon_context_t * ctx, FILE * fp, oberon_object_t * x)
310 char * name;
311 char * desc;
313 name = x -> name;
314 desc = get_descriptor(ctx, x -> type);
315 switch(x -> class)
317 case OBERON_CLASS_VAR:
318 if(x -> local == 0)
320 fprintf(fp, ".field public static %s %s\n\n", name, desc);
322 break;
323 case OBERON_CLASS_FIELD:
324 fprintf(fp, ".field public %s %s\n\n", name, desc);
325 break;
326 default:
327 oberon_error(ctx, "oberon_generate_object: unk class %i", x -> class);
328 break;
332 void
333 oberon_generator_init_record(oberon_context_t * ctx, oberon_type_t * rec)
335 FILE * fp;
337 fp = rec -> gen_type -> fp;
339 int num = rec -> num_decl;
340 oberon_object_t * field = rec -> decl;
341 for(int i = 0; i < num; i++)
343 oberon_generate_object(ctx, fp, field);
344 field = field -> next;
347 fprintf(fp, ".method public <init>()V\n");
348 fprintf(fp, " aload_0\n");
349 fprintf(fp, " invokespecial java/lang/Object/<init>()V\n");
350 fprintf(fp, " return\n");
351 fprintf(fp, ".end method\n");
353 fclose(fp);
356 void
357 oberon_generator_init_var(oberon_context_t * ctx, oberon_object_t * var)
359 gen_var_t * v = GC_MALLOC(sizeof *v);
360 memset(v, 0, sizeof *v);
361 var -> gen_var = v;
363 gen_module_t * m = ctx -> mod -> gen_mod;
365 switch(var -> class)
367 case OBERON_CLASS_VAR_PARAM:
368 oberon_error(ctx, "generator: VAR-parameters not implemented");
369 break;
370 case OBERON_CLASS_PARAM:
371 case OBERON_CLASS_FIELD:
372 break;
373 case OBERON_CLASS_VAR:
374 oberon_generate_object(ctx, m -> fp, var);
375 break;
376 default:
377 oberon_error(ctx, "oberon_generator_init_var: unk var class %i", var -> class);
378 break;
382 void
383 oberon_generator_init_proc(oberon_context_t * ctx, oberon_object_t * proc)
385 gen_proc_t * p = GC_MALLOC(sizeof *p);
386 memset(p, 0, sizeof *p);
387 proc -> gen_proc = p;
389 struct gen_register_file * rf = GC_MALLOC(sizeof *rf);
390 memset(rf, 0, sizeof *rf);
391 p -> rf = rf;
393 if(proc -> local)
395 oberon_error(ctx, "generator: local procedures not implemented");
399 void
400 oberon_generator_init_module(oberon_context_t * ctx, oberon_module_t * mod)
402 gen_module_t * m = GC_MALLOC(sizeof *m);
403 memset(m, 0, sizeof *m);
404 mod -> gen_mod = m;
406 int fnamesz = strlen(mod -> name) + 3;
407 char fname[fnamesz + 1];
408 snprintf(fname, fnamesz, "%s.j", mod -> name);
410 FILE * fp;
411 fp = fopen(fname, "w");
412 assert(fp != NULL);
414 fprintf(fp, ".source %s\n", mod -> name);
415 fprintf(fp, ".class %s\n", mod -> name);
416 fprintf(fp, ".super java/lang/Object\n\n");
418 m -> fp = fp;
421 // =======================================================================
422 // GENERATOR
423 // =======================================================================
425 static void
426 push_expr(oberon_context_t * ctx, FILE * fp, oberon_expr_t * expr);
428 void
429 oberon_generate_begin_module(oberon_context_t * ctx)
431 gen_module_t * m = ctx -> mod -> gen_mod;
432 fprintf(m -> fp, ".method public <init>()V\n");
433 fprintf(m -> fp, " aload_0\n");
434 fprintf(m -> fp, " invokespecial java/lang/Object/<init>()V\n");
437 void
438 oberon_generate_end_module(oberon_context_t * ctx)
440 gen_module_t * m = ctx -> mod -> gen_mod;
442 fprintf(m -> fp, " .limit stack 32\n");
443 fprintf(m -> fp, " .limit locals 32\n");
444 fprintf(m -> fp, " return\n");
445 fprintf(m -> fp, ".end method\n");
448 static int
449 jvm_cell_size_for_type(oberon_type_t * type)
451 if(type -> class == OBERON_TYPE_INTEGER
452 || type -> class == OBERON_TYPE_REAL)
454 if(type -> size > 4)
456 return 2;
460 return 1;
463 static bool
464 jvm_is_wide_type(oberon_type_t * type)
466 int cell;
467 cell = jvm_cell_size_for_type(type);
468 assert(cell <= 2);
469 return (cell == 2);
472 static bool
473 jvm_is_free_register(struct gen_register_file * rf, int i, bool wide)
475 if(wide)
477 assert(i + 1 < MAX_REGISTERS);
478 return !(rf -> reg[i].used || rf -> reg[i + 1].used);
480 else
482 assert(i < MAX_REGISTERS);
483 return !(rf -> reg[i].used);
487 static int
488 jvm_alloc_register(struct gen_register_file * rf, oberon_type_t * type)
490 bool wide;
491 wide = jvm_is_wide_type(type);
493 int i = 0;
494 while(i < MAX_REGISTERS && !jvm_is_free_register(rf, i, wide))
496 i += 1;
499 if(wide)
501 assert(i + 1 <= MAX_REGISTERS);
502 rf -> num_used += 2;
503 rf -> reg[i].used = true;
504 rf -> reg[i + 1].used = true;
505 rf -> reg[i].used = true;
506 rf -> reg[i + 1].wide = false;
508 else
510 assert(i <= MAX_REGISTERS);
511 rf -> num_used += 1;
512 rf -> reg[i].used = true;
513 rf -> reg[i].wide = false;
516 if(rf -> num_used > rf -> max_used)
518 rf -> max_used = rf -> num_used;
521 return i;
524 static void
525 jvm_init_local_object(oberon_context_t * ctx, FILE * fp, oberon_object_t * x)
527 int reg;
528 gen_context_t * c;
529 gen_var_t * v;
530 char * desc;
532 c = ctx -> gen_context;
533 v = x -> gen_var;
534 desc = get_descriptor(ctx, x -> type);
536 reg = -1;
537 switch(x -> class)
539 case OBERON_CLASS_VAR:
540 case OBERON_CLASS_PARAM:
541 if(x -> local)
543 reg = jvm_alloc_register(c -> rf, x -> type);
545 v -> reg = reg;
546 fprintf(fp, ".var %i is %s %s from start to end\n", reg, x -> name, desc);
547 break;
548 default:
549 oberon_error(ctx, "jvm_init_local_object: wat");
550 break;
554 void
555 oberon_generate_begin_proc(oberon_context_t * ctx, oberon_object_t * proc)
557 gen_context_t * c;
558 gen_module_t * m;
559 gen_proc_t * p;
560 char * signature;
562 c = ctx -> gen_context;
563 m = ctx -> mod -> gen_mod;
564 p = proc -> gen_proc;
566 signature = get_procedure_signature(ctx, proc -> type);
567 fprintf(m -> fp, ".method public static %s%s\n", proc -> name, signature);
569 /* Сохраняем регистровый файл в стеке */
570 p -> rf -> up = c -> rf;
571 c -> rf = p -> rf;
573 oberon_object_t * var = proc -> type -> decl;
574 while(var)
576 jvm_init_local_object(ctx, m -> fp, var);
577 var = var -> next;
580 fprintf(m -> fp, "start:\n");
583 void
584 oberon_generate_end_proc(oberon_context_t * ctx)
586 gen_context_t * c;
587 gen_module_t * m;
589 c = ctx -> gen_context;
590 m = ctx -> mod -> gen_mod;
592 fprintf(m -> fp, "end:\n");
593 fprintf(m -> fp, " .limit stack 32\n");
594 fprintf(m -> fp, " .limit locals %i\n", c -> rf -> max_used);
595 fprintf(m -> fp, ".end method\n\n");
597 /* Возвращаем исходный регистровый файл */
598 c -> rf = c -> rf -> up;
601 void
602 oberon_generate_call_proc(oberon_context_t * ctx, oberon_expr_t * desig)
604 oberon_object_t * proc;
605 gen_module_t * m;
606 char * fullname;
607 char * signature;
609 assert(desig -> is_item);
610 assert(desig -> item.mode == MODE_CALL);
612 m = ctx -> mod -> gen_mod;
613 proc = desig -> item.var;
614 fullname = get_field_full_name(ctx, proc);
615 signature = get_procedure_signature(ctx, proc -> type);
617 int num = desig -> item.num_args;
618 oberon_expr_t * arg = desig -> item.args;
619 for(int i = 0; i < num; i++)
621 push_expr(ctx, m -> fp, arg);
622 arg = arg -> next;
625 fprintf(m -> fp, "invokestatic %s%s\n", fullname, signature);
628 void
629 oberon_generate_return(oberon_context_t * ctx, oberon_expr_t * expr)
631 gen_module_t * m;
632 char prefix;
634 m = ctx -> mod -> gen_mod;
636 if(expr)
638 push_expr(ctx, m -> fp, expr);
639 prefix = get_prefix(ctx, expr -> result);
640 fprintf(m -> fp, " %creturn\n", prefix);
642 else
644 fprintf(m -> fp, " return\n");
648 static void
649 push_int(FILE * fp, long i)
651 if(i == -1)
653 fprintf(fp, "iconst_m1\n");
655 else if(i >= 0 && i <= 5)
657 fprintf(fp, "iconst_%li\n", i);
659 else if(i >= -128 && i <= 127)
661 fprintf(fp, "bipush %li\n", i);
663 else if(i >= -32768 && i <= 32767)
665 fprintf(fp, "sipush %li\n", i);
667 else if(i >= -2147483648 && i <= 2147483647)
669 fprintf(fp, "ldc %li\n", i);
671 else
673 fprintf(fp, "ldc2 %li\n", i);
677 static void
678 push_float(FILE * fp, double f, int size)
680 if(size <= 4)
682 if(f == 0.0)
684 fprintf(fp, "fconst_0\n");
686 if(f == 1.0)
688 fprintf(fp, "fconst_1\n");
690 if(f == 2.0)
692 fprintf(fp, "fconst_2\n");
694 else
696 fprintf(fp, "ldc %lf\n", f);
699 else
701 if(f == 0.0)
703 fprintf(fp, "dconst_0\n");
705 if(f == 1.0)
707 fprintf(fp, "dconst_1\n");
709 else
711 fprintf(fp, "ldc2 %lf\n", f);
716 static void
717 push_var(oberon_context_t * ctx, FILE * fp, oberon_object_t * var)
719 if(var -> local)
721 int reg = var -> gen_var -> reg;
722 char prefix = get_prefix(ctx, var -> type);
723 fprintf(fp, "%cload %i\n", prefix, reg);
725 else
727 char * fullname = get_field_full_name(ctx, var);
728 char * desc = get_descriptor(ctx, var -> type);
729 fprintf(fp, "getstatic %s %s\n", fullname, desc);
733 static void
734 jvm_generate_new_static(oberon_context_t * ctx, FILE * fp, oberon_type_t * type, int num, oberon_expr_t * arg)
736 //char * desc;
737 char * cname;
738 //desc = get_descriptor(ctx, type);
739 cname = get_class_full_name(ctx, type);
741 switch(type -> class)
743 case OBERON_TYPE_INTEGER:
744 case OBERON_TYPE_BOOLEAN:
745 case OBERON_TYPE_PROCEDURE:
746 case OBERON_TYPE_REAL:
747 case OBERON_TYPE_POINTER:
748 /* ничего не генерируем */
749 break;
750 case OBERON_TYPE_RECORD:
751 fprintf(fp, "new %s\n", cname);
752 fprintf(fp, "dup\n");
753 fprintf(fp, "invokespecial %s/<init>()V\n", cname);
754 break;
755 case OBERON_TYPE_ARRAY:
756 oberon_error(ctx, "jvm_generate_new_static: TODO array");
757 break;
758 default:
759 oberon_error(ctx, "jvm_generate_new_static: unk type class %i", type -> class);
760 break;
764 static void
765 jvm_generate_new_pointer(oberon_context_t * ctx, FILE * fp, oberon_type_t * type, int num, oberon_expr_t * arg)
767 assert(type -> class == OBERON_TYPE_POINTER);
768 jvm_generate_new_static(ctx, fp, type -> base, num, arg);
771 static void
772 push_item(oberon_context_t * ctx, FILE * fp, oberon_item_t * item)
774 switch(item -> mode)
776 case MODE_VAR:
777 push_var(ctx, fp, item -> var);
778 break;
779 case MODE_INTEGER:
780 push_int(fp, item -> integer);
781 break;
782 case MODE_BOOLEAN:
783 push_int(fp, item -> boolean);
784 break;
785 case MODE_CALL:
786 oberon_generate_call_proc(ctx, (oberon_expr_t *) item);
787 break;
788 case MODE_INDEX:
789 oberon_error(ctx, "push_item: TODO index");
790 break;
791 case MODE_FIELD:
792 push_item(ctx, fp, item -> parent);
793 char * field = get_field_full_name(ctx, item -> var);
794 char * desc = get_descriptor(ctx, item -> var -> type);
795 fprintf(fp, "getfield %s %s\n", field, desc);
796 break;
797 case MODE_DEREF:
798 /* Все объекты представляются как увказатели */
799 push_item(ctx, fp, item -> parent);
800 break;
801 case MODE_NIL:
802 fprintf(fp, "aconst_null\n");
803 break;
804 case MODE_NEW:
805 jvm_generate_new_pointer(ctx, fp, item -> result, item -> num_args, item -> args);
806 break;
807 case MODE_REAL:
808 push_float(fp, item -> real, item -> result -> size);
809 break;
810 default:
811 oberon_error(ctx, "push_item: unk mode %i", item -> mode);
812 break;
816 static int
817 jvm_new_label_id(oberon_context_t * ctx)
819 gen_context_t * c = ctx -> gen_context;
820 int label_id = c -> label_id;
821 c -> label_id += 1;
822 return label_id;
825 static char *
826 jvm_get_label_name(int label_id)
828 return new_string("L%i", label_id);
831 static void
832 jvm_generate_label(FILE * fp, int label_id)
834 fprintf(fp, "L%i:\n", label_id);
837 static void
838 jvm_generate_logical_not(oberon_context_t * ctx, FILE * fp)
840 int label_true = jvm_new_label_id(ctx);
841 int label_false = jvm_new_label_id(ctx);
842 char * label_name_true = jvm_get_label_name(label_true);
843 char * label_name_false = jvm_get_label_name(label_false);
845 fprintf(fp, "ifne %s\n", label_name_false);
846 fprintf(fp, "iconst_1\n");
847 fprintf(fp, "goto %s\n", label_name_true);
848 jvm_generate_label(fp, label_false);
849 fprintf(fp, "iconst_0\n");
850 jvm_generate_label(fp, label_true);
853 static char
854 jvm_get_type_of_prefix(char prefix)
856 switch(prefix)
858 case 'b':
859 return 'B';
860 case 'c':
861 return 'C';
862 case 'd':
863 return 'D';
864 case 'f':
865 return 'F';
866 case 'i':
867 return 'I';
868 case 'l':
869 return 'J';
872 assert(0);
875 static void
876 jvm_generate_abs(FILE * fp, char prefix)
878 char t = jvm_get_type_of_prefix(prefix);
879 fprintf(fp, "invokestatic java/lang/Math/abs(%c)%c\n", t, t);
882 static void
883 jvm_generate_compare_op(oberon_context_t * ctx, FILE *fp, char prefix, int op)
885 int label_true = jvm_new_label_id(ctx);
886 int label_false = jvm_new_label_id(ctx);
887 char * label_name_true = jvm_get_label_name(label_true);
888 char * label_name_false = jvm_get_label_name(label_false);
890 assert(prefix == 'i' || prefix == 'a');
892 switch(op)
894 case OP_EQ:
895 fprintf(fp, "if_%ccmpeq %s\n", prefix, label_name_true);
896 break;
897 case OP_NEQ:
898 fprintf(fp, "if_%ccmpne %s\n", prefix, label_name_true);
899 break;
900 case OP_LSS:
901 fprintf(fp, "if_icmplt %s\n", label_name_true);
902 break;
903 case OP_LEQ:
904 fprintf(fp, "if_icmple %s\n", label_name_true);
905 break;
906 case OP_GRT:
907 fprintf(fp, "if_icmpgt %s\n", label_name_true);
908 break;
909 case OP_GEQ:
910 fprintf(fp, "if_icmpge %s\n", label_name_true);
911 break;
912 default:
913 oberon_error(ctx, "jvm_generate_compare_op: wat");
914 break;
917 fprintf(fp, "iconst_0\n");
918 fprintf(fp, "goto %s\n", label_name_false);
919 jvm_generate_label(fp, label_true);
920 fprintf(fp, "iconst_1\n");
921 jvm_generate_label(fp, label_false);
924 static void
925 jvm_generate_operator(oberon_context_t * ctx, FILE *fp, char prefix, int op)
927 switch(op)
929 case OP_UNARY_MINUS:
930 fprintf(fp, "%cneg\n", prefix);
931 break;
932 case OP_BITWISE_NOT:
933 push_int(fp, -1);
934 fprintf(fp, "%cxor\n", prefix);
935 break;
936 case OP_LOGIC_NOT:
937 jvm_generate_logical_not(ctx, fp);
938 break;
939 case OP_ABS:
940 jvm_generate_abs(fp, prefix);
941 break;
943 case OP_ADD:
944 fprintf(fp, "%cadd\n", prefix);
945 break;
946 case OP_SUB:
947 fprintf(fp, "%csub\n", prefix);
948 break;
949 case OP_MUL:
950 fprintf(fp, "%cmul\n", prefix);
951 break;
952 case OP_DIV:
953 fprintf(fp, "%cdiv\n", prefix);
954 break;
955 case OP_MOD:
956 fprintf(fp, "%crem\n", prefix);
957 break;
958 case OP_BITWISE_AND:
959 fprintf(fp, "%cand\n", prefix);
960 break;
961 case OP_BITWISE_XOR:
962 fprintf(fp, "%cxor\n", prefix);
963 break;
964 case OP_BITWISE_OR:
965 fprintf(fp, "%cor\n", prefix);
966 break;
968 case OP_EQ:
969 case OP_NEQ:
970 case OP_LSS:
971 case OP_LEQ:
972 case OP_GRT:
973 case OP_GEQ:
974 jvm_generate_compare_op(ctx, fp, prefix, op);
975 break;
976 default:
977 oberon_error(ctx, "jvm_generate_operator: unk op %i", op);
978 break;
979 }
982 static void
983 jvm_generate_logical_or(oberon_context_t * ctx, FILE * fp, oberon_expr_t * p, oberon_expr_t * q)
985 int label_calc_q = jvm_new_label_id(ctx);
986 int label_done = jvm_new_label_id(ctx);
987 char * label_name_calc_q = jvm_get_label_name(label_calc_q);
988 char * label_name_done = jvm_get_label_name(label_done);
990 /* p OR q -- если p, то TRUE, иначе q */
992 push_expr(ctx, fp, p);
993 fprintf(fp, "ifne %s\n", label_name_calc_q);
994 fprintf(fp, "iconst_1\n");
995 fprintf(fp, "goto %s\n", label_name_done);
996 jvm_generate_label(fp, label_calc_q);
997 push_expr(ctx, fp, q);
998 jvm_generate_label(fp, label_done);
1001 static void
1002 jvm_generate_logical_and(oberon_context_t * ctx, FILE * fp, oberon_expr_t * p, oberon_expr_t * q)
1004 int label_false = jvm_new_label_id(ctx);
1005 int label_done = jvm_new_label_id(ctx);
1006 char * label_name_false = jvm_get_label_name(label_false);
1007 char * label_name_done = jvm_get_label_name(label_done);
1009 /* p AND q -- если p, то q, иначе FALSE */
1011 push_expr(ctx, fp, p);
1012 fprintf(fp, "ifne %s\n", label_name_false);
1013 push_expr(ctx, fp, q);
1014 fprintf(fp, "goto %s\n", label_name_done);
1015 jvm_generate_label(fp, label_false);
1016 fprintf(fp, "iconst_0\n");
1017 jvm_generate_label(fp, label_done);
1020 static void
1021 push_operator(oberon_context_t * ctx, FILE * fp, oberon_oper_t * oper)
1023 char prefix = get_prefix(ctx, oper -> result);
1024 int op = oper -> op;
1025 switch(op)
1027 case OP_UNARY_MINUS:
1028 case OP_BITWISE_NOT:
1029 case OP_LOGIC_NOT:
1030 case OP_ABS:
1031 push_expr(ctx, fp, oper -> left);
1032 jvm_generate_operator(ctx, fp, prefix, op);
1033 break;
1035 case OP_ADD:
1036 case OP_SUB:
1037 case OP_MUL:
1038 case OP_DIV:
1039 case OP_MOD:
1040 case OP_BITWISE_AND:
1041 case OP_BITWISE_XOR:
1042 case OP_BITWISE_OR:
1044 case OP_EQ:
1045 case OP_NEQ:
1046 case OP_LSS:
1047 case OP_LEQ:
1048 case OP_GRT:
1049 case OP_GEQ:
1050 push_expr(ctx, fp, oper -> left);
1051 push_expr(ctx, fp, oper -> right);
1052 jvm_generate_operator(ctx, fp, prefix, op);
1053 break;
1055 case OP_LOGIC_OR:
1056 jvm_generate_logical_or(ctx, fp, oper -> left, oper -> right);
1057 break;
1058 case OP_LOGIC_AND:
1059 jvm_generate_logical_and(ctx, fp, oper -> left, oper -> right);
1060 break;
1061 default:
1062 oberon_error(ctx, "push_oper: unk op %i", op);
1063 break;
1067 static void
1068 push_expr(oberon_context_t * ctx, FILE * fp, oberon_expr_t * expr)
1070 if(expr -> is_item)
1072 push_item(ctx, fp, (oberon_item_t *) expr);
1074 else
1076 push_operator(ctx, fp, (oberon_oper_t *) expr);
1080 static void
1081 store_expr(oberon_context_t * ctx, FILE * fp, oberon_expr_t * dst, oberon_expr_t * src)
1083 assert(dst -> is_item);
1084 oberon_item_t * item = (oberon_item_t *) dst;
1086 char prefix;
1087 switch(item -> mode)
1089 case MODE_VAR:
1090 push_expr(ctx, fp, src);
1091 if(item -> var -> local)
1093 int reg = item -> var -> gen_var -> reg;
1094 prefix = get_prefix(ctx, item -> result);
1095 fprintf(fp, "%cstore %i\n", prefix, reg);
1097 else
1099 char * fullname = get_field_full_name(ctx, item -> var);
1100 char * desc = get_descriptor(ctx, item -> result);
1101 fprintf(fp, "putstatic %s %s\n", fullname, desc);
1103 break;
1104 case MODE_INDEX:
1105 oberon_error(ctx, "store_expr: TODO index");
1106 break;
1107 case MODE_FIELD:
1109 char * fullname = get_field_full_name(ctx, item -> var);
1110 char * desc = get_descriptor(ctx, item -> result);
1111 printf("push parent\n");
1112 push_item(ctx, fp, item -> parent);
1113 printf("push expr\n");
1114 push_expr(ctx, fp, src);
1115 printf("store to field %s:%s\n", fullname, desc);
1116 fprintf(fp, "putfield %s %s ; store field\n", fullname, desc);
1118 break;
1119 default:
1120 oberon_error(ctx, "store_expr: unk mode %i", item -> mode);
1121 break;
1125 void
1126 oberon_generate_assign(oberon_context_t * ctx, oberon_expr_t * src, oberon_expr_t * dst)
1128 gen_module_t * m;
1129 m = ctx -> mod -> gen_mod;
1131 store_expr(ctx, m -> fp, dst, src);
1134 void
1135 oberon_generate_code(oberon_context_t * ctx)
1137 printf("generate code\n");
1140 void
1141 oberon_generator_dump(oberon_context_t * ctx, char * path)
1143 printf("jit: dump code\n");
1146 void *
1147 oberon_generator_get_procedure(oberon_context_t * ctx, const char * name)
1149 printf("jit: get pointer to procedure %s\n", name);
1150 return NULL;
1153 void *
1154 oberon_generator_get_var(oberon_context_t * ctx, const char * name)
1156 printf("jit: get pointer to var %s\n", name);
1157 return NULL;