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 if(proc -> local)
374 oberon_error(ctx, "generator: local procedures not implemented");
378 void
379 oberon_generator_init_module(oberon_context_t * ctx, oberon_module_t * mod)
381 gen_module_t * m = GC_MALLOC(sizeof *m);
382 memset(m, 0, sizeof *m);
383 mod -> gen_mod = m;
385 int fnamesz = strlen(mod -> name) + 3;
386 char fname[fnamesz + 1];
387 snprintf(fname, fnamesz, "%s.j", mod -> name);
389 FILE * fp;
390 fp = fopen(fname, "w");
391 assert(fp != NULL);
393 fprintf(fp, ".source %s\n", mod -> name);
394 fprintf(fp, ".class %s\n", mod -> name);
395 fprintf(fp, ".super java/lang/Object\n\n");
397 m -> fp = fp;
400 // =======================================================================
401 // GENERATOR
402 // =======================================================================
404 static void
405 push_expr(oberon_context_t * ctx, FILE * fp, oberon_expr_t * expr);
407 void
408 oberon_generate_begin_module(oberon_context_t * ctx)
410 gen_module_t * m = ctx -> mod -> gen_mod;
411 fprintf(m -> fp, ".method public <init>()V\n");
412 fprintf(m -> fp, " aload_0\n");
413 fprintf(m -> fp, " invokespecial java/lang/Object/<init>()V\n");
416 void
417 oberon_generate_end_module(oberon_context_t * ctx)
419 gen_module_t * m = ctx -> mod -> gen_mod;
421 fprintf(m -> fp, " .limit stack 32\n");
422 fprintf(m -> fp, " .limit locals 32\n");
423 fprintf(m -> fp, " return\n");
424 fprintf(m -> fp, ".end method\n");
427 void
428 oberon_generate_begin_proc(oberon_context_t * ctx, oberon_object_t * proc)
430 gen_module_t * m;
431 char * signature;
433 m = ctx -> mod -> gen_mod;
434 signature = get_procedure_signature(ctx, proc -> type);
436 fprintf(m -> fp, ".method public static %s%s\n", proc -> name, signature);
439 void
440 oberon_generate_call_proc(oberon_context_t * ctx, oberon_expr_t * desig)
442 oberon_object_t * proc;
443 gen_module_t * m;
444 char * fullname;
445 char * signature;
447 assert(desig -> is_item);
448 assert(desig -> item.mode == MODE_CALL);
450 m = ctx -> mod -> gen_mod;
451 proc = desig -> item.var;
452 fullname = get_field_full_name(ctx, proc);
453 signature = get_procedure_signature(ctx, proc -> type);
455 int num = desig -> item.num_args;
456 oberon_expr_t * arg = desig -> item.args;
457 for(int i = 0; i < num; i++)
459 push_expr(ctx, m -> fp, arg);
460 arg = arg -> next;
463 fprintf(m -> fp, "invokestatic %s%s\n", fullname, signature);
466 void
467 oberon_generate_end_proc(oberon_context_t * ctx)
469 gen_module_t * m;
470 m = ctx -> mod -> gen_mod;
472 fprintf(m -> fp, " .limit stack 32\n");
473 fprintf(m -> fp, " .limit locals 32\n");
474 fprintf(m -> fp, ".end method\n\n");
477 void
478 oberon_generate_return(oberon_context_t * ctx, oberon_expr_t * expr)
480 gen_module_t * m;
481 char prefix;
483 m = ctx -> mod -> gen_mod;
485 if(expr)
487 push_expr(ctx, m -> fp, expr);
488 prefix = get_prefix(ctx, expr -> result);
489 fprintf(m -> fp, " %creturn\n", prefix);
491 else
493 fprintf(m -> fp, " return\n");
497 static void
498 push_int(FILE * fp, long i)
500 if(i == -1)
502 fprintf(fp, "iconst_m1\n");
504 else if(i >= 0 && i <= 5)
506 fprintf(fp, "iconst_%li\n", i);
508 else if(i >= -128 && i <= 127)
510 fprintf(fp, "bipush %li\n", i);
512 else if(i >= -32768 && i <= 32767)
514 fprintf(fp, "sipush %li\n", i);
516 else if(i >= -2147483648 && i <= 2147483647)
518 fprintf(fp, "ldc %li\n", i);
520 else
522 fprintf(fp, "ldc2 %li\n", i);
526 static void
527 push_float(FILE * fp, double f, int size)
529 if(size <= 4)
531 if(f == 0.0)
533 fprintf(fp, "fconst_0\n");
535 if(f == 1.0)
537 fprintf(fp, "fconst_1\n");
539 if(f == 2.0)
541 fprintf(fp, "fconst_2\n");
543 else
545 fprintf(fp, "ldc %lf\n", f);
548 else
550 if(f == 0.0)
552 fprintf(fp, "dconst_0\n");
554 if(f == 1.0)
556 fprintf(fp, "dconst_1\n");
558 else
560 fprintf(fp, "ldc2 %lf\n", f);
565 static void
566 push_var(oberon_context_t * ctx, FILE * fp, oberon_object_t * var)
568 if(var -> local)
570 int reg = var -> gen_var -> reg;
571 char prefix = get_prefix(ctx, var -> type);
572 fprintf(fp, "%cload %i\n", prefix, reg);
574 else
576 char * fullname = get_field_full_name(ctx, var);
577 char * desc = get_descriptor(ctx, var -> type);
578 fprintf(fp, "getstatic %s %s\n", fullname, desc);
582 static void
583 push_item(oberon_context_t * ctx, FILE * fp, oberon_item_t * item)
585 switch(item -> mode)
587 case MODE_VAR:
588 push_var(ctx, fp, item -> var);
589 break;
590 case MODE_INTEGER:
591 push_int(fp, item -> integer);
592 break;
593 case MODE_BOOLEAN:
594 push_int(fp, item -> boolean);
595 break;
596 case MODE_CALL:
597 oberon_generate_call_proc(ctx, (oberon_expr_t *) item);
598 break;
599 case MODE_INDEX:
600 oberon_error(ctx, "push_item: TODO index");
601 break;
602 case MODE_FIELD:
603 oberon_error(ctx, "push_item: TODO field");
604 break;
605 case MODE_DEREF:
606 oberon_error(ctx, "push_item: TODO deref");
607 break;
608 case MODE_NIL:
609 fprintf(fp, "aconst_null\n");
610 break;
611 case MODE_NEW:
612 oberon_error(ctx, "push_item: TODO new");
613 break;
614 case MODE_REAL:
615 push_float(fp, item -> real, item -> result -> size);
616 break;
617 default:
618 oberon_error(ctx, "push_item: unk mode %i", item -> mode);
619 break;
623 static void
624 push_operator(oberon_context_t * ctx, FILE * fp, oberon_oper_t * oper)
626 char prefix = get_prefix(ctx, oper -> result);
627 switch(oper -> op)
629 case OP_UNARY_MINUS:
630 push_expr(ctx, fp, oper -> left);
631 fprintf(fp, "%cneg\n", prefix);
632 break;
633 case OP_BITWISE_NOT:
634 push_expr(ctx, fp, oper -> left);
635 push_int(fp, -1);
636 fprintf(fp, "%cxor\n", prefix);
637 break;
639 case OP_ADD:
640 push_expr(ctx, fp, oper -> left);
641 push_expr(ctx, fp, oper -> right);
642 fprintf(fp, "%cadd\n", prefix);
643 break;
644 case OP_SUB:
645 push_expr(ctx, fp, oper -> left);
646 push_expr(ctx, fp, oper -> right);
647 fprintf(fp, "%csub\n", prefix);
648 break;
649 case OP_MUL:
650 push_expr(ctx, fp, oper -> left);
651 push_expr(ctx, fp, oper -> right);
652 fprintf(fp, "%cmul\n", prefix);
653 break;
654 case OP_DIV:
655 push_expr(ctx, fp, oper -> left);
656 push_expr(ctx, fp, oper -> right);
657 fprintf(fp, "%cdiv\n", prefix);
658 break;
659 case OP_MOD:
660 push_expr(ctx, fp, oper -> left);
661 push_expr(ctx, fp, oper -> right);
662 fprintf(fp, "%crem\n", prefix);
663 break;
664 case OP_BITWISE_AND:
665 push_expr(ctx, fp, oper -> left);
666 push_expr(ctx, fp, oper -> right);
667 fprintf(fp, "%cand\n", prefix);
668 break;
669 case OP_BITWISE_XOR:
670 push_expr(ctx, fp, oper -> left);
671 push_expr(ctx, fp, oper -> right);
672 fprintf(fp, "%cxor\n", prefix);
673 break;
674 case OP_BITWISE_OR:
675 push_expr(ctx, fp, oper -> left);
676 push_expr(ctx, fp, oper -> right);
677 fprintf(fp, "%cor\n", prefix);
678 break;
680 case OP_EQ:
681 case OP_NEQ:
682 case OP_LSS:
683 case OP_LEQ:
684 case OP_GRT:
685 case OP_GEQ:
686 case OP_LOGIC_NOT:
687 case OP_ABS:
688 oberon_error(ctx, "push_oper: TODO op %i", oper -> op);
689 break;
690 default:
691 oberon_error(ctx, "push_oper: unk op %i", oper -> op);
692 break;
696 static void
697 push_expr(oberon_context_t * ctx, FILE * fp, oberon_expr_t * expr)
699 if(expr -> is_item)
701 push_item(ctx, fp, (oberon_item_t *) expr);
703 else
705 push_operator(ctx, fp, (oberon_oper_t *) expr);
709 static void
710 store_expr(oberon_context_t * ctx, FILE * fp, oberon_expr_t * expr)
712 assert(expr -> is_item);
713 oberon_item_t * item = (oberon_item_t *) expr;
715 char prefix;
716 switch(item -> mode)
718 case MODE_VAR:
719 if(item -> var -> local)
721 int reg = item -> var -> gen_var -> reg;
722 prefix = get_prefix(ctx, item -> result);
723 fprintf(fp, "%cstore %i\n", prefix, reg);
725 else
727 char * fullname = get_field_full_name(ctx, item -> var);
728 char * desc = get_descriptor(ctx, item -> result);
729 fprintf(fp, "putstatic %s %s\n", fullname, desc);
731 break;
732 default:
733 oberon_error(ctx, "store_expr: unk mode %i", item -> mode);
734 break;
738 void
739 oberon_generate_assign(oberon_context_t * ctx, oberon_expr_t * src, oberon_expr_t * dst)
741 gen_module_t * m;
742 m = ctx -> mod -> gen_mod;
744 push_expr(ctx, m -> fp, src);
745 store_expr(ctx, m -> fp, dst);
748 void
749 oberon_generate_code(oberon_context_t * ctx)
751 printf("generate code\n");
754 void
755 oberon_generator_dump(oberon_context_t * ctx, char * path)
757 printf("jit: dump code\n");
760 void *
761 oberon_generator_get_procedure(oberon_context_t * ctx, const char * name)
763 printf("jit: get pointer to procedure %s\n", name);
764 return NULL;
767 void *
768 oberon_generator_get_var(oberon_context_t * ctx, const char * name)
770 printf("jit: get pointer to var %s\n", name);
771 return NULL;