DEADSOFTWARE

eb0f3dc16b014bc803edf7307ce29049917efb51
[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_PROCEDURE:
100 case OBERON_TYPE_RECORD:
101 desc = get_class_full_name(ctx, type);
102 return new_string("L%s;", desc);
103 break;
104 case OBERON_TYPE_ARRAY:
105 desc = get_descriptor(ctx, type -> base);
106 return new_string("[%s", desc);
107 break;
108 default:
109 oberon_error(ctx, "print_descriptor: unsupported type class %i", type -> class);
110 break;
113 return NULL;
116 static char
117 get_prefix(oberon_context_t * ctx, oberon_type_t * type)
119 int size = type -> size;
120 switch(type -> class)
122 case OBERON_TYPE_BOOLEAN:
123 case OBERON_TYPE_INTEGER:
124 return (size <= 4) ? ('i') : ('l');
125 break;
126 case OBERON_TYPE_PROCEDURE:
127 case OBERON_TYPE_ARRAY:
128 case OBERON_TYPE_RECORD:
129 case OBERON_TYPE_POINTER:
130 return 'a';
131 break;
132 case OBERON_TYPE_REAL:
133 return (size <= 4) ? ('f') : ('d');
134 break;
137 oberon_error(ctx, "get_prefix: wat");
138 return '!';
141 static char *
142 get_field_full_name(oberon_context_t * ctx, oberon_object_t * x)
144 return new_string("%s/%s", x -> module -> name, x -> name);
147 static char *
148 get_class_full_name(oberon_context_t * ctx, oberon_type_t * type)
150 int rec_id;
151 char * name = NULL;
153 switch(type -> class)
155 case OBERON_TYPE_PROCEDURE:
156 name = new_string("SYSTEM$PROCEDURE");
158 char * desc;
159 desc = get_descriptor(ctx, type -> base);
160 name = new_string("%s$%s", name, desc);
162 int num = type -> num_decl;
163 oberon_object_t * arg = type -> decl;
164 for(int i = 0; i < num; i++)
166 desc = get_descriptor(ctx, arg -> type);
167 name = new_string("%s%s", name, desc);
168 arg = arg -> next;
171 break;
172 case OBERON_TYPE_RECORD:
173 assert(type -> module);
174 assert(type -> module -> gen_mod);
175 rec_id = type -> gen_type -> rec_id;
176 name = new_string("%s$RECORD%i", type -> module -> name, rec_id);
177 break;
178 default:
179 oberon_error(ctx, "get_record_full_name: unk type class %i", type -> class);
180 break;
183 return name;
186 static char *
187 get_procedure_signature(oberon_context_t * ctx, oberon_type_t * proc)
189 char * signature;
190 char * desc;
192 signature = new_string("(");
194 int num = proc -> num_decl;
195 oberon_object_t * arg = proc -> decl;
196 for(int i = 0; i < num; i++)
198 desc = get_descriptor(ctx, arg -> type);
199 signature = new_string("%s%s", signature, desc);
200 arg = arg -> next;
203 desc = get_descriptor(ctx, proc -> base);
204 signature = new_string("%s)%s", signature, desc);
206 return signature;
209 static void
210 oberon_generate_procedure_class(oberon_context_t * ctx, oberon_type_t * proc)
212 FILE * fp;
213 char * cname;
214 char * fname;
215 char * signature;
217 cname = get_class_full_name(ctx, proc);
218 fname = new_string("%s.j", cname);
220 fp = fopen(fname, "w");
222 fprintf(fp, ".source SYSTEM\n");
223 fprintf(fp, ".class public abstract %s\n", cname);
224 fprintf(fp, ".super java/lang/Object\n\n");
226 signature = get_procedure_signature(ctx, proc);
228 fprintf(fp, ".method public <init>()V\n");
229 fprintf(fp, " aload_0\n");
230 fprintf(fp, " invokespecial java/lang/Object/<init>()V\n");
231 fprintf(fp, " return\n");
232 fprintf(fp, ".end method\n\n");
234 fprintf(fp, ".method public abstract invoke%s\n", signature);
235 fprintf(fp, ".end method\n\n");
237 fclose(fp);
240 static void
241 oberon_generate_record_class(oberon_context_t * ctx, oberon_type_t * rec)
243 FILE * fp;
244 char * cname;
245 char * fname;
247 /* Устанавливаем новоый id */
248 rec -> gen_type -> rec_id = rec -> module -> gen_mod -> rec_id;
249 rec -> module -> gen_mod -> rec_id += 1;
251 cname = get_class_full_name(ctx, rec);
252 fname = new_string("%s.j", cname);
254 fp = fopen(fname, "w");
256 fprintf(fp, ".source %s\n", rec -> module -> name);
257 fprintf(fp, ".class public %s\n", cname);
258 fprintf(fp, ".super java/lang/Object\n\n");
260 rec -> gen_type -> fp = fp;
263 void
264 oberon_generator_init_type(oberon_context_t * ctx, oberon_type_t * type)
266 gen_type_t * t = GC_MALLOC(sizeof *t);
267 memset(t, 0, sizeof *t);
268 type -> gen_type = t;
270 switch(type -> class)
272 case OBERON_TYPE_VOID:
273 case OBERON_TYPE_INTEGER:
274 case OBERON_TYPE_BOOLEAN:
275 case OBERON_TYPE_ARRAY:
276 case OBERON_TYPE_REAL:
277 break;
278 case OBERON_TYPE_RECORD:
279 oberon_generate_record_class(ctx, type);
280 break;
281 case OBERON_TYPE_PROCEDURE:
282 oberon_generate_procedure_class(ctx, type);
283 break;
284 case OBERON_TYPE_POINTER:
285 assert(type -> base -> class == OBERON_TYPE_VOID);
286 break;
287 default:
288 oberon_error(ctx, "oberon_generator_init_type: unk calss %i", type -> class);
289 break;
293 static void
294 oberon_generate_object(oberon_context_t * ctx, FILE * fp, oberon_object_t * x)
296 char * name;
297 char * desc;
299 name = x -> name;
300 desc = get_descriptor(ctx, x -> type);
301 switch(x -> class)
303 case OBERON_CLASS_VAR:
304 fprintf(fp, ".field public static %s %s\n\n", name, desc);
305 break;
306 case OBERON_CLASS_FIELD:
307 fprintf(fp, ".field public %s %s\n\n", name, desc);
308 break;
309 default:
310 oberon_error(ctx, "oberon_generate_object: unk class %i", x -> class);
311 break;
315 void
316 oberon_generator_init_record(oberon_context_t * ctx, oberon_type_t * rec)
318 FILE * fp;
320 fp = rec -> gen_type -> fp;
322 int num = rec -> num_decl;
323 oberon_object_t * field = rec -> decl;
324 for(int i = 0; i < num; i++)
326 oberon_generate_object(ctx, fp, field);
327 field = field -> next;
330 fprintf(fp, ".method public <init>()V\n");
331 fprintf(fp, " aload_0\n");
332 fprintf(fp, " invokespecial java/lang/Object/<init>()V\n");
333 fprintf(fp, " return\n");
334 fprintf(fp, ".end method\n");
336 fclose(fp);
339 void
340 oberon_generator_init_var(oberon_context_t * ctx, oberon_object_t * var)
342 gen_var_t * v = GC_MALLOC(sizeof *v);
343 memset(v, 0, sizeof *v);
344 var -> gen_var = v;
346 gen_module_t * m = ctx -> mod -> gen_mod;
348 switch(var -> class)
350 case OBERON_CLASS_VAR_PARAM:
351 oberon_error(ctx, "generator: VAR-parameters not implemented");
352 break;
353 case OBERON_CLASS_PARAM:
354 case OBERON_CLASS_FIELD:
355 break;
356 case OBERON_CLASS_VAR:
357 oberon_generate_object(ctx, m -> fp, var);
358 break;
359 default:
360 oberon_error(ctx, "oberon_generator_init_var: unk var class %i", var -> class);
361 break;
365 void
366 oberon_generator_init_proc(oberon_context_t * ctx, oberon_object_t * proc)
368 gen_proc_t * p = GC_MALLOC(sizeof *p);
369 memset(p, 0, sizeof *p);
370 proc -> gen_proc = p;
372 struct gen_register_file * rf = GC_MALLOC(sizeof *rf);
373 memset(rf, 0, sizeof *rf);
374 p -> rf = rf;
376 if(proc -> local)
378 oberon_error(ctx, "generator: local procedures not implemented");
382 void
383 oberon_generator_init_module(oberon_context_t * ctx, oberon_module_t * mod)
385 gen_module_t * m = GC_MALLOC(sizeof *m);
386 memset(m, 0, sizeof *m);
387 mod -> gen_mod = m;
389 int fnamesz = strlen(mod -> name) + 3;
390 char fname[fnamesz + 1];
391 snprintf(fname, fnamesz, "%s.j", mod -> name);
393 FILE * fp;
394 fp = fopen(fname, "w");
395 assert(fp != NULL);
397 fprintf(fp, ".source %s\n", mod -> name);
398 fprintf(fp, ".class %s\n", mod -> name);
399 fprintf(fp, ".super java/lang/Object\n\n");
401 m -> fp = fp;
404 // =======================================================================
405 // GENERATOR
406 // =======================================================================
408 static void
409 push_expr(oberon_context_t * ctx, FILE * fp, oberon_expr_t * expr);
411 void
412 oberon_generate_begin_module(oberon_context_t * ctx)
414 gen_module_t * m = ctx -> mod -> gen_mod;
415 fprintf(m -> fp, ".method public <init>()V\n");
416 fprintf(m -> fp, " aload_0\n");
417 fprintf(m -> fp, " invokespecial java/lang/Object/<init>()V\n");
420 void
421 oberon_generate_end_module(oberon_context_t * ctx)
423 gen_module_t * m = ctx -> mod -> gen_mod;
425 fprintf(m -> fp, " .limit stack 32\n");
426 fprintf(m -> fp, " .limit locals 32\n");
427 fprintf(m -> fp, " return\n");
428 fprintf(m -> fp, ".end method\n");
431 static int
432 jvm_cell_size_for_type(oberon_type_t * type)
434 if(type -> class == OBERON_TYPE_INTEGER
435 || type -> class == OBERON_TYPE_REAL)
437 if(type -> size > 4)
439 return 2;
443 return 1;
446 static bool
447 jvm_is_wide_type(oberon_type_t * type)
449 int cell;
450 cell = jvm_cell_size_for_type(type);
451 assert(cell <= 2);
452 return (cell == 2);
455 static bool
456 jvm_is_free_register(struct gen_register_file * rf, int i, bool wide)
458 if(wide)
460 assert(i + 1 < MAX_REGISTERS);
461 return !(rf -> reg[i].used || rf -> reg[i + 1].used);
463 else
465 assert(i < MAX_REGISTERS);
466 return !(rf -> reg[i].used);
470 static int
471 jvm_alloc_register(struct gen_register_file * rf, oberon_type_t * type)
473 bool wide;
474 wide = jvm_is_wide_type(type);
476 int i = 0;
477 while(i < MAX_REGISTERS && !jvm_is_free_register(rf, i, wide))
479 i += 1;
482 if(wide)
484 assert(i + 1 <= MAX_REGISTERS);
485 rf -> num_used += 2;
486 rf -> reg[i].used = true;
487 rf -> reg[i + 1].used = true;
488 rf -> reg[i].used = true;
489 rf -> reg[i + 1].wide = false;
491 else
493 assert(i <= MAX_REGISTERS);
494 rf -> num_used += 1;
495 rf -> reg[i].used = true;
496 rf -> reg[i].wide = false;
499 if(rf -> num_used > rf -> max_used)
501 rf -> max_used = rf -> num_used;
504 return i;
507 static void
508 jvm_init_local_object(oberon_context_t * ctx, FILE * fp, oberon_object_t * x)
510 int reg;
511 gen_context_t * c;
512 gen_var_t * v;
513 char * desc;
515 c = ctx -> gen_context;
516 v = x -> gen_var;
517 desc = get_descriptor(ctx, x -> type);
519 reg = -1;
520 switch(x -> class)
522 case OBERON_CLASS_VAR:
523 case OBERON_CLASS_PARAM:
524 if(x -> local)
526 reg = jvm_alloc_register(c -> rf, x -> type);
528 v -> reg = reg;
529 fprintf(fp, ".var %i is %s %s from start to end\n", reg, x -> name, desc);
530 break;
531 default:
532 oberon_error(ctx, "jvm_init_local_object: wat");
533 break;
537 void
538 oberon_generate_begin_proc(oberon_context_t * ctx, oberon_object_t * proc)
540 gen_context_t * c;
541 gen_module_t * m;
542 gen_proc_t * p;
543 char * signature;
545 c = ctx -> gen_context;
546 m = ctx -> mod -> gen_mod;
547 p = proc -> gen_proc;
549 signature = get_procedure_signature(ctx, proc -> type);
550 fprintf(m -> fp, ".method public static %s%s\n", proc -> name, signature);
552 /* Сохраняем регистровый файл в стеке */
553 p -> rf -> up = c -> rf;
554 c -> rf = p -> rf;
556 oberon_object_t * var = proc -> type -> decl;
557 while(var)
559 jvm_init_local_object(ctx, m -> fp, var);
560 var = var -> next;
563 fprintf(m -> fp, "start:\n");
566 void
567 oberon_generate_end_proc(oberon_context_t * ctx)
569 gen_context_t * c;
570 gen_module_t * m;
572 c = ctx -> gen_context;
573 m = ctx -> mod -> gen_mod;
575 fprintf(m -> fp, "end:\n");
576 fprintf(m -> fp, " .limit stack 32\n");
577 fprintf(m -> fp, " .limit locals %i\n", c -> rf -> max_used);
578 fprintf(m -> fp, ".end method\n\n");
580 /* Возвращаем исходный регистровый файл */
581 c -> rf = c -> rf -> up;
584 void
585 oberon_generate_call_proc(oberon_context_t * ctx, oberon_expr_t * desig)
587 oberon_object_t * proc;
588 gen_module_t * m;
589 char * fullname;
590 char * signature;
592 assert(desig -> is_item);
593 assert(desig -> item.mode == MODE_CALL);
595 m = ctx -> mod -> gen_mod;
596 proc = desig -> item.var;
597 fullname = get_field_full_name(ctx, proc);
598 signature = get_procedure_signature(ctx, proc -> type);
600 int num = desig -> item.num_args;
601 oberon_expr_t * arg = desig -> item.args;
602 for(int i = 0; i < num; i++)
604 push_expr(ctx, m -> fp, arg);
605 arg = arg -> next;
608 fprintf(m -> fp, "invokestatic %s%s\n", fullname, signature);
611 void
612 oberon_generate_return(oberon_context_t * ctx, oberon_expr_t * expr)
614 gen_module_t * m;
615 char prefix;
617 m = ctx -> mod -> gen_mod;
619 if(expr)
621 push_expr(ctx, m -> fp, expr);
622 prefix = get_prefix(ctx, expr -> result);
623 fprintf(m -> fp, " %creturn\n", prefix);
625 else
627 fprintf(m -> fp, " return\n");
631 static void
632 push_int(FILE * fp, long i)
634 if(i == -1)
636 fprintf(fp, "iconst_m1\n");
638 else if(i >= 0 && i <= 5)
640 fprintf(fp, "iconst_%li\n", i);
642 else if(i >= -128 && i <= 127)
644 fprintf(fp, "bipush %li\n", i);
646 else if(i >= -32768 && i <= 32767)
648 fprintf(fp, "sipush %li\n", i);
650 else if(i >= -2147483648 && i <= 2147483647)
652 fprintf(fp, "ldc %li\n", i);
654 else
656 fprintf(fp, "ldc2 %li\n", i);
660 static void
661 push_float(FILE * fp, double f, int size)
663 if(size <= 4)
665 if(f == 0.0)
667 fprintf(fp, "fconst_0\n");
669 if(f == 1.0)
671 fprintf(fp, "fconst_1\n");
673 if(f == 2.0)
675 fprintf(fp, "fconst_2\n");
677 else
679 fprintf(fp, "ldc %lf\n", f);
682 else
684 if(f == 0.0)
686 fprintf(fp, "dconst_0\n");
688 if(f == 1.0)
690 fprintf(fp, "dconst_1\n");
692 else
694 fprintf(fp, "ldc2 %lf\n", f);
699 static void
700 push_var(oberon_context_t * ctx, FILE * fp, oberon_object_t * var)
702 if(var -> local)
704 int reg = var -> gen_var -> reg;
705 char prefix = get_prefix(ctx, var -> type);
706 fprintf(fp, "%cload %i\n", prefix, reg);
708 else
710 char * fullname = get_field_full_name(ctx, var);
711 char * desc = get_descriptor(ctx, var -> type);
712 fprintf(fp, "getstatic %s %s\n", fullname, desc);
716 static void
717 push_item(oberon_context_t * ctx, FILE * fp, oberon_item_t * item)
719 switch(item -> mode)
721 case MODE_VAR:
722 push_var(ctx, fp, item -> var);
723 break;
724 case MODE_INTEGER:
725 push_int(fp, item -> integer);
726 break;
727 case MODE_BOOLEAN:
728 push_int(fp, item -> boolean);
729 break;
730 case MODE_CALL:
731 oberon_generate_call_proc(ctx, (oberon_expr_t *) item);
732 break;
733 case MODE_INDEX:
734 oberon_error(ctx, "push_item: TODO index");
735 break;
736 case MODE_FIELD:
737 oberon_error(ctx, "push_item: TODO field");
738 break;
739 case MODE_DEREF:
740 oberon_error(ctx, "push_item: TODO deref");
741 break;
742 case MODE_NIL:
743 fprintf(fp, "aconst_null\n");
744 break;
745 case MODE_NEW:
746 oberon_error(ctx, "push_item: TODO new");
747 break;
748 case MODE_REAL:
749 push_float(fp, item -> real, item -> result -> size);
750 break;
751 default:
752 oberon_error(ctx, "push_item: unk mode %i", item -> mode);
753 break;
757 static int
758 jvm_new_label_id(oberon_context_t * ctx)
760 gen_context_t * c = ctx -> gen_context;
761 int label_id = c -> label_id;
762 c -> label_id += 1;
763 return label_id;
766 static char *
767 jvm_get_label_name(int label_id)
769 return new_string("L%i", label_id);
772 static void
773 jvm_generate_label(FILE * fp, int label_id)
775 fprintf(fp, "L%i:\n", label_id);
778 static void
779 jvm_generate_logical_not(oberon_context_t * ctx, FILE * fp)
781 int label_true = jvm_new_label_id(ctx);
782 int label_false = jvm_new_label_id(ctx);
783 char * label_name_true = jvm_get_label_name(label_true);
784 char * label_name_false = jvm_get_label_name(label_false);
786 fprintf(fp, "ifne %s\n", label_name_false);
787 fprintf(fp, "iconst_1\n");
788 fprintf(fp, "goto %s\n", label_name_true);
789 jvm_generate_label(fp, label_false);
790 fprintf(fp, "iconst_0\n");
791 jvm_generate_label(fp, label_true);
794 static char
795 jvm_get_type_of_prefix(char prefix)
797 switch(prefix)
799 case 'b':
800 return 'B';
801 case 'c':
802 return 'C';
803 case 'd':
804 return 'D';
805 case 'f':
806 return 'F';
807 case 'i':
808 return 'I';
809 case 'l':
810 return 'J';
813 assert(0);
816 static void
817 jvm_generate_abs(FILE * fp, char prefix)
819 char t = jvm_get_type_of_prefix(prefix);
820 fprintf(fp, "invokestatic java/lang/Math/abs(%c)%c\n", t, t);
823 static void
824 jvm_generate_compare_op(oberon_context_t * ctx, FILE *fp, char prefix, int op)
826 int label_true = jvm_new_label_id(ctx);
827 int label_false = jvm_new_label_id(ctx);
828 char * label_name_true = jvm_get_label_name(label_true);
829 char * label_name_false = jvm_get_label_name(label_false);
831 assert(prefix == 'i' || prefix == 'a');
833 switch(op)
835 case OP_EQ:
836 fprintf(fp, "if_%ccmpeq %s\n", prefix, label_name_true);
837 break;
838 case OP_NEQ:
839 fprintf(fp, "if_%ccmpne %s\n", prefix, label_name_true);
840 break;
841 case OP_LSS:
842 fprintf(fp, "if_icmplt %s\n", label_name_true);
843 break;
844 case OP_LEQ:
845 fprintf(fp, "if_icmple %s\n", label_name_true);
846 break;
847 case OP_GRT:
848 fprintf(fp, "if_icmpgt %s\n", label_name_true);
849 break;
850 case OP_GEQ:
851 fprintf(fp, "if_icmpge %s\n", label_name_true);
852 break;
853 default:
854 oberon_error(ctx, "jvm_generate_compare_op: wat");
855 break;
858 fprintf(fp, "iconst_0\n");
859 fprintf(fp, "goto %s\n", label_name_false);
860 jvm_generate_label(fp, label_true);
861 fprintf(fp, "iconst_1\n");
862 jvm_generate_label(fp, label_false);
865 static void
866 jvm_generate_operator(oberon_context_t * ctx, FILE *fp, char prefix, int op)
868 switch(op)
870 case OP_UNARY_MINUS:
871 fprintf(fp, "%cneg\n", prefix);
872 break;
873 case OP_BITWISE_NOT:
874 push_int(fp, -1);
875 fprintf(fp, "%cxor\n", prefix);
876 break;
877 case OP_LOGIC_NOT:
878 jvm_generate_logical_not(ctx, fp);
879 break;
880 case OP_ABS:
881 jvm_generate_abs(fp, prefix);
882 break;
884 case OP_ADD:
885 fprintf(fp, "%cadd\n", prefix);
886 break;
887 case OP_SUB:
888 fprintf(fp, "%csub\n", prefix);
889 break;
890 case OP_MUL:
891 fprintf(fp, "%cmul\n", prefix);
892 break;
893 case OP_DIV:
894 fprintf(fp, "%cdiv\n", prefix);
895 break;
896 case OP_MOD:
897 fprintf(fp, "%crem\n", prefix);
898 break;
899 case OP_BITWISE_AND:
900 fprintf(fp, "%cand\n", prefix);
901 break;
902 case OP_BITWISE_XOR:
903 fprintf(fp, "%cxor\n", prefix);
904 break;
905 case OP_BITWISE_OR:
906 fprintf(fp, "%cor\n", prefix);
907 break;
909 case OP_EQ:
910 case OP_NEQ:
911 case OP_LSS:
912 case OP_LEQ:
913 case OP_GRT:
914 case OP_GEQ:
915 jvm_generate_compare_op(ctx, fp, prefix, op);
916 break;
917 default:
918 oberon_error(ctx, "jvm_generate_operator: unk op %i", op);
919 break;
920 }
923 static void
924 jvm_generate_logical_or(oberon_context_t * ctx, FILE * fp, oberon_expr_t * p, oberon_expr_t * q)
926 int label_calc_q = jvm_new_label_id(ctx);
927 int label_done = jvm_new_label_id(ctx);
928 char * label_name_calc_q = jvm_get_label_name(label_calc_q);
929 char * label_name_done = jvm_get_label_name(label_done);
931 /* p OR q -- если p, то TRUE, иначе q */
933 push_expr(ctx, fp, p);
934 fprintf(fp, "ifne %s\n", label_name_calc_q);
935 fprintf(fp, "iconst_1\n");
936 fprintf(fp, "goto %s\n", label_name_done);
937 jvm_generate_label(fp, label_calc_q);
938 push_expr(ctx, fp, q);
939 jvm_generate_label(fp, label_done);
942 static void
943 jvm_generate_logical_and(oberon_context_t * ctx, FILE * fp, oberon_expr_t * p, oberon_expr_t * q)
945 int label_false = jvm_new_label_id(ctx);
946 int label_done = jvm_new_label_id(ctx);
947 char * label_name_false = jvm_get_label_name(label_false);
948 char * label_name_done = jvm_get_label_name(label_done);
950 /* p AND q -- если p, то q, иначе FALSE */
952 push_expr(ctx, fp, p);
953 fprintf(fp, "ifne %s\n", label_name_false);
954 push_expr(ctx, fp, q);
955 fprintf(fp, "goto %s\n", label_name_done);
956 jvm_generate_label(fp, label_false);
957 fprintf(fp, "iconst_0\n");
958 jvm_generate_label(fp, label_done);
961 static void
962 push_operator(oberon_context_t * ctx, FILE * fp, oberon_oper_t * oper)
964 char prefix = get_prefix(ctx, oper -> result);
965 int op = oper -> op;
966 switch(op)
968 case OP_UNARY_MINUS:
969 case OP_BITWISE_NOT:
970 case OP_LOGIC_NOT:
971 case OP_ABS:
972 push_expr(ctx, fp, oper -> left);
973 jvm_generate_operator(ctx, fp, prefix, op);
974 break;
976 case OP_ADD:
977 case OP_SUB:
978 case OP_MUL:
979 case OP_DIV:
980 case OP_MOD:
981 case OP_BITWISE_AND:
982 case OP_BITWISE_XOR:
983 case OP_BITWISE_OR:
985 case OP_EQ:
986 case OP_NEQ:
987 case OP_LSS:
988 case OP_LEQ:
989 case OP_GRT:
990 case OP_GEQ:
991 push_expr(ctx, fp, oper -> left);
992 push_expr(ctx, fp, oper -> right);
993 jvm_generate_operator(ctx, fp, prefix, op);
994 break;
996 case OP_LOGIC_OR:
997 jvm_generate_logical_or(ctx, fp, oper -> left, oper -> right);
998 break;
999 case OP_LOGIC_AND:
1000 jvm_generate_logical_and(ctx, fp, oper -> left, oper -> right);
1001 break;
1002 default:
1003 oberon_error(ctx, "push_oper: unk op %i", op);
1004 break;
1008 static void
1009 push_expr(oberon_context_t * ctx, FILE * fp, oberon_expr_t * expr)
1011 if(expr -> is_item)
1013 push_item(ctx, fp, (oberon_item_t *) expr);
1015 else
1017 push_operator(ctx, fp, (oberon_oper_t *) expr);
1021 static void
1022 store_expr(oberon_context_t * ctx, FILE * fp, oberon_expr_t * expr)
1024 assert(expr -> is_item);
1025 oberon_item_t * item = (oberon_item_t *) expr;
1027 char prefix;
1028 switch(item -> mode)
1030 case MODE_VAR:
1031 if(item -> var -> local)
1033 int reg = item -> var -> gen_var -> reg;
1034 prefix = get_prefix(ctx, item -> result);
1035 fprintf(fp, "%cstore %i\n", prefix, reg);
1037 else
1039 char * fullname = get_field_full_name(ctx, item -> var);
1040 char * desc = get_descriptor(ctx, item -> result);
1041 fprintf(fp, "putstatic %s %s\n", fullname, desc);
1043 break;
1044 default:
1045 oberon_error(ctx, "store_expr: unk mode %i", item -> mode);
1046 break;
1050 void
1051 oberon_generate_assign(oberon_context_t * ctx, oberon_expr_t * src, oberon_expr_t * dst)
1053 gen_module_t * m;
1054 m = ctx -> mod -> gen_mod;
1056 push_expr(ctx, m -> fp, src);
1057 store_expr(ctx, m -> fp, dst);
1060 void
1061 oberon_generate_code(oberon_context_t * ctx)
1063 printf("generate code\n");
1066 void
1067 oberon_generator_dump(oberon_context_t * ctx, char * path)
1069 printf("jit: dump code\n");
1072 void *
1073 oberon_generator_get_procedure(oberon_context_t * ctx, const char * name)
1075 printf("jit: get pointer to procedure %s\n", name);
1076 return NULL;
1079 void *
1080 oberon_generator_get_var(oberon_context_t * ctx, const char * name)
1082 printf("jit: get pointer to var %s\n", name);
1083 return NULL;