11 #include "../../oberon-internals.h"
12 #include "generator-jvm.h"
13 #include "generator-jvm-abi.h"
14 #include "generator-jvm-asm.h"
15 #include "generator-jvm-basic.h"
18 push_item(gen_proc_t
* p
, oberon_item_t
* item
);
21 jvm_generate_new(gen_proc_t
* p
, oberon_type_t
* type
, int num
);
24 * Генерирует код для инициализации массива со статическим базовым типом
29 jvm_generate_array_initialization(gen_proc_t
* p
, oberon_type_t
* arr
)
32 oberon_type_t
* base
= arr
;
33 while(base
-> class == OBERON_TYPE_ARRAY
)
39 if(base
-> class != OBERON_TYPE_RECORD
)
41 jvm_generate(p
, 1, 0, "pop");
53 reg_dst
= jvm_alloc_register_untyped(p
-> rf
, false);
54 jvm_generate(p
, 1, 0, "astore %i", reg_dst
);
57 * Входящие параметры заграблены.
58 * Теперь генерируем эквивалентный код:
60 * int len = dst.length
65 * dst[i, ...] = new record;
70 * Где "..." такой же код (начало и конец) для следующей размерности.
73 for(int i
= 0; i
< dim
; i
++)
75 loop
[i
].reg_index
= jvm_alloc_register_untyped(p
-> rf
, false);
76 loop
[i
].reg_length
= jvm_alloc_register_untyped(p
-> rf
, false);
77 loop
[i
].start
= jvm_new_label_id(p
);
78 loop
[i
].end
= jvm_new_label_id(p
);
80 jvm_generate(p
, 0, 1, "iconst_0");
81 jvm_generate(p
, 1, 0, "istore %i", loop
[i
].reg_index
);
83 jvm_generate(p
, 0, 1, "aload %i", reg_dst
);
84 jvm_generate(p
, 1, 1, "arraylength");
85 jvm_generate(p
, 1, 0, "istore %i", loop
[i
].reg_length
);
87 /* if(i >= len) goto end; */
88 jvm_generate_label(p
, loop
[i
].start
);
89 jvm_generate(p
, 0, 1, "iload %i", loop
[i
].reg_index
);
90 jvm_generate(p
, 0, 1, "iload %i", loop
[i
].reg_length
);
91 jvm_generate(p
, 2, 0, "if_icmpge L%i", loop
[i
].end
);
94 jvm_generate(p
, 0, 1, "aload %i", reg_dst
);
95 jvm_generate(p
, 0, 1, "iload %i", loop
[0].reg_index
);
96 for(int i
= 1; i
< dim
; i
++)
98 jvm_generate(p
, 2, 1, "aaload");
99 jvm_generate(p
, 0, 1, "iload %i", loop
[i
].reg_index
);
101 jvm_generate_new(p
, base
, 0);
102 jvm_generate(p
, 3, 0, "aastore");
104 for(int i
= dim
- 1; i
>= 0; i
--)
106 jvm_generate(p
, 0, 0, "iinc %i 1", loop
[i
].reg_index
);
107 jvm_generate(p
, 0, 0, "goto L%i", loop
[i
].start
);
108 jvm_generate_label(p
, loop
[i
].end
);
113 jvm_generate_new(gen_proc_t
* p
, oberon_type_t
* type
, int num
)
118 oberon_type_t
* base
;
120 switch(type
-> class)
122 case OBERON_TYPE_INTEGER
:
123 case OBERON_TYPE_BOOLEAN
:
124 case OBERON_TYPE_PROCEDURE
:
125 case OBERON_TYPE_REAL
:
126 case OBERON_TYPE_POINTER
:
127 gen_error("jvm_generate_new_static: static alocation not allowed");
129 case OBERON_TYPE_RECORD
:
131 cname
= jvm_get_class_full_name(type
);
132 jvm_generate(p
, 0, 1, "new %s", cname
);
133 jvm_generate(p
, 1, 2, "dup");
134 jvm_generate(p
, 1, 0, "invokespecial %s/<init>()V", cname
);
136 case OBERON_TYPE_ARRAY
:
139 desc
= jvm_get_descriptor(type
);
140 while(base
-> class == OBERON_TYPE_ARRAY
)
144 assert(base
-> size
== 0);
149 assert(base
-> size
> 0);
150 jvm_generate_push_int(p
, base
-> size
);
157 jvm_generate(p
, dim
, 1, "multianewarray %s %i", desc
, dim
);
158 jvm_generate(p
, 1, 2, "dup");
159 jvm_generate_array_initialization(p
, type
);
162 gen_error("jvm_generate_new_static: unk type class %i", type
-> class);
168 * Генерирует код для копирования полей из первой записи во вторую.
169 * ( aref_dst aref_src -- )
174 jvm_generate_copy_record(gen_proc_t
* p
, oberon_type_t
* rec
)
176 assert(rec
-> class == OBERON_TYPE_RECORD
);
177 char * desc
= jvm_get_descriptor(rec
);
178 char * cname
= jvm_get_class_full_name(rec
);
179 jvm_generate(p
, 1 + 1, 0, "invokestatic %s/$COPY$(%s%s)V", cname
, desc
, desc
);
183 * Генерирует кода для копирования массивов.
184 * ( aref_dst aref_src -- )
189 jvm_generate_copy_array(gen_proc_t
* p
, oberon_type_t
* arr
)
192 oberon_type_t
* base
= arr
;
193 while(base
-> class == OBERON_TYPE_ARRAY
)
206 int reg_dst
= jvm_alloc_register_untyped(p
-> rf
, false);
207 int reg_src
= jvm_alloc_register_untyped(p
-> rf
, false);
208 jvm_generate(p
, 1, 0, "astore %i", reg_src
);
209 jvm_generate(p
, 1, 0, "astore %i", reg_dst
);
212 * Входящие параметры заграблены.
213 * Теперь генерируем эквивалентный код:
215 * int len = src.length
220 * copy from src[i, ...] to dst[i, ...];
225 * Где "..." такой же код (начало и конец) для следующей размерности.
228 for(int i
= 0; i
< dim
; i
++)
230 loop
[i
].reg_index
= jvm_alloc_register_untyped(p
-> rf
, false);
231 loop
[i
].reg_length
= jvm_alloc_register_untyped(p
-> rf
, false);
232 loop
[i
].start
= jvm_new_label_id(p
);
233 loop
[i
].end
= jvm_new_label_id(p
);
235 jvm_generate(p
, 0, 1, "iconst_0");
236 jvm_generate(p
, 1, 0, "istore %i", loop
[i
].reg_index
);
238 jvm_generate(p
, 0, 1, "aload %i", reg_src
);
239 jvm_generate(p
, 1, 1, "arraylength");
240 jvm_generate(p
, 1, 0, "istore %i", loop
[i
].reg_length
);
242 /* if(i >= len) goto end; */
243 jvm_generate_label(p
, loop
[i
].start
);
244 jvm_generate(p
, 0, 1, "iload %i", loop
[i
].reg_index
);
245 jvm_generate(p
, 0, 1, "iload %i", loop
[i
].reg_length
);
246 jvm_generate(p
, 2, 0, "if_icmpge L%i", loop
[i
].end
);
249 if(base
-> class == OBERON_TYPE_RECORD
)
251 /* Получаем записи по индексам ( -- dst src ) */
253 jvm_generate(p
, 0, 1, "aload %i", reg_dst
);
254 for(int i
= 0; i
< dim
; i
++)
256 jvm_generate(p
, 0, 1, "iload %i", loop
[i
].reg_index
);
257 jvm_generate(p
, 2, 1, "aaload");
260 jvm_generate(p
, 0, 1, "aload %i", reg_src
);
261 for(int i
= 0; i
< dim
; i
++)
263 jvm_generate(p
, 0, 1, "iload %i", loop
[i
].reg_index
);
264 jvm_generate(p
, 2, 1, "aaload");
267 /* Копируем записи ( dst src -- ) */
268 jvm_generate_copy_record(p
, base
);
272 char postfix
= jvm_get_postfix(base
);
273 int cell_size
= jvm_cell_size_for_postfix(postfix
);
275 /* Получаем массивы и индексы ( -- dst i src i ) */
277 jvm_generate(p
, 0, 1, "aload %i", reg_dst
);
278 jvm_generate(p
, 0, 1, "iload %i", loop
[0].reg_index
);
279 for(int i
= 1; i
< dim
; i
++)
281 jvm_generate(p
, 2, 1, "aaload");
282 jvm_generate(p
, 0, 1, "iload %i", loop
[i
].reg_index
);
285 jvm_generate(p
, 0, 1, "aload %i", reg_src
);
286 jvm_generate(p
, 0, 1, "iload %i", loop
[0].reg_index
);
287 for(int i
= 1; i
< dim
; i
++)
289 jvm_generate(p
, 2, 1, "aaload");
290 jvm_generate(p
, 0, 1, "iload %i", loop
[i
].reg_index
);
293 /* Копируем значения ( dst i src i -- ) */
294 jvm_generate(p
, 2, cell_size
, "%caload", postfix
);
295 jvm_generate(p
, 2 + cell_size
, 0, "%castore", postfix
);
298 for(int i
= dim
- 1; i
>= 0; i
--)
300 jvm_generate(p
, 0, 0, "iinc %i 1", loop
[i
].reg_index
);
301 jvm_generate(p
, 0, 0, "goto L%i", loop
[i
].start
);
302 jvm_generate_label(p
, loop
[i
].end
);
307 jvm_generate_push_procedure_pointer(gen_proc_t
* p
, oberon_object_t
* proc
)
309 char * full_name
= jvm_get_field_full_name_safe(proc
);
310 char * desc
= jvm_get_descriptor(proc
-> type
);
311 jvm_generate(p
, 0, 1, "getstatic %s/pointer %s", full_name
, desc
);
315 oberon_generator_init_context(oberon_context_t
* ctx
)
317 gen_context_t
* gen_context
= GC_MALLOC(sizeof *gen_context
);
318 memset(gen_context
, 0, sizeof *gen_context
);
320 ctx
-> gen_context
= gen_context
;
321 gen_context
-> dir
= ".";
325 oberon_generator_destroy_context(oberon_context_t
* ctx
)
330 oberon_generate_procedure_class(const char * dir
, oberon_type_t
* proc
)
335 struct gen_class
* class;
337 cname
= jvm_get_class_full_name(proc
);
338 class = jvm_create_class(dir
, cname
);
341 fprintf(fp
, ".source SYSTEM\n");
342 fprintf(fp
, ".class public abstract %s\n", cname
);
343 fprintf(fp
, ".super java/lang/Object\n\n");
345 fprintf(fp
, ".method <init>()V\n");
346 fprintf(fp
, " aload_0\n");
347 fprintf(fp
, " invokespecial java/lang/Object/<init>()V\n");
348 fprintf(fp
, " return\n");
349 fprintf(fp
, ".end method\n\n");
351 signature
= jvm_get_procedure_signature(proc
);
353 fprintf(fp
, ".method public abstract invoke%s\n", signature
);
354 fprintf(fp
, ".end method\n\n");
356 jvm_destroy_class(class);
360 oberon_generate_procedure_pointer_class(const char * dir
, oberon_object_t
* proc
)
367 struct gen_class
* class;
369 cname
= jvm_get_field_full_name_safe(proc
);
370 class = jvm_create_class(dir
, cname
);
371 abscname
= jvm_get_class_full_name(proc
-> type
);
372 absdesc
= jvm_get_descriptor(proc
-> type
);
375 fprintf(fp
, ".source %s\n", proc
-> module
-> name
);
376 fprintf(fp
, ".class public %s\n", cname
);
377 fprintf(fp
, ".super %s\n\n", abscname
);
379 fprintf(fp
, ".field public static pointer %s\n\n", absdesc
);
381 fprintf(fp
, ".method private <init>()V\n");
382 fprintf(fp
, " aload_0\n");
383 fprintf(fp
, " invokespecial %s/<init>()V\n", abscname
);
384 fprintf(fp
, " return\n");
385 fprintf(fp
, ".end method\n\n");
387 fprintf(fp
, ".method static <clinit>()V\n");
388 fprintf(fp
, " .limit stack 2\n");
389 fprintf(fp
, " new %s\n", cname
);
390 fprintf(fp
, " dup\n");
391 fprintf(fp
, " invokespecial %s/<init>()V\n", cname
);
392 fprintf(fp
, " putstatic %s/pointer %s\n", cname
, absdesc
);
393 fprintf(fp
, " return\n");
394 fprintf(fp
, ".end method\n\n");
396 signature
= jvm_get_procedure_signature(proc
-> type
);
398 gen_proc_t
* p
= jvm_create_proc(class);
399 jvm_generate_function_header(p
, "public", "invoke", signature
);
400 jvm_alloc_register_untyped(p
-> rf
, false);
403 int num
= proc
-> type
-> num_decl
;
404 oberon_object_t
* param
= proc
-> type
-> decl
;
405 for(int i
= 0; i
< num
; i
++)
407 gen_type_t
* t
= param
-> type
-> gen_type
;
408 if(param
-> class == OBERON_CLASS_VAR_PARAM
)
410 int reg
= jvm_alloc_register_untyped(p
-> rf
, true);
411 jvm_generate(p
, 0, 1, "aload %i", reg
);
412 jvm_generate(p
, 0, 1, "iload %i", reg
+ 1);
416 int reg
= jvm_alloc_register_untyped(p
-> rf
, t
-> wide
);
417 jvm_generate(p
, 0, t
-> cell_size
, "%cload %i", t
-> prefix
, reg
);
419 use_size
+= t
-> cell_size
;
420 param
= param
-> next
;
423 char * full_name
= jvm_get_field_full_name(proc
);
424 int cell_size
= jvm_cell_size_for_type(proc
-> type
-> base
);
425 jvm_generate(p
, use_size
, cell_size
, "invokestatic %s%s", full_name
, signature
);
427 if(proc
-> type
-> base
-> class == OBERON_TYPE_NOTYPE
)
429 jvm_generate(p
, 0, 0, "return");
433 char prefix
= jvm_get_prefix(proc
-> type
-> base
);
434 jvm_generate(p
, cell_size
, 0, "%creturn", prefix
);
437 jvm_generate_function_end(p
);
439 jvm_destroy_class(class);
443 oberon_generate_record_class(const char * dir
, gen_module_t
* m
, oberon_type_t
* rec
)
446 struct gen_class
* class;
448 /* Устанавливаем новоый id */
449 rec
-> gen_type
-> rec_id
= m
-> rec_id
;
452 cname
= jvm_get_class_full_name(rec
);
453 class = jvm_create_class(dir
, cname
);
455 fprintf(class -> fp
, ".source %s\n", rec
-> module
-> name
);
456 fprintf(class -> fp
, ".class public %s\n", cname
);
458 if(rec
-> base
== NULL
)
460 fprintf(class -> fp
, ".super java/lang/Object\n\n");
464 class -> base
= rec
-> base
-> gen_type
-> class;
465 fprintf(class -> fp
, ".super %s\n\n", class -> base
-> full_name
);
468 rec
-> gen_type
-> class = class;
472 oberon_generator_init_type(oberon_context_t
* ctx
, oberon_type_t
* type
)
474 gen_type_t
* t
= GC_MALLOC(sizeof *t
);
475 memset(t
, 0, sizeof *t
);
476 type
-> gen_type
= t
;
479 c
= ctx
-> gen_context
;
482 switch(type
-> class)
484 case OBERON_TYPE_NOTYPE
:
485 case OBERON_TYPE_INTEGER
:
486 case OBERON_TYPE_BOOLEAN
:
487 case OBERON_TYPE_ARRAY
:
488 case OBERON_TYPE_POINTER
:
489 case OBERON_TYPE_REAL
:
490 case OBERON_TYPE_CHAR
:
491 case OBERON_TYPE_STRING
:
492 case OBERON_TYPE_SET
:
493 case OBERON_TYPE_NIL
:
494 case OBERON_TYPE_SYSTEM_BYTE
:
495 case OBERON_TYPE_SYSTEM_PTR
:
497 case OBERON_TYPE_RECORD
:
498 m
= type
-> module
-> gen_mod
;
499 oberon_generate_record_class(c
-> dir
, m
, type
);
501 case OBERON_TYPE_PROCEDURE
:
502 oberon_generate_procedure_class(c
-> dir
, type
);
505 gen_error("oberon_generator_init_type: unk calss %i", type
-> class);
509 if(type
-> class != OBERON_TYPE_NOTYPE
)
511 t
-> wide
= jvm_is_wide_type(type
);
512 t
-> prefix
= jvm_get_prefix(type
);
513 t
-> postfix
= jvm_get_postfix(type
);
516 t
-> cell_size
= jvm_cell_size_for_type(type
);
518 if(type
-> class != OBERON_TYPE_NIL
)
520 t
-> desc
= jvm_get_descriptor(type
);
525 oberon_generator_init_record(oberon_context_t
* ctx
, oberon_type_t
* rec
)
527 struct gen_class
* class;
528 class = rec
-> gen_type
-> class;
530 int num
= rec
-> num_decl
;
531 oberon_object_t
* field
= rec
-> decl
;
532 for(int i
= 0; i
< num
; i
++)
534 jvm_generate_var(field
-> gen_var
);
535 field
= field
-> next
;
538 /* Стандартный конструктор класса */
539 /* Инициализирует внутренние статические записи и массивы */
540 gen_proc_t
* p
= jvm_create_proc(class);
541 jvm_generate_function_header(p
, "public", "<init>", "()V");
542 jvm_alloc_register_untyped(p
-> rf
, false);
543 jvm_generate(p
, 0, 1, "aload_0");
546 jvm_generate(p
, 1, 0, "invokespecial %s/<init>()V", class -> base
-> full_name
);
550 jvm_generate(p
, 1, 0, "invokespecial java/lang/Object/<init>()V");
552 num
= rec
-> num_decl
;
554 for(int i
= 0; i
< num
; i
++)
556 jvm_generate(p
, 0, 1, "aload_0");
557 jvm_generate_var_initialization(p
, field
-> gen_var
);
559 if(field
-> type
-> class == OBERON_TYPE_RECORD
560 || field
-> type
-> class == OBERON_TYPE_ARRAY
)
562 jvm_generate(p
, 0, 1, "aload_0");
563 jvm_generate_ldst_prepare(p
, field
-> gen_var
);
564 jvm_generate_new(p
, field
-> type
, 0);
565 jvm_generate_store(p
, field
-> gen_var
);
567 field
= field
-> next
;
569 jvm_generate(p
, 0, 0, "return");
570 jvm_generate_function_end(p
);
572 /* Метод для копирования полей класса */
573 /* reg0 == src -> reg1 == dst */
574 p
= jvm_create_proc(class);
575 char * signature
= new_string("(%s%s)V", rec
-> gen_type
-> desc
, rec
-> gen_type
-> desc
);
576 jvm_generate_function_header(p
, "public static", "$COPY$", signature
);
578 gen_var_t
* copy_dst
= jvm_create_function_var(p
, JVM_STORAGE_REGISTER
, "dst", rec
-> gen_type
);
579 gen_var_t
* copy_src
= jvm_create_function_var(p
, JVM_STORAGE_REGISTER
, "src", rec
-> gen_type
);
580 jvm_generate_var(copy_dst
);
581 jvm_generate_var(copy_src
);
582 jvm_generate_var_initialization(p
, copy_dst
);
583 jvm_generate_var_initialization(p
, copy_src
);
585 num
= rec
-> num_decl
;
587 for(int i
= 0; i
< num
; i
++)
589 if(field
-> type
-> class == OBERON_TYPE_RECORD
)
591 jvm_generate_load(p
, copy_dst
);
592 jvm_generate_load(p
, field
-> gen_var
);
593 jvm_generate_load(p
, copy_src
);
594 jvm_generate_load(p
, field
-> gen_var
);
595 jvm_generate_copy_record(p
, field
-> type
);
597 else if(field
-> type
-> class == OBERON_TYPE_ARRAY
)
599 jvm_generate_load(p
, copy_dst
);
600 jvm_generate_load(p
, field
-> gen_var
);
601 jvm_generate_load(p
, copy_src
);
602 jvm_generate_load(p
, field
-> gen_var
);
603 jvm_generate_copy_array(p
, field
-> type
);
607 jvm_generate_load(p
, copy_dst
);
608 jvm_generate_ldst_prepare(p
, field
-> gen_var
);
609 jvm_generate_load(p
, copy_src
);
610 jvm_generate_load(p
, field
-> gen_var
);
611 jvm_generate_store(p
, field
-> gen_var
);
613 field
= field
-> next
;
615 jvm_generate(p
, 0, 0, "return");
616 jvm_generate_function_end(p
);
618 jvm_destroy_class(class);
622 oberon_generator_init_var(oberon_context_t
* ctx
, oberon_object_t
* var
)
625 m
= ctx
-> mod
-> gen_mod
;
627 struct gen_class
* class;
631 struct gen_class
* c
;
632 char * name
= var
-> name
;
633 gen_type_t
* t
= var
-> type
-> gen_type
;
638 gen_error("uninitialized type class %i", var
-> type
-> class);
643 case OBERON_CLASS_VAR_PARAM
:
644 p
= var
-> parent
-> gen_proc
;
645 var
-> gen_var
= jvm_create_function_var(p
, JVM_STORAGE_FRAME_PARAM_VARPTR
, name
, t
);
647 case OBERON_CLASS_PARAM
:
648 p
= var
-> parent
-> gen_proc
;
649 var
-> gen_var
= jvm_create_function_var(p
, JVM_STORAGE_FRAME_PARAM_VAR
, name
, t
);
651 case OBERON_CLASS_FIELD
:
652 c
= var
-> parent_type
-> gen_type
-> class;
653 var
-> gen_var
= jvm_create_class_var(c
, JVM_STORAGE_FIELD_VAR
, name
, t
);
655 case OBERON_CLASS_VAR
:
658 p
= var
-> parent
-> gen_proc
;
659 var
-> gen_var
= jvm_create_function_var(p
, JVM_STORAGE_FRAME_VAR
, name
, t
);
663 var
-> gen_var
= jvm_create_class_var(class, JVM_STORAGE_STATIC_VAR
, name
, t
);
664 jvm_generate_var(var
-> gen_var
);
668 gen_error("oberon_generator_init_var: unk var class %i", var
-> class);
674 oberon_generator_init_temp_var(oberon_context_t
* ctx
, oberon_object_t
* var
)
676 assert(var
-> class == OBERON_CLASS_VAR
);
679 m
= ctx
-> mod
-> gen_mod
;
685 t
= var
-> type
-> gen_type
;
687 var
-> gen_var
= jvm_create_function_temp_var(p
, t
);
688 jvm_generate_var(var
-> gen_var
);
689 jvm_generate_var_initialization(p
, var
-> gen_var
);
693 oberon_generator_init_proc(oberon_context_t
* ctx
, oberon_object_t
* proc
)
695 struct gen_class
* class = proc
-> module
-> gen_mod
-> class;
696 proc
-> gen_proc
= jvm_create_proc(class);
697 proc
-> gen_proc
-> full_name
= jvm_get_field_full_name_safe(proc
);
698 jvm_create_static_links(proc
);
702 oberon_generator_init_module(oberon_context_t
* ctx
, oberon_module_t
* mod
)
704 gen_module_t
* m
= GC_MALLOC(sizeof *m
);
705 memset(m
, 0, sizeof *m
);
709 c
= ctx
-> gen_context
;
711 struct gen_class
* class;
712 class = jvm_create_class(c
-> dir
, mod
-> name
);
714 fprintf(class -> fp
, ".source %s\n", mod
-> name
);
715 fprintf(class -> fp
, ".class %s\n", mod
-> name
);
716 fprintf(class -> fp
, ".super java/lang/Object\n\n");
718 fprintf(class -> fp
, ".field private static $INITIALIZED$ Z\n\n");
726 oberon_generator_fini_module(oberon_module_t
* mod
)
728 jvm_destroy_class(mod
-> gen_mod
-> class);
732 push_expr(gen_proc_t
* p
, oberon_expr_t
* expr
);
735 oberon_generate_begin_module(oberon_context_t
* ctx
)
739 struct gen_class
* class;
741 class = ctx
-> mod
-> gen_mod
-> class;
743 p
= jvm_create_proc(class);
744 jvm_generate_function_header(p
, "public static", "BEGIN", "()V");
746 label_cont
= jvm_new_label_id(p
);
747 jvm_generate(p
, 0, 1, "getstatic %s/$INITIALIZED$ Z", class -> full_name
);
748 jvm_generate(p
, 1, 0, "ifeq L%i", label_cont
);
749 jvm_generate(p
, 0, 0, "return");
750 jvm_generate_label(p
, label_cont
);
752 jvm_generate(p
, 0, 1, "iconst_1");
753 jvm_generate(p
, 1, 0, "putstatic %s/$INITIALIZED$ Z", class -> full_name
);
755 /* Инициализация переменных объявленных в модуле */
756 oberon_object_t
* x
= ctx
-> mod
-> decl
-> list
-> next
;
759 if(x
-> class == OBERON_CLASS_MODULE
)
761 if(!x
-> module
-> intrinsic
)
763 jvm_generate(p
, 0, 0, "invokestatic %s/BEGIN()V", x
-> module
-> gen_mod
-> class -> full_name
);
766 else if(x
-> class == OBERON_CLASS_VAR
)
768 jvm_generate_var_initialization(p
, x
-> gen_var
);
769 if(x
-> type
-> class == OBERON_TYPE_ARRAY
770 || x
-> type
-> class == OBERON_TYPE_RECORD
)
772 jvm_generate_ldst_prepare(p
, x
-> gen_var
);
773 jvm_generate_new(p
, x
-> type
, 0);
774 jvm_generate_store(p
, x
-> gen_var
);
783 oberon_generate_end_module(oberon_context_t
* ctx
)
785 struct gen_class
* class = ctx
-> mod
-> gen_mod
-> class;
786 gen_proc_t
* p
= class -> p
;
788 jvm_generate(p
, 0, 0, "return");
789 jvm_generate_function_end(class -> p
);
791 p
= jvm_create_proc(class);
792 jvm_generate_function_header(p
, "private", "<init>", "()V");
793 jvm_alloc_register_untyped(p
-> rf
, false);
794 jvm_generate(p
, 0, 1, "aload_0");
795 jvm_generate(p
, 1, 0, "invokespecial java/lang/Object/<init>()V");
796 jvm_generate(p
, 0, 0, "return");
797 jvm_generate_function_end(class -> p
);
801 * Генерирует код для получения размера измерения массива
802 * Аналог Обероновского LEN(v, n); где n = 0 - первое измерение.
807 jvm_generate_array_len(gen_proc_t
* p
, int dim
)
811 jvm_generate(p
, 0, 1, "iconst_0");
812 jvm_generate(p
, 2, 1, "aaload");
815 jvm_generate(p
, 1, 1, "arraylength");
819 jvm_generate_array_duplicate_and_replace(gen_proc_t
* p
, gen_var_t
* v
, oberon_type_t
* arr
)
821 jvm_generate_ldst_prepare(p
, v
);
824 oberon_type_t
* base
= arr
;
825 while(base
-> class == OBERON_TYPE_ARRAY
)
827 if(base
-> size
== 0)
829 jvm_generate_load(p
, v
);
830 jvm_generate_array_len(p
, dim
);
836 jvm_generate_new(p
, arr
, dim
);
837 jvm_generate(p
, 1, 2, "dup");
838 jvm_generate_load(p
, v
);
839 jvm_generate_copy_array(p
, arr
);
840 jvm_generate_store(p
, v
);
844 jvm_generate_record_duplicate_and_replace(gen_proc_t
* p
, gen_var_t
* v
, oberon_type_t
* rec
)
846 jvm_generate_ldst_prepare(p
, v
);
847 jvm_generate_new(p
, rec
, 0);
848 jvm_generate(p
, 1, 2, "dup");
849 jvm_generate_load(p
, v
);
850 jvm_generate_copy_record(p
, rec
);
851 jvm_generate_store(p
, v
);
855 jvm_generate_local_object(gen_proc_t
* p
, oberon_object_t
* x
)
858 struct gen_class
* class;
863 // Убеждаемся что сейчас находимся в функции
869 case OBERON_CLASS_VAR_PARAM
:
870 case OBERON_CLASS_PARAM
:
871 case OBERON_CLASS_VAR
:
874 case OBERON_CLASS_PROC
:
877 gen_error("jvm_generate_local_initialization: wat");
883 jvm_generate_local_initialization(gen_proc_t
* p
, oberon_object_t
* x
)
886 struct gen_class
* class;
891 // Убеждаемся что сейчас находимся в функции
897 case OBERON_CLASS_VAR_PARAM
:
898 case OBERON_CLASS_PARAM
:
899 case OBERON_CLASS_VAR
:
900 jvm_generate_var_initialization(p
, v
);
902 case OBERON_CLASS_PROC
:
905 gen_error("jvm_generate_local_initialization: wat");
909 if(x
-> class == OBERON_CLASS_PARAM
)
911 if(x
-> type
-> class == OBERON_TYPE_ARRAY
)
913 jvm_generate_array_duplicate_and_replace(p
, v
, x
-> type
);
915 else if(x
-> type
-> class == OBERON_TYPE_RECORD
)
917 jvm_generate_record_duplicate_and_replace(p
, v
, x
-> type
);
923 oberon_generate_begin_proc(oberon_context_t
* ctx
, oberon_object_t
* proc
)
928 oberon_object_t
* var
;
930 p
= proc
-> gen_proc
;
934 signature
= jvm_get_local_procedure_signature(proc
);
938 oberon_generate_procedure_pointer_class(p
-> class -> dir
, proc
);
939 signature
= jvm_get_procedure_signature(proc
-> type
);
942 name
= jvm_get_name(proc
);
943 jvm_generate_function_header(p
, "public static", name
, signature
);
947 jvm_generate_staticlinks(proc
);
950 jvm_generate_procedure_frame(proc
);
952 /* Создание параметров и переменных */
953 var
= proc
-> scope
-> list
-> next
;
956 jvm_generate_local_object(p
, var
);
960 jvm_generate_frame_initialization(p
);
962 /* Инициализация парамеров и переменных */
963 var
= proc
-> scope
-> list
-> next
;
966 jvm_generate_local_initialization(p
, var
);
972 oberon_generate_end_proc(oberon_context_t
* ctx
)
977 m
= ctx
-> mod
-> gen_mod
;
980 jvm_generate_function_end(p
);
984 oberon_generator_reserve_label(oberon_context_t
* ctx
)
990 m
= ctx
-> mod
-> gen_mod
;
993 l
= GC_MALLOC(sizeof *l
);
994 memset(l
, 0, sizeof *l
);
996 l
-> id
= jvm_new_label_id(p
);
1001 oberon_generate_label(oberon_context_t
* ctx
, gen_label_t
* l
)
1006 m
= ctx
-> mod
-> gen_mod
;
1007 p
= m
-> class -> p
;
1009 jvm_generate_label(p
, l
-> id
);
1013 oberon_generate_goto(oberon_context_t
* ctx
, gen_label_t
* l
)
1018 m
= ctx
-> mod
-> gen_mod
;
1019 p
= m
-> class -> p
;
1021 jvm_generate(p
, 0, 0, "goto L%i", l
-> id
);
1025 oberon_generate_branch(oberon_context_t
* ctx
, oberon_expr_t
* cond
, bool gotoif
, gen_label_t
* l
)
1030 m
= ctx
-> mod
-> gen_mod
;
1031 p
= m
-> class -> p
;
1037 /* переход если false */
1038 jvm_generate(p
, 1, 0, "ifeq L%i", l
-> id
);
1042 /* переход если true */
1043 jvm_generate(p
, 1, 0, "ifne L%i", l
-> id
);
1048 push_varptr(gen_proc_t
* p
, oberon_expr_t
* expr
)
1050 assert(expr
-> is_item
);
1052 switch(expr
-> item
.mode
)
1055 jvm_generate_ldst_prepare(p
, expr
-> item
.var
-> gen_var
);
1058 push_item(p
, expr
-> item
.parent
);
1059 push_expr(p
, expr
-> item
.args
);
1062 push_item(p
, expr
-> item
.parent
);
1063 jvm_generate_ldst_prepare(p
, expr
-> item
.var
-> gen_var
);
1066 push_varptr(p
, (oberon_expr_t
*) expr
-> item
.parent
);
1069 gen_error("push_varptr: wat %i", expr
-> item
.mode
);
1075 jvm_generate_call_proc(gen_proc_t
* p
, oberon_item_t
* desig
)
1077 assert(desig
-> var
== NULL
);
1078 assert(desig
-> mode
== MODE_CALL
);
1080 bool direct_call
= false;
1081 if(desig
-> parent
-> mode
== MODE_VAR
)
1083 if(desig
-> parent
-> var
-> class == OBERON_CLASS_PROC
)
1089 oberon_type_t
* procsig
;
1090 procsig
= desig
-> parent
-> result
;
1092 if(direct_call
== false)
1094 /* Загружаем указатель на процедуру */
1095 push_item(p
, desig
-> parent
);
1100 jvm_generate_push_static_links(p
, desig
-> parent
-> var
);
1104 int result_cells
= jvm_cell_size_for_type(procsig
-> base
);
1106 int num
= desig
-> num_args
;
1107 oberon_expr_t
* arg
= desig
-> args
;
1108 oberon_object_t
* param
= procsig
-> decl
;
1109 for(int i
= 0; i
< num
; i
++)
1111 if(param
-> class == OBERON_CLASS_VAR_PARAM
)
1114 push_varptr(p
, arg
);
1118 args_cells
+= jvm_cell_size_for_type(arg
-> result
);
1122 param
= param
-> next
;
1127 char * full_name
= jvm_get_field_full_name(desig
-> parent
-> var
);
1128 char * signature
= jvm_get_local_procedure_signature(desig
-> parent
-> var
);
1129 jvm_generate(p
, args_cells
, result_cells
, "invokestatic %s%s", full_name
, signature
);
1133 char * cname
= jvm_get_class_full_name(procsig
);
1134 char * signature
= jvm_get_procedure_signature(procsig
);
1135 jvm_generate(p
, 1 + args_cells
, result_cells
, "invokevirtual %s/invoke%s", cname
, signature
);
1140 oberon_generate_call_proc(oberon_context_t
* ctx
, oberon_expr_t
* desig
)
1142 assert(desig
-> is_item
);
1143 jvm_generate_call_proc(ctx
-> mod
-> gen_mod
-> class -> p
, (oberon_item_t
*) desig
);
1147 oberon_generate_return(oberon_context_t
* ctx
, oberon_expr_t
* expr
)
1154 m
= ctx
-> mod
-> gen_mod
;
1155 p
= m
-> class -> p
;
1160 prefix
= jvm_get_prefix(expr
-> result
);
1161 cell_size
= jvm_cell_size_for_type(expr
-> result
);
1162 jvm_generate(p
, cell_size
, 0, "%creturn", prefix
);
1166 jvm_generate(p
, 0, 0, "return");
1171 jvm_generate_expr_new_pointer(gen_proc_t
* p
, oberon_type_t
* type
, int num
, oberon_expr_t
* arg
)
1173 assert(type
-> class == OBERON_TYPE_POINTER
);
1175 for(int i
= 0; i
< num
; i
++)
1181 jvm_generate_new(p
, type
-> base
, num
);
1185 jvm_generate_cast_prefix(gen_proc_t
* p
, char prefix
, char postfix
)
1187 if(prefix
== postfix
)
1192 int from_cell_size
= jvm_cell_size_for_postfix(prefix
);
1193 int to_cell_size
= jvm_cell_size_for_postfix(postfix
);
1194 jvm_generate(p
, from_cell_size
, to_cell_size
, "%c2%c", prefix
, postfix
);
1198 jvm_generate_cast_type(gen_proc_t
* p
, oberon_type_t
* from
, oberon_type_t
* to
)
1200 if(to
-> class == OBERON_TYPE_RECORD
|| to
-> class == OBERON_TYPE_POINTER
)
1202 if(to
-> class == OBERON_TYPE_POINTER
&& to
-> base
-> class == OBERON_TYPE_RECORD
)
1204 char * full_name
= jvm_get_class_full_name(to
);
1205 jvm_generate(p
, 1, 1, "checkcast %s", full_name
);
1210 char prefix
= jvm_get_prefix(from
);
1211 char postfix
= jvm_get_postfix(to
);
1212 jvm_generate_cast_prefix(p
, prefix
, postfix
);
1217 jvm_generate_hard_cast_type(gen_proc_t
* p
, oberon_type_t
* from
, oberon_type_t
* to
)
1219 if(from
-> class == OBERON_TYPE_REAL
1220 && (to
-> class == OBERON_TYPE_INTEGER
|| to
-> class == OBERON_TYPE_SYSTEM_BYTE
))
1222 char postfix
= jvm_get_postfix(to
);
1223 if(from
-> size
<= 4)
1225 jvm_generate(p
, 1, 1, "invokestatic java/lang/Float/floatToIntBits(F)I");
1226 jvm_generate_cast_prefix(p
, 'i', postfix
);
1230 jvm_generate(p
, 2, 2, "invokestatic java/lang/Double/doubleToIntBits(D)J");
1231 jvm_generate_cast_prefix(p
, 'l', postfix
);
1234 else if((from
-> class == OBERON_TYPE_INTEGER
|| from
-> class == OBERON_TYPE_SYSTEM_BYTE
)
1235 && to
-> class == OBERON_TYPE_REAL
)
1237 char prefix
= jvm_get_prefix(from
);
1240 jvm_generate_cast_prefix(p
, prefix
, 'i');
1241 jvm_generate(p
, 1, 1, "invokestatic java/lang/Float/intBitsToFloat(I)F");
1245 jvm_generate_cast_prefix(p
, prefix
, 'l');
1246 jvm_generate(p
, 2, 2, "invokestatic java/lang/Double/longBitsToDouble(J)D");
1251 jvm_generate_cast_type(p
, from
, to
);
1256 push_item(gen_proc_t
* p
, oberon_item_t
* item
)
1258 switch(item
-> mode
)
1261 if(item
-> var
-> class == OBERON_CLASS_PROC
)
1263 jvm_generate_push_procedure_pointer(p
, item
-> var
);
1267 jvm_generate_load(p
, item
-> var
-> gen_var
);
1274 jvm_generate_push_int_size(p
, item
-> integer
, item
-> result
-> size
);
1277 jvm_generate_call_proc(p
, item
);
1281 char postfix
= jvm_get_postfix(item
-> result
);
1282 int cell_size
= jvm_cell_size_for_postfix(postfix
);
1283 push_item(p
, item
-> parent
);
1284 push_expr(p
, item
-> args
);
1285 jvm_generate(p
, 1 + 1, cell_size
, "%caload", postfix
);
1288 push_item(p
, item
-> parent
);
1289 jvm_generate_load(p
, item
-> var
-> gen_var
);
1292 /* Все объекты в jvm представляются как указатели */
1293 push_item(p
, item
-> parent
);
1296 jvm_generate(p
, 0, 1, "aconst_null");
1299 jvm_generate_expr_new_pointer(p
, item
-> result
, item
-> num_args
, item
-> args
);
1302 jvm_generate_push_float(p
, item
-> real
, item
-> result
-> size
);
1305 jvm_generate_push_string(p
, item
-> string
, item
-> result
-> size
);
1308 push_item(p
, item
-> parent
);
1309 jvm_generate_array_len(p
, item
-> integer
);
1310 jvm_generate_cast_prefix(p
, 'i', jvm_get_postfix(item
-> result
));
1313 gen_error("push_item: unk mode %i", item
-> mode
);
1319 jvm_generate_logical_not(gen_proc_t
* p
)
1321 int label_done
= jvm_new_label_id(p
);
1322 int label_false
= jvm_new_label_id(p
);
1324 jvm_generate(p
, 1, 0, "ifne L%i", label_false
);
1325 jvm_generate(p
, 0, 1, "iconst_1");
1326 jvm_generate(p
, 0, 0, "goto L%i", label_done
);
1327 jvm_generate_label(p
, label_false
);
1328 jvm_generate(p
, 0, 1, "iconst_0");
1329 jvm_generate_label(p
, label_done
);
1333 jvm_generate_abs(gen_proc_t
* p
, char prefix
)
1335 char t
= jvm_get_type_of_prefix(prefix
);
1336 int cell_size
= jvm_cell_size_for_postfix(prefix
);
1337 jvm_generate(p
, cell_size
, cell_size
, "invokestatic java/lang/Math/abs(%c)%c", t
, t
);
1341 jvm_get_compare_postfix(int op
)
1365 gen_error("jvm_generate_compare_op: wat");
1372 jvm_generate_compare_op(gen_proc_t
* p
, oberon_type_t
* t
, int op
)
1374 char prefix
= jvm_get_prefix(t
);
1375 int label_true
= jvm_new_label_id(p
);
1376 int label_done
= jvm_new_label_id(p
);
1377 int cell_size
= jvm_cell_size_for_type(t
);
1378 char * cmpop
= jvm_get_compare_postfix(op
);
1382 jvm_generate(p
, 2 * cell_size
, 1, "lcmp");
1383 jvm_generate(p
, 1, 1, "if%s L%i", cmpop
, label_true
);
1385 else if(prefix
== 'f' || prefix
== 'd')
1388 if(op
== OP_EQ
|| op
== OP_NEQ
|| op
== OP_GRT
|| op
== OP_GEQ
)
1396 jvm_generate(p
, 2 * cell_size
, 1, "%ccmp%c", prefix
, fop
);
1397 jvm_generate(p
, 1, 1, "if%s L%i", cmpop
, label_true
);
1399 else if(prefix
== 'a')
1401 if(t
-> class == OBERON_TYPE_STRING
1402 || (t
-> class == OBERON_TYPE_POINTER
&& t
-> base
-> class == OBERON_TYPE_CHAR
))
1404 jvm_generate(p
, 2, 1, "invokestatic SYSTEM/STRCMP([B[B)I");
1405 jvm_generate(p
, 1, 0, "if%s L%i", cmpop
, label_true
);
1409 jvm_generate(p
, 1, 0, "if_acmp%s L%i", cmpop
, label_true
);
1414 jvm_generate(p
, 2 * cell_size
, 0, "if_%ccmp%s L%i", prefix
, cmpop
, label_true
);
1417 jvm_generate(p
, 0, 1, "iconst_0");
1418 jvm_generate(p
, 0, 0, "goto L%i", label_done
);
1419 jvm_generate_label(p
, label_true
);
1420 jvm_generate(p
, 0, 1, "iconst_1");
1421 jvm_generate_label(p
, label_done
);
1425 jvm_generate_operator(gen_proc_t
* p
, oberon_type_t
* t
, int op
)
1427 char prefix
= jvm_get_prefix(t
);
1428 int cell_size
= jvm_cell_size_for_type(t
);
1431 case OP_UNARY_MINUS
:
1432 jvm_generate(p
, cell_size
, cell_size
, "%cneg", prefix
);
1434 case OP_COMPLEMENTATION
:
1435 jvm_generate_push_int_size(p
, -1, t
-> size
);
1436 jvm_generate(p
, 2 * cell_size
, cell_size
, "%cxor", prefix
);
1439 jvm_generate_logical_not(p
);
1442 jvm_generate_abs(p
, prefix
);
1445 jvm_generate(p
, cell_size
, cell_size
, "invokestatic java/lang/Character/toUpperCase(I)I");
1449 jvm_generate(p
, 2 * cell_size
, cell_size
, "%cadd", prefix
);
1452 jvm_generate(p
, 2 * cell_size
, cell_size
, "%csub", prefix
);
1455 jvm_generate(p
, 2 * cell_size
, cell_size
, "%cmul", prefix
);
1458 jvm_generate(p
, 2 * cell_size
, cell_size
, "%cdiv", prefix
);
1461 jvm_generate(p
, 2 * cell_size
, cell_size
, "%crem", prefix
);
1464 jvm_generate(p
, 2 * cell_size
, cell_size
, "%cor", prefix
);
1466 case OP_INTERSECTION
:
1467 jvm_generate(p
, 2 * cell_size
, cell_size
, "%cand", prefix
);
1470 /* (a - b) == a & ~b */
1471 jvm_generate_push_int_size(p
, -1, t
-> size
);
1472 jvm_generate(p
, 2 * cell_size
, cell_size
, "%cxor", prefix
);
1473 jvm_generate(p
, 2 * cell_size
, cell_size
, "%cand", prefix
);
1475 case OP_SYM_DIFFERENCE
:
1476 jvm_generate(p
, 2 * cell_size
, cell_size
, "%cxor", prefix
);
1485 jvm_generate_compare_op(p
, t
, op
);
1488 gen_error("jvm_generate_operator: unk op %i", op
);
1494 jvm_generate_logical_or(gen_proc_t
* p
, oberon_expr_t
* a
, oberon_expr_t
* b
)
1496 int label_calc_b
= jvm_new_label_id(p
);
1497 int label_done
= jvm_new_label_id(p
);
1499 /* a OR b -- если a, то TRUE, иначе b */
1502 jvm_generate(p
, 1, 0, "ifeq L%i", label_calc_b
);
1503 jvm_generate(p
, 0, 1, "iconst_1");
1504 jvm_generate(p
, 0, 0, "goto L%i", label_done
);
1505 jvm_generate_label(p
, label_calc_b
);
1507 jvm_generate_label(p
, label_done
);
1511 jvm_generate_logical_and(gen_proc_t
* p
, oberon_expr_t
* a
, oberon_expr_t
* b
)
1513 int label_false
= jvm_new_label_id(p
);
1514 int label_done
= jvm_new_label_id(p
);
1516 /* a AND b -- если a, то b, иначе FALSE */
1519 jvm_generate(p
, 1, 0, "ifeq L%i", label_false
);
1521 jvm_generate(p
, 0, 0, "goto L%i", label_done
);
1522 jvm_generate_label(p
, label_false
);
1523 jvm_generate(p
, 0, 1, "iconst_0");
1524 jvm_generate_label(p
, label_done
);
1528 jvm_generate_range(gen_proc_t
* p
, oberon_expr_t
* a
, oberon_expr_t
* b
)
1530 /* { a } == 1 << a */
1531 /* { a..b } == (a <= b) ? ((2 << b) - (1 << a)) : (0); */
1535 oberon_type_t
* type
;
1542 cell_size
= jvm_cell_size_for_type(type
);
1543 prefix
= jvm_get_prefix(type
);
1547 jvm_generate_push_int_size(p
, 1, type
-> size
);
1549 jvm_generate(p
, 2 * cell_size
, cell_size
, "%cshl", prefix
);
1553 ra
= jvm_create_function_temp_var(p
, type
-> gen_type
);
1554 rb
= jvm_create_function_temp_var(p
, type
-> gen_type
);
1555 jvm_generate_var(ra
);
1556 jvm_generate_var(rb
);
1557 jvm_generate_var_initialization(p
, ra
);
1558 jvm_generate_var_initialization(p
, rb
);
1559 label_else
= jvm_new_label_id(p
);
1560 label_end
= jvm_new_label_id(p
);
1563 jvm_generate_store(p
, ra
);
1565 jvm_generate_store(p
, rb
);
1567 jvm_generate_load(p
, ra
);
1568 jvm_generate_load(p
, rb
);
1569 jvm_generate(p
, 2 * cell_size
, 0, "if_%ccmpgt L%i", prefix
, label_else
);
1571 jvm_generate_push_int_size(p
, 2, type
-> size
);
1572 jvm_generate_load(p
, rb
);
1573 jvm_generate(p
, 2 * cell_size
, cell_size
, "%cshl", prefix
);
1574 jvm_generate_push_int_size(p
, 2, type
-> size
);
1575 jvm_generate_load(p
, ra
);
1576 jvm_generate(p
, 2 * cell_size
, cell_size
, "%cshl", prefix
);
1577 jvm_generate(p
, 2 * cell_size
, cell_size
, "%csub", prefix
);
1578 jvm_generate(p
, 0, 0, "goto L%i", label_end
);
1580 jvm_generate_label(p
, label_else
);
1581 jvm_generate_push_int_size(p
, 0, type
-> size
);
1582 jvm_generate_label(p
, label_end
);
1585 /* TODO free registers */
1589 jvm_generate_in(gen_proc_t
* p
, oberon_expr_t
* a
, oberon_expr_t
* b
)
1591 oberon_type_t
* t
= a
-> result
;
1592 int cell_size
= jvm_cell_size_for_type(t
);
1593 char prefix
= jvm_get_prefix(t
);
1594 int label_else
= jvm_new_label_id(p
);
1595 int label_end
= jvm_new_label_id(p
);
1597 /* (a IN b) == (1 << a) & b */
1598 jvm_generate_push_int_size(p
, 1, t
-> size
);
1600 jvm_generate(p
, 2 * cell_size
, cell_size
, "%cshl", prefix
);
1602 jvm_generate(p
, 2 * cell_size
, cell_size
, "%cand", prefix
);
1606 jvm_generate(p
, cell_size
, 0, "lcmp");
1609 jvm_generate(p
, 1, 0, "ifeq L%i", label_else
);
1610 jvm_generate(p
, 0, 1, "iconst_1");
1611 jvm_generate(p
, 0, 0, "goto L%i", label_end
);
1612 jvm_generate_label(p
, label_else
);
1613 jvm_generate(p
, 0, 1, "iconst_0");
1614 jvm_generate_label(p
, label_end
);
1618 jvm_generate_shift(gen_proc_t
* p
, int op
, oberon_expr_t
* a
, oberon_expr_t
* b
)
1620 oberon_type_t
* t
= a
-> result
;
1621 int cell_size
= jvm_cell_size_for_type(t
);
1622 char prefix
= jvm_get_prefix(t
);
1623 char dt
= jvm_get_type_of_prefix(prefix
);
1626 jvm_generate_cast_type(p
, a
-> result
, t
);
1628 jvm_generate_cast_type(p
, b
-> result
, t
);
1643 gen_error("jvm_generate_shift: invalid op %i", op
);
1646 jvm_generate(p
, 2 * cell_size
, cell_size
, "invokestatic SYSTEM/%s(%c%c)%c", opname
, dt
, dt
, dt
);
1650 jvm_generate_entier(gen_proc_t
* p
, oberon_expr_t
* x
, oberon_type_t
* res
)
1652 char prefix
= jvm_get_prefix(x
-> result
);
1653 char postfix
= jvm_get_postfix(res
);
1656 jvm_generate_cast_prefix(p
, prefix
, 'd');
1657 jvm_generate(p
, 2, 2, "invokestatic java/lang/Math/floor(D)D");
1658 jvm_generate_cast_prefix(p
, 'd', postfix
);
1662 push_operator(gen_proc_t
* p
, oberon_oper_t
* oper
)
1664 oberon_type_t
* preq
= oper
-> left
-> result
;
1665 int op
= oper
-> op
;
1669 push_expr(p
, oper
-> left
);
1670 jvm_generate_cast_type(p
, oper
-> left
-> result
, oper
-> result
);
1673 push_expr(p
, oper
-> left
);
1674 jvm_generate_hard_cast_type(p
, oper
-> left
-> result
, oper
-> result
);
1676 case OP_COMPLEMENTATION
:
1677 case OP_UNARY_MINUS
:
1681 push_expr(p
, oper
-> left
);
1682 jvm_generate_operator(p
, preq
, op
);
1685 jvm_generate_entier(p
, oper
-> left
, oper
-> result
);
1695 case OP_INTERSECTION
:
1697 case OP_SYM_DIFFERENCE
:
1705 push_expr(p
, oper
-> left
);
1706 push_expr(p
, oper
-> right
);
1707 jvm_generate_operator(p
, preq
, op
);
1711 jvm_generate_logical_or(p
, oper
-> left
, oper
-> right
);
1714 jvm_generate_logical_and(p
, oper
-> left
, oper
-> right
);
1718 preq
= oper
-> right
-> result
;
1719 char * cname
= jvm_get_class_full_name(preq
);
1720 push_expr(p
, oper
-> left
);
1721 jvm_generate(p
, 1, 1, "instanceof %s", cname
);
1724 jvm_generate_range(p
, oper
-> left
, oper
-> right
);
1727 jvm_generate_in(p
, oper
-> left
, oper
-> right
);
1733 jvm_generate_shift(p
, op
, oper
-> left
, oper
-> right
);
1736 gen_error("push_oper: unk op %i", op
);
1742 push_expr(gen_proc_t
* p
, oberon_expr_t
* expr
)
1746 push_item(p
, (oberon_item_t
*) expr
);
1750 push_operator(p
, (oberon_oper_t
*) expr
);
1755 store_expr(gen_proc_t
* p
, oberon_expr_t
* dst
, oberon_expr_t
* src
)
1757 assert(dst
-> is_item
);
1758 oberon_item_t
* item
= (oberon_item_t
*) dst
;
1760 if(dst
-> result
-> class == OBERON_TYPE_ARRAY
1761 || src
-> result
-> class == OBERON_TYPE_ARRAY
)
1765 jvm_generate_copy_array(p
, dst
-> result
);
1767 else if(dst
-> result
-> class == OBERON_TYPE_RECORD
1768 || src
-> result
-> class == OBERON_TYPE_RECORD
)
1772 jvm_generate_copy_record(p
, dst
-> result
);
1774 else switch(item
-> mode
)
1777 jvm_generate_ldst_prepare(p
, item
-> var
-> gen_var
);
1779 jvm_generate_store(p
, item
-> var
-> gen_var
);
1783 char postfix
= jvm_get_postfix(src
-> result
);
1784 int cell_size
= jvm_cell_size_for_postfix(postfix
);
1785 assert(item
-> parent
-> is_item
);
1786 push_item(p
, (oberon_item_t
*) item
-> parent
);
1787 push_expr(p
, item
-> args
);
1789 jvm_generate(p
, 1 + 1 + cell_size
, 0, "%castore", postfix
);
1792 assert(item
-> parent
-> is_item
);
1793 push_item(p
, (oberon_item_t
*) item
-> parent
);
1794 jvm_generate_ldst_prepare(p
, item
-> var
-> gen_var
);
1796 jvm_generate_store(p
, item
-> var
-> gen_var
);
1799 gen_error("store_expr: unk mode %i", item
-> mode
);
1805 oberon_generate_assign(oberon_context_t
* ctx
, oberon_expr_t
* src
, oberon_expr_t
* dst
)
1810 m
= ctx
-> mod
-> gen_mod
;
1811 p
= m
-> class -> p
;
1813 store_expr(p
, dst
, src
);
1817 oberon_generate_copy(oberon_context_t
* ctx
, oberon_expr_t
* src
, oberon_expr_t
* dst
)
1823 m
= ctx
-> mod
-> gen_mod
;
1824 p
= m
-> class -> p
;
1829 desc
= jvm_get_descriptor(dst
-> result
);
1831 jvm_generate(p
, 2, 0, "invokestatic SYSTEM/COPY(%s%s)V", desc
, desc
);
1835 oberon_generate_assert(oberon_context_t
* ctx
, oberon_expr_t
* cond
)
1840 m
= ctx
-> mod
-> gen_mod
;
1841 p
= m
-> class -> p
;
1844 jvm_generate(p
, 1, 0, "invokestatic SYSTEM/ASSERT(Z)V");
1848 oberon_generate_assert_n(oberon_context_t
* ctx
, oberon_expr_t
* cond
, int64_t n
)
1853 m
= ctx
-> mod
-> gen_mod
;
1854 p
= m
-> class -> p
;
1857 jvm_generate_push_int_size(p
, n
, 8);
1858 jvm_generate(p
, 1 + 2, 0, "invokestatic SYSTEM/ASSERT(ZJ)V");
1862 oberon_generate_trap(oberon_context_t
* ctx
, int64_t n
)
1867 m
= ctx
-> mod
-> gen_mod
;
1868 p
= m
-> class -> p
;
1870 jvm_generate_push_int_size(p
, n
, 8);
1871 jvm_generate(p
, 2, 0, "invokestatic SYSTEM/TRAP(J)V");
1875 oberon_generate_halt(oberon_context_t
* ctx
, int64_t n
)
1880 m
= ctx
-> mod
-> gen_mod
;
1881 p
= m
-> class -> p
;
1883 jvm_generate_push_int_size(p
, n
, 8);
1884 jvm_generate(p
, 2, 0, "invokestatic SYSTEM/HALT(J)V");
1888 oberon_set_out_directory(oberon_context_t
* ctx
, const char * path
)
1892 c
= ctx
-> gen_context
;
1894 c
-> dir
= new_string(path
);