7c426d546c7bdf190f3594e7b5bda31293f89543
11 #include "../../../include/oberon.h"
12 #include "../../oberon-internals.h"
13 #include "generator-jvm.h"
14 #include "generator-jvm-basic.h"
16 // ==========================================
17 // ==========================================
18 // ==========================================
21 jvm_create_proc(struct gen_class
* class)
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
);
41 jvm_generate_function_header(gen_proc_t
* p
, char * access
, char * name
, char * signature
)
43 struct gen_class
* class;
46 /* Делаем процедуру текущей в этом классе */
47 assert(class -> p
== NULL
);
50 fprintf(class -> fp
, ".method %s %s%s\n", access
, name
, signature
);
54 jvm_generate_function_end(gen_proc_t
* p
)
56 struct gen_class
* class;
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");
68 jvm_create_class(char * full_name
)
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");
81 jvm_destroy_class(struct gen_class
* class)
83 assert(class -> p
== NULL
);
88 jvm_generate_field(struct gen_class
* class, char * access
, char * name
, char * desc
)
90 assert(class -> p
== NULL
);
91 fprintf(class -> fp
, ".field %s %s %s\n\n", access
, name
, desc
);
95 jvm_stack_push(gen_proc_t
* p
, unsigned size
)
97 p
-> stack
-> pointer
+= size
;
98 if(p
-> stack
-> pointer
> p
-> stack
-> max_pointer
)
100 p
-> stack
-> max_pointer
= p
-> stack
-> pointer
;
105 jvm_stack_pop(gen_proc_t
* p
, unsigned size
)
107 p
-> stack
-> pointer
-= size
;
108 assert(p
-> stack
-> pointer
>= 0);
112 jvm_generate(gen_proc_t
* p
, unsigned get
, unsigned push
, char * format
, ...)
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
);
127 jvm_generate_push_int(gen_proc_t
* p
, int64_t i
)
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
);
151 jvm_generate(p
, 0, 2, "ldc2 %li", i
);
156 jvm_generate_push_float(gen_proc_t
* p
, double f
, int size
)
162 jvm_generate(p
, 0, 1, "fconst_0");
166 jvm_generate(p
, 0, 1, "fconst_1");
170 jvm_generate(p
, 0, 1, "fconst_2");
174 jvm_generate(p
, 0, 1, "ldc %lf", f
);
181 jvm_generate(p
, 0, 2, "dconst_0");
185 jvm_generate(p
, 0, 2, "dconst_1");
189 jvm_generate(p
, 0, 2, "ldc2 %lf", f
);
195 jvm_new_label_id(gen_proc_t
* p
)
197 int label_id
= p
-> label_id
;
203 jvm_get_label_name(int label_id
)
205 return new_string("L%i", label_id
);
209 jvm_generate_label(gen_proc_t
* p
, int label_id
)
211 jvm_generate(p
, 0, 0, "L%i:", label_id
);
214 // ==========================================
215 // ==========================================
216 // ==========================================
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
;
228 oberon_generator_destroy_context(oberon_context_t
* ctx
)
233 oberon_generate_procedure_class(oberon_type_t
* proc
)
238 struct gen_class
* class;
240 cname
= jvm_get_class_full_name(proc
);
241 class = jvm_create_class(cname
);
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);
263 oberon_generate_record_class(gen_module_t
* m
, oberon_type_t
* rec
)
266 struct gen_class
* class;
268 /* Устанавливаем новоый id */
269 rec
-> gen_type
-> rec_id
= m
-> rec_id
;
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;
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
:
297 case OBERON_TYPE_RECORD
:
300 m
= type
-> module
-> gen_mod
;
301 oberon_generate_record_class(m
, type
);
303 case OBERON_TYPE_PROCEDURE
:
304 oberon_generate_procedure_class(type
);
306 case OBERON_TYPE_POINTER
:
309 gen_error("oberon_generator_init_type: unk calss %i", type
-> class);
315 jvm_generate_object(struct gen_class
* class, oberon_object_t
* x
)
321 desc
= jvm_get_descriptor(x
-> type
);
324 case OBERON_CLASS_VAR
:
327 jvm_generate_field(class, "public static", name
, desc
);
331 gen_error("jvm_generate_object: local variable as class field? wat");
334 case OBERON_CLASS_FIELD
:
335 jvm_generate_field(class, "public", name
, desc
);
338 gen_error("jvm_generate_object: unk class %i", x
-> class);
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);
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
);
374 m
= ctx
-> mod
-> gen_mod
;
376 struct gen_class
* class;
381 case OBERON_CLASS_VAR_PARAM
:
382 gen_error("generator: VAR-parameters not implemented");
384 case OBERON_CLASS_PARAM
:
385 case OBERON_CLASS_FIELD
:
387 case OBERON_CLASS_VAR
:
388 jvm_generate_object(class, var
);
391 gen_error("oberon_generator_init_var: unk var class %i", var
-> class);
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);
404 gen_error("generator: local procedures not implemented");
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
);
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");
424 ctx
-> gen_context
-> current_m
= m
;
428 oberon_generator_fini_module(oberon_module_t
* mod
)
430 jvm_destroy_class(mod
-> gen_mod
-> class);
434 push_expr(gen_proc_t
* p
, oberon_expr_t
* expr
);
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");
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
);
459 jvm_init_local_object(gen_proc_t
* p
, oberon_object_t
* x
)
463 struct gen_class
* class;
467 desc
= jvm_get_descriptor(x
-> type
);
469 // Убеждаемся что сейчас находимся в функции
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
);
481 gen_error("jvm_init_local_object: wat");
487 oberon_generate_begin_proc(oberon_context_t
* ctx
, oberon_object_t
* proc
)
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
;
501 jvm_init_local_object(p
, var
);
507 oberon_generate_end_proc(oberon_context_t
* ctx
)
512 m
= ctx
-> mod
-> gen_mod
;
515 jvm_generate_function_end(p
);
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
;
528 proc
= desig
-> item
.var
;
529 fullname
= jvm_get_field_full_name(proc
);
530 signature
= jvm_get_procedure_signature(proc
-> type
);
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
);
544 jvm_generate(p
, args_cells
, result_cells
, "invokestatic %s%s", fullname
, signature
);
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
);
554 oberon_generate_return(oberon_context_t
* ctx
, oberon_expr_t
* expr
)
561 m
= ctx
-> mod
-> gen_mod
;
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
);
573 jvm_generate(p
, 0, 0, "return");
578 jvm_push_var(gen_proc_t
* p
, oberon_object_t
* var
)
580 int cell_size
= jvm_cell_size_for_type(var
-> type
);
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
);
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
);
597 jvm_generate_new_static(gen_proc_t
* p
, oberon_type_t
* type
, int num
, oberon_expr_t
* arg
)
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 /* ничего не надо делать при статической инициализации */
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
);
618 case OBERON_TYPE_ARRAY
:
619 gen_error("jvm_generate_new_static: TODO array");
622 gen_error("jvm_generate_new_static: unk type class %i", type
-> class);
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
);
635 push_item(gen_proc_t
* p
, oberon_item_t
* item
)
640 jvm_push_var(p
, item
-> var
);
643 jvm_generate_push_int(p
, item
-> integer
);
646 jvm_generate_push_int(p
, item
-> boolean
);
649 jvm_generate_call_proc(p
, (oberon_expr_t
*) item
);
652 gen_error("push_item: TODO index");
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
);
661 /* Все объекты представляются как увказатели */
662 push_item(p
, item
-> parent
);
665 jvm_generate(p
, 0, 1, "aconst_null");
668 jvm_generate_new_pointer(p
, item
-> result
, item
-> num_args
, item
-> args
);
671 jvm_generate_push_float(p
, item
-> real
, item
-> result
-> size
);
674 gen_error("push_item: unk mode %i", item
-> mode
);
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
);
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
);
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
= "";
736 gen_error("jvm_generate_compare_op: wat");
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
);
749 jvm_generate_operator(gen_proc_t
* p
, char prefix
, int op
)
751 int cell_size
= jvm_cell_size_for_prefix(prefix
);
755 jvm_generate(p
, cell_size
, cell_size
, "%cneg", prefix
);
758 jvm_generate_push_int(p
, -1);
759 jvm_generate(p
, 2 * cell_size
, cell_size
, "%cxor", prefix
);
762 jvm_generate_logical_not(p
);
765 jvm_generate_abs(p
, prefix
);
769 jvm_generate(p
, 2 * cell_size
, cell_size
, "%cadd", prefix
);
772 jvm_generate(p
, 2 * cell_size
, cell_size
, "%csub", prefix
);
775 jvm_generate(p
, 2 * cell_size
, cell_size
, "%cmul", prefix
);
778 jvm_generate(p
, 2 * cell_size
, cell_size
, "%cdiv", prefix
);
781 jvm_generate(p
, 2 * cell_size
, cell_size
, "%crem", prefix
);
784 jvm_generate(p
, 2 * cell_size
, cell_size
, "%cand", prefix
);
787 jvm_generate(p
, 2 * cell_size
, cell_size
, "%cxor", prefix
);
790 jvm_generate(p
, 2 * cell_size
, cell_size
, "%cor", prefix
);
799 jvm_generate_compare_op(p
, prefix
, op
);
802 gen_error("jvm_generate_operator: unk op %i", op
);
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 */
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
);
823 jvm_generate_label(p
, label_done
);
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 */
837 jvm_generate(p
, 1, 0, "ifne %s", label_name_false
);
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
);
846 push_operator(gen_proc_t
* p
, oberon_oper_t
* oper
)
848 char prefix
= jvm_get_prefix(oper
-> result
);
856 push_expr(p
, oper
-> left
);
857 jvm_generate_operator(p
, prefix
, op
);
875 push_expr(p
, oper
-> left
);
876 push_expr(p
, oper
-> right
);
877 jvm_generate_operator(p
, prefix
, op
);
881 jvm_generate_logical_or(p
, oper
-> left
, oper
-> right
);
884 jvm_generate_logical_and(p
, oper
-> left
, oper
-> right
);
887 gen_error("push_oper: unk op %i", op
);
893 push_expr(gen_proc_t
* p
, oberon_expr_t
* expr
)
897 push_item(p
, (oberon_item_t
*) expr
);
901 push_operator(p
, (oberon_oper_t
*) expr
);
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
);
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
);
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
);
932 gen_error("store_expr: TODO index");
936 char * fullname
= jvm_get_field_full_name(item
-> var
);
937 char * desc
= jvm_get_descriptor(item
-> result
);
938 push_item(p
, item
-> parent
);
940 jvm_generate(p
, 1 + cell_size
, 0, "putfield %s %s", fullname
, desc
);
944 gen_error("store_expr: unk mode %i", item
-> mode
);
950 oberon_generate_assign(oberon_context_t
* ctx
, oberon_expr_t
* src
, oberon_expr_t
* dst
)
955 m
= ctx
-> mod
-> gen_mod
;
958 store_expr(p
, dst
, src
);
962 oberon_generate_code(oberon_context_t
* ctx
)
964 printf("generate code\n");
968 oberon_generator_dump(oberon_context_t
* ctx
, char * path
)
970 printf("jit: dump code\n");
974 oberon_generator_get_procedure(oberon_context_t
* ctx
, const char * name
)
976 printf("jit: get pointer to procedure %s\n", name
);
981 oberon_generator_get_var(oberon_context_t
* ctx
, const char * name
)
983 printf("jit: get pointer to var %s\n", name
);