9 #include "../../../include/oberon.h"
10 #include "../../oberon-internals.h"
11 #include "generator-jvm.h"
14 new_string(const char * format
, ...)
17 va_start(ptr
, format
);
20 vsnprintf(buf
, 1024, format
, ptr
);
28 result
= GC_MALLOC(size
+ 1);
29 memset(result
, 0, size
);
30 strncpy(result
, buf
, size
);
36 oberon_generator_init_context(oberon_context_t
* ctx
)
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
;
45 oberon_generator_destroy_context(oberon_context_t
* ctx
)
47 ctx
-> gen_context
= NULL
;
50 static char * get_class_full_name(oberon_context_t
* ctx
, oberon_type_t
* type
);
53 get_descriptor(oberon_context_t
* ctx
, oberon_type_t
* type
)
59 case OBERON_TYPE_VOID
:
60 return new_string("V");
62 case OBERON_TYPE_INTEGER
:
66 return new_string("B");
69 return new_string("S");
72 return new_string("I");
75 return new_string("J");
78 oberon_error(ctx
, "get_descriptor: unsupported int size %i", type
-> size
);
82 case OBERON_TYPE_REAL
:
86 return new_string("F");
89 return new_string("D");
92 oberon_error(ctx
, "get_descriptor: unsupported float size %i", type
-> size
);
96 case OBERON_TYPE_BOOLEAN
:
97 return new_string("Z");
99 case OBERON_TYPE_POINTER
:
100 return get_descriptor(ctx
, type
-> base
);
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
);
107 case OBERON_TYPE_ARRAY
:
108 desc
= get_descriptor(ctx
, type
-> base
);
109 return new_string("[%s", desc
);
112 oberon_error(ctx
, "print_descriptor: unsupported type class %i", type
-> class);
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');
129 case OBERON_TYPE_PROCEDURE
:
130 case OBERON_TYPE_ARRAY
:
131 case OBERON_TYPE_RECORD
:
132 case OBERON_TYPE_POINTER
:
135 case OBERON_TYPE_REAL
:
136 return (size
<= 4) ? ('f') : ('d');
140 oberon_error(ctx
, "get_prefix: wat");
145 get_field_full_name(oberon_context_t
* ctx
, oberon_object_t
* x
)
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
);
157 oberon_error(ctx
, "get_field_full_name: wat");
165 get_class_full_name(oberon_context_t
* ctx
, oberon_type_t
* type
)
170 switch(type
-> class)
172 case OBERON_TYPE_PROCEDURE
:
173 name
= new_string("SYSTEM$PROCEDURE");
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
);
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
);
194 oberon_error(ctx
, "get_record_full_name: unk type class %i", type
-> class);
202 get_procedure_signature(oberon_context_t
* ctx
, oberon_type_t
* proc
)
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
);
218 desc
= get_descriptor(ctx
, proc
-> base
);
219 signature
= new_string("%s)%s", signature
, desc
);
225 oberon_generate_procedure_class(oberon_context_t
* ctx
, oberon_type_t
* proc
)
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");
256 oberon_generate_record_class(oberon_context_t
* ctx
, oberon_type_t
* rec
)
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
;
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
:
293 case OBERON_TYPE_RECORD
:
294 oberon_generate_record_class(ctx
, type
);
296 case OBERON_TYPE_PROCEDURE
:
297 oberon_generate_procedure_class(ctx
, type
);
299 case OBERON_TYPE_POINTER
:
302 oberon_error(ctx
, "oberon_generator_init_type: unk calss %i", type
-> class);
308 oberon_generate_object(oberon_context_t
* ctx
, FILE * fp
, oberon_object_t
* x
)
314 desc
= get_descriptor(ctx
, x
-> type
);
317 case OBERON_CLASS_VAR
:
320 fprintf(fp
, ".field public static %s %s\n\n", name
, desc
);
323 case OBERON_CLASS_FIELD
:
324 fprintf(fp
, ".field public %s %s\n\n", name
, desc
);
327 oberon_error(ctx
, "oberon_generate_object: unk class %i", x
-> class);
333 oberon_generator_init_record(oberon_context_t
* ctx
, oberon_type_t
* rec
)
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");
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
);
363 gen_module_t
* m
= ctx
-> mod
-> gen_mod
;
367 case OBERON_CLASS_VAR_PARAM
:
368 oberon_error(ctx
, "generator: VAR-parameters not implemented");
370 case OBERON_CLASS_PARAM
:
371 case OBERON_CLASS_FIELD
:
373 case OBERON_CLASS_VAR
:
374 oberon_generate_object(ctx
, m
-> fp
, var
);
377 oberon_error(ctx
, "oberon_generator_init_var: unk var class %i", var
-> class);
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
);
395 oberon_error(ctx
, "generator: local procedures not implemented");
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
);
406 int fnamesz
= strlen(mod
-> name
) + 3;
407 char fname
[fnamesz
+ 1];
408 snprintf(fname
, fnamesz
, "%s.j", mod
-> name
);
411 fp
= fopen(fname
, "w");
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");
421 // =======================================================================
423 // =======================================================================
426 push_expr(oberon_context_t
* ctx
, FILE * fp
, oberon_expr_t
* expr
);
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");
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");
449 jvm_cell_size_for_type(oberon_type_t
* type
)
451 if(type
-> class == OBERON_TYPE_INTEGER
452 || type
-> class == OBERON_TYPE_REAL
)
464 jvm_is_wide_type(oberon_type_t
* type
)
467 cell
= jvm_cell_size_for_type(type
);
473 jvm_is_free_register(struct gen_register_file
* rf
, int i
, bool wide
)
477 assert(i
+ 1 < MAX_REGISTERS
);
478 return !(rf
-> reg
[i
].used
|| rf
-> reg
[i
+ 1].used
);
482 assert(i
< MAX_REGISTERS
);
483 return !(rf
-> reg
[i
].used
);
488 jvm_alloc_register(struct gen_register_file
* rf
, oberon_type_t
* type
)
491 wide
= jvm_is_wide_type(type
);
494 while(i
< MAX_REGISTERS
&& !jvm_is_free_register(rf
, i
, wide
))
501 assert(i
+ 1 <= MAX_REGISTERS
);
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;
510 assert(i
<= MAX_REGISTERS
);
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
;
525 jvm_init_local_object(oberon_context_t
* ctx
, FILE * fp
, oberon_object_t
* x
)
532 c
= ctx
-> gen_context
;
534 desc
= get_descriptor(ctx
, x
-> type
);
539 case OBERON_CLASS_VAR
:
540 case OBERON_CLASS_PARAM
:
543 reg
= jvm_alloc_register(c
-> rf
, x
-> type
);
546 fprintf(fp
, ".var %i is %s %s from start to end\n", reg
, x
-> name
, desc
);
549 oberon_error(ctx
, "jvm_init_local_object: wat");
555 oberon_generate_begin_proc(oberon_context_t
* ctx
, oberon_object_t
* proc
)
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
;
573 oberon_object_t
* var
= proc
-> type
-> decl
;
576 jvm_init_local_object(ctx
, m
-> fp
, var
);
580 fprintf(m
-> fp
, "start:\n");
584 oberon_generate_end_proc(oberon_context_t
* ctx
)
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
;
602 oberon_generate_call_proc(oberon_context_t
* ctx
, oberon_expr_t
* desig
)
604 oberon_object_t
* proc
;
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
);
625 fprintf(m
-> fp
, "invokestatic %s%s\n", fullname
, signature
);
629 oberon_generate_return(oberon_context_t
* ctx
, oberon_expr_t
* expr
)
634 m
= ctx
-> mod
-> gen_mod
;
638 push_expr(ctx
, m
-> fp
, expr
);
639 prefix
= get_prefix(ctx
, expr
-> result
);
640 fprintf(m
-> fp
, " %creturn\n", prefix
);
644 fprintf(m
-> fp
, " return\n");
649 push_int(FILE * fp
, long i
)
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
);
673 fprintf(fp
, "ldc2 %li\n", i
);
678 push_float(FILE * fp
, double f
, int size
)
684 fprintf(fp
, "fconst_0\n");
688 fprintf(fp
, "fconst_1\n");
692 fprintf(fp
, "fconst_2\n");
696 fprintf(fp
, "ldc %lf\n", f
);
703 fprintf(fp
, "dconst_0\n");
707 fprintf(fp
, "dconst_1\n");
711 fprintf(fp
, "ldc2 %lf\n", f
);
717 push_var(oberon_context_t
* ctx
, FILE * fp
, oberon_object_t
* var
)
721 int reg
= var
-> gen_var
-> reg
;
722 char prefix
= get_prefix(ctx
, var
-> type
);
723 fprintf(fp
, "%cload %i\n", prefix
, reg
);
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
);
734 jvm_generate_new_static(oberon_context_t
* ctx
, FILE * fp
, oberon_type_t
* type
, int num
, oberon_expr_t
* arg
)
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 /* ничего не генерируем */
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
);
755 case OBERON_TYPE_ARRAY
:
756 oberon_error(ctx
, "jvm_generate_new_static: TODO array");
759 oberon_error(ctx
, "jvm_generate_new_static: unk type class %i", type
-> class);
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
);
772 push_item(oberon_context_t
* ctx
, FILE * fp
, oberon_item_t
* item
)
777 push_var(ctx
, fp
, item
-> var
);
780 push_int(fp
, item
-> integer
);
783 push_int(fp
, item
-> boolean
);
786 oberon_generate_call_proc(ctx
, (oberon_expr_t
*) item
);
789 oberon_error(ctx
, "push_item: TODO index");
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
);
798 /* Все объекты представляются как увказатели */
799 push_item(ctx
, fp
, item
-> parent
);
802 fprintf(fp
, "aconst_null\n");
805 jvm_generate_new_pointer(ctx
, fp
, item
-> result
, item
-> num_args
, item
-> args
);
808 push_float(fp
, item
-> real
, item
-> result
-> size
);
811 oberon_error(ctx
, "push_item: unk mode %i", item
-> mode
);
817 jvm_new_label_id(oberon_context_t
* ctx
)
819 gen_context_t
* c
= ctx
-> gen_context
;
820 int label_id
= c
-> label_id
;
826 jvm_get_label_name(int label_id
)
828 return new_string("L%i", label_id
);
832 jvm_generate_label(FILE * fp
, int label_id
)
834 fprintf(fp
, "L%i:\n", label_id
);
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
);
854 jvm_get_type_of_prefix(char prefix
)
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
);
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');
895 fprintf(fp
, "if_%ccmpeq %s\n", prefix
, label_name_true
);
898 fprintf(fp
, "if_%ccmpne %s\n", prefix
, label_name_true
);
901 fprintf(fp
, "if_icmplt %s\n", label_name_true
);
904 fprintf(fp
, "if_icmple %s\n", label_name_true
);
907 fprintf(fp
, "if_icmpgt %s\n", label_name_true
);
910 fprintf(fp
, "if_icmpge %s\n", label_name_true
);
913 oberon_error(ctx
, "jvm_generate_compare_op: wat");
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
);
925 jvm_generate_operator(oberon_context_t
* ctx
, FILE *fp
, char prefix
, int op
)
930 fprintf(fp
, "%cneg\n", prefix
);
934 fprintf(fp
, "%cxor\n", prefix
);
937 jvm_generate_logical_not(ctx
, fp
);
940 jvm_generate_abs(fp
, prefix
);
944 fprintf(fp
, "%cadd\n", prefix
);
947 fprintf(fp
, "%csub\n", prefix
);
950 fprintf(fp
, "%cmul\n", prefix
);
953 fprintf(fp
, "%cdiv\n", prefix
);
956 fprintf(fp
, "%crem\n", prefix
);
959 fprintf(fp
, "%cand\n", prefix
);
962 fprintf(fp
, "%cxor\n", prefix
);
965 fprintf(fp
, "%cor\n", prefix
);
974 jvm_generate_compare_op(ctx
, fp
, prefix
, op
);
977 oberon_error(ctx
, "jvm_generate_operator: unk op %i", op
);
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
);
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
);
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
;
1027 case OP_UNARY_MINUS
:
1028 case OP_BITWISE_NOT
:
1031 push_expr(ctx
, fp
, oper
-> left
);
1032 jvm_generate_operator(ctx
, fp
, prefix
, op
);
1040 case OP_BITWISE_AND
:
1041 case OP_BITWISE_XOR
:
1050 push_expr(ctx
, fp
, oper
-> left
);
1051 push_expr(ctx
, fp
, oper
-> right
);
1052 jvm_generate_operator(ctx
, fp
, prefix
, op
);
1056 jvm_generate_logical_or(ctx
, fp
, oper
-> left
, oper
-> right
);
1059 jvm_generate_logical_and(ctx
, fp
, oper
-> left
, oper
-> right
);
1062 oberon_error(ctx
, "push_oper: unk op %i", op
);
1068 push_expr(oberon_context_t
* ctx
, FILE * fp
, oberon_expr_t
* expr
)
1072 push_item(ctx
, fp
, (oberon_item_t
*) expr
);
1076 push_operator(ctx
, fp
, (oberon_oper_t
*) expr
);
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
;
1087 switch(item
-> mode
)
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
);
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
);
1105 oberon_error(ctx
, "store_expr: TODO index");
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
);
1120 oberon_error(ctx
, "store_expr: unk mode %i", item
-> mode
);
1126 oberon_generate_assign(oberon_context_t
* ctx
, oberon_expr_t
* src
, oberon_expr_t
* dst
)
1129 m
= ctx
-> mod
-> gen_mod
;
1131 store_expr(ctx
, m
-> fp
, dst
, src
);
1135 oberon_generate_code(oberon_context_t
* ctx
)
1137 printf("generate code\n");
1141 oberon_generator_dump(oberon_context_t
* ctx
, char * path
)
1143 printf("jit: dump code\n");
1147 oberon_generator_get_procedure(oberon_context_t
* ctx
, const char * name
)
1149 printf("jit: get pointer to procedure %s\n", name
);
1154 oberon_generator_get_var(oberon_context_t
* ctx
, const char * name
)
1156 printf("jit: get pointer to var %s\n", name
);