DEADSOFTWARE

JVM: Реализованы локальные переменные
[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 += 2;
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 void
758 push_operator(oberon_context_t * ctx, FILE * fp, oberon_oper_t * oper)
760 char prefix = get_prefix(ctx, oper -> result);
761 switch(oper -> op)
763 case OP_UNARY_MINUS:
764 push_expr(ctx, fp, oper -> left);
765 fprintf(fp, "%cneg\n", prefix);
766 break;
767 case OP_BITWISE_NOT:
768 push_expr(ctx, fp, oper -> left);
769 push_int(fp, -1);
770 fprintf(fp, "%cxor\n", prefix);
771 break;
773 case OP_ADD:
774 push_expr(ctx, fp, oper -> left);
775 push_expr(ctx, fp, oper -> right);
776 fprintf(fp, "%cadd\n", prefix);
777 break;
778 case OP_SUB:
779 push_expr(ctx, fp, oper -> left);
780 push_expr(ctx, fp, oper -> right);
781 fprintf(fp, "%csub\n", prefix);
782 break;
783 case OP_MUL:
784 push_expr(ctx, fp, oper -> left);
785 push_expr(ctx, fp, oper -> right);
786 fprintf(fp, "%cmul\n", prefix);
787 break;
788 case OP_DIV:
789 push_expr(ctx, fp, oper -> left);
790 push_expr(ctx, fp, oper -> right);
791 fprintf(fp, "%cdiv\n", prefix);
792 break;
793 case OP_MOD:
794 push_expr(ctx, fp, oper -> left);
795 push_expr(ctx, fp, oper -> right);
796 fprintf(fp, "%crem\n", prefix);
797 break;
798 case OP_BITWISE_AND:
799 push_expr(ctx, fp, oper -> left);
800 push_expr(ctx, fp, oper -> right);
801 fprintf(fp, "%cand\n", prefix);
802 break;
803 case OP_BITWISE_XOR:
804 push_expr(ctx, fp, oper -> left);
805 push_expr(ctx, fp, oper -> right);
806 fprintf(fp, "%cxor\n", prefix);
807 break;
808 case OP_BITWISE_OR:
809 push_expr(ctx, fp, oper -> left);
810 push_expr(ctx, fp, oper -> right);
811 fprintf(fp, "%cor\n", prefix);
812 break;
814 case OP_EQ:
815 case OP_NEQ:
816 case OP_LSS:
817 case OP_LEQ:
818 case OP_GRT:
819 case OP_GEQ:
820 case OP_LOGIC_NOT:
821 case OP_ABS:
822 oberon_error(ctx, "push_oper: TODO op %i", oper -> op);
823 break;
824 default:
825 oberon_error(ctx, "push_oper: unk op %i", oper -> op);
826 break;
830 static void
831 push_expr(oberon_context_t * ctx, FILE * fp, oberon_expr_t * expr)
833 if(expr -> is_item)
835 push_item(ctx, fp, (oberon_item_t *) expr);
837 else
839 push_operator(ctx, fp, (oberon_oper_t *) expr);
843 static void
844 store_expr(oberon_context_t * ctx, FILE * fp, oberon_expr_t * expr)
846 assert(expr -> is_item);
847 oberon_item_t * item = (oberon_item_t *) expr;
849 char prefix;
850 switch(item -> mode)
852 case MODE_VAR:
853 if(item -> var -> local)
855 int reg = item -> var -> gen_var -> reg;
856 prefix = get_prefix(ctx, item -> result);
857 fprintf(fp, "%cstore %i\n", prefix, reg);
859 else
861 char * fullname = get_field_full_name(ctx, item -> var);
862 char * desc = get_descriptor(ctx, item -> result);
863 fprintf(fp, "putstatic %s %s\n", fullname, desc);
865 break;
866 default:
867 oberon_error(ctx, "store_expr: unk mode %i", item -> mode);
868 break;
872 void
873 oberon_generate_assign(oberon_context_t * ctx, oberon_expr_t * src, oberon_expr_t * dst)
875 gen_module_t * m;
876 m = ctx -> mod -> gen_mod;
878 push_expr(ctx, m -> fp, src);
879 store_expr(ctx, m -> fp, dst);
882 void
883 oberon_generate_code(oberon_context_t * ctx)
885 printf("generate code\n");
888 void
889 oberon_generator_dump(oberon_context_t * ctx, char * path)
891 printf("jit: dump code\n");
894 void *
895 oberon_generator_get_procedure(oberon_context_t * ctx, const char * name)
897 printf("jit: get pointer to procedure %s\n", name);
898 return NULL;
901 void *
902 oberon_generator_get_var(oberon_context_t * ctx, const char * name)
904 printf("jit: get pointer to var %s\n", name);
905 return NULL;