2a2abcdcd3632f1b73a22aecc2135138f8e94523
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_PROCEDURE
:
100 case OBERON_TYPE_RECORD
:
101 desc
= get_class_full_name(ctx
, type
);
102 return new_string("L%s;", desc
);
104 case OBERON_TYPE_ARRAY
:
105 desc
= get_descriptor(ctx
, type
-> base
);
106 return new_string("[%s", desc
);
109 oberon_error(ctx
, "print_descriptor: unsupported type class %i", type
-> class);
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');
126 case OBERON_TYPE_PROCEDURE
:
127 case OBERON_TYPE_ARRAY
:
128 case OBERON_TYPE_RECORD
:
129 case OBERON_TYPE_POINTER
:
132 case OBERON_TYPE_REAL
:
133 return (size
<= 4) ? ('f') : ('d');
137 oberon_error(ctx
, "get_prefix: wat");
142 get_field_full_name(oberon_context_t
* ctx
, oberon_object_t
* x
)
144 return new_string("%s/%s", x
-> module
-> name
, x
-> name
);
148 get_class_full_name(oberon_context_t
* ctx
, oberon_type_t
* type
)
153 switch(type
-> class)
155 case OBERON_TYPE_PROCEDURE
:
156 name
= new_string("SYSTEM$PROCEDURE");
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
);
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
);
179 oberon_error(ctx
, "get_record_full_name: unk type class %i", type
-> class);
187 get_procedure_signature(oberon_context_t
* ctx
, oberon_type_t
* proc
)
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
);
203 desc
= get_descriptor(ctx
, proc
-> base
);
204 signature
= new_string("%s)%s", signature
, desc
);
210 oberon_generate_procedure_class(oberon_context_t
* ctx
, oberon_type_t
* proc
)
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");
234 fprintf(fp
, ".method public abstract invoke%s\n", signature
);
235 fprintf(fp
, ".end method\n\n");
241 oberon_generate_record_class(oberon_context_t
* ctx
, oberon_type_t
* rec
)
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
;
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
:
278 case OBERON_TYPE_RECORD
:
279 oberon_generate_record_class(ctx
, type
);
281 case OBERON_TYPE_PROCEDURE
:
282 oberon_generate_procedure_class(ctx
, type
);
284 case OBERON_TYPE_POINTER
:
285 assert(type
-> base
-> class == OBERON_TYPE_VOID
);
288 oberon_error(ctx
, "oberon_generator_init_type: unk calss %i", type
-> class);
294 oberon_generate_object(oberon_context_t
* ctx
, FILE * fp
, oberon_object_t
* x
)
300 desc
= get_descriptor(ctx
, x
-> type
);
303 case OBERON_CLASS_VAR
:
304 fprintf(fp
, ".field public static %s %s\n\n", name
, desc
);
306 case OBERON_CLASS_FIELD
:
307 fprintf(fp
, ".field public %s %s\n\n", name
, desc
);
310 oberon_error(ctx
, "oberon_generate_object: unk class %i", x
-> class);
316 oberon_generator_init_record(oberon_context_t
* ctx
, oberon_type_t
* rec
)
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");
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
);
346 gen_module_t
* m
= ctx
-> mod
-> gen_mod
;
350 case OBERON_CLASS_PARAM
:
351 case OBERON_CLASS_FIELD
:
353 case OBERON_CLASS_VAR
:
354 oberon_generate_object(ctx
, m
-> fp
, var
);
357 oberon_error(ctx
, "oberon_generator_init_var: unk var class %i", var
-> class);
363 oberon_generator_init_proc(oberon_context_t
* ctx
, oberon_object_t
* proc
)
365 gen_proc_t
* p
= GC_MALLOC(sizeof *p
);
366 memset(p
, 0, sizeof *p
);
367 proc
-> gen_proc
= p
;
371 oberon_error(ctx
, "generator: local procedures not implemented");
376 oberon_generator_init_module(oberon_context_t
* ctx
, oberon_module_t
* mod
)
378 gen_module_t
* m
= GC_MALLOC(sizeof *m
);
379 memset(m
, 0, sizeof *m
);
382 int fnamesz
= strlen(mod
-> name
) + 3;
383 char fname
[fnamesz
+ 1];
384 snprintf(fname
, fnamesz
, "%s.j", mod
-> name
);
387 fp
= fopen(fname
, "w");
390 fprintf(fp
, ".source %s\n", mod
-> name
);
391 fprintf(fp
, ".class %s\n", mod
-> name
);
392 fprintf(fp
, ".super java/lang/Object\n\n");
397 // =======================================================================
399 // =======================================================================
402 oberon_generate_begin_module(oberon_context_t
* ctx
)
404 gen_module_t
* m
= ctx
-> mod
-> gen_mod
;
405 fprintf(m
-> fp
, ".method public <init>()V\n");
406 fprintf(m
-> fp
, " aload_0\n");
407 fprintf(m
-> fp
, " invokespecial java/lang/Object/<init>()V\n");
411 oberon_generate_end_module(oberon_context_t
* ctx
)
413 gen_module_t
* m
= ctx
-> mod
-> gen_mod
;
415 fprintf(m
-> fp
, " .limit stack 32\n");
416 fprintf(m
-> fp
, " .limit locals 32\n");
417 fprintf(m
-> fp
, " return\n");
418 fprintf(m
-> fp
, ".end method\n");
422 oberon_generate_begin_proc(oberon_context_t
* ctx
, oberon_object_t
* proc
)
427 m
= ctx
-> mod
-> gen_mod
;
428 signature
= get_procedure_signature(ctx
, proc
-> type
);
430 fprintf(m
-> fp
, ".method public static %s%s\n", proc
-> name
, signature
);
434 oberon_generate_call_proc(oberon_context_t
* ctx
, oberon_expr_t
* desig
)
436 printf("call proc\n");
440 oberon_generate_end_proc(oberon_context_t
* ctx
)
443 m
= ctx
-> mod
-> gen_mod
;
445 fprintf(m
-> fp
, " .limit stack 32\n");
446 fprintf(m
-> fp
, " .limit locals 32\n");
447 fprintf(m
-> fp
, ".end method\n\n");
451 oberon_generate_return(oberon_context_t
* ctx
, oberon_expr_t
* expr
)
455 m
= ctx
-> mod
-> gen_mod
;
459 oberon_error(ctx
, "oberon_generate_return: TODO return expr");
463 fprintf(m
-> fp
, " return\n");
468 push_int(FILE * fp
, long i
)
472 fprintf(fp
, "iconst_m1\n");
474 else if(i
>= 0 && i
<= 5)
476 fprintf(fp
, "iconst_%li\n", i
);
478 else if(i
>= -128 && i
<= 127)
480 fprintf(fp
, "bipush %li\n", i
);
482 else if(i
>= -32768 && i
<= 32767)
484 fprintf(fp
, "sipush %li\n", i
);
486 else if(i
>= -2147483648 && i
<= 2147483647)
488 fprintf(fp
, "ldc %li\n", i
);
492 fprintf(fp
, "ldc2 %li\n", i
);
497 push_float(FILE * fp
, double f
, int size
)
503 fprintf(fp
, "fconst_0\n");
507 fprintf(fp
, "fconst_1\n");
511 fprintf(fp
, "fconst_2\n");
515 fprintf(fp
, "ldc %lf\n", f
);
522 fprintf(fp
, "dconst_0\n");
526 fprintf(fp
, "dconst_1\n");
530 fprintf(fp
, "ldc2 %lf\n", f
);
535 static void push_expr(oberon_context_t
* ctx
, FILE * fp
, oberon_expr_t
* expr
);
538 push_var(oberon_context_t
* ctx
, FILE * fp
, oberon_object_t
* var
)
542 int reg
= var
-> gen_var
-> reg
;
543 char prefix
= get_prefix(ctx
, var
-> type
);
544 fprintf(fp
, "%cload %i\n", prefix
, reg
);
548 char * fullname
= get_field_full_name(ctx
, var
);
549 char * desc
= get_descriptor(ctx
, var
-> type
);
550 fprintf(fp
, "getstatic %s %s\n", fullname
, desc
);
555 push_item(oberon_context_t
* ctx
, FILE * fp
, oberon_item_t
* item
)
560 push_var(ctx
, fp
, item
-> var
);
563 push_int(fp
, item
-> integer
);
566 push_int(fp
, item
-> boolean
);
569 oberon_error(ctx
, "push_item: TODO call");
572 oberon_error(ctx
, "push_item: TODO index");
575 oberon_error(ctx
, "push_item: TODO field");
578 oberon_error(ctx
, "push_item: TODO deref");
581 fprintf(fp
, "aconst_null\n");
584 oberon_error(ctx
, "push_item: TODO new");
587 push_float(fp
, item
-> real
, item
-> result
-> size
);
590 oberon_error(ctx
, "push_item: unk mode %i", item
-> mode
);
596 push_operator(oberon_context_t
* ctx
, FILE * fp
, oberon_oper_t
* oper
)
598 char prefix
= get_prefix(ctx
, oper
-> result
);
602 push_expr(ctx
, fp
, oper
-> left
);
603 fprintf(fp
, "%cneg\n", prefix
);
606 push_expr(ctx
, fp
, oper
-> left
);
608 fprintf(fp
, "%cxor\n", prefix
);
612 push_expr(ctx
, fp
, oper
-> left
);
613 push_expr(ctx
, fp
, oper
-> right
);
614 fprintf(fp
, "%cadd\n", prefix
);
617 push_expr(ctx
, fp
, oper
-> left
);
618 push_expr(ctx
, fp
, oper
-> right
);
619 fprintf(fp
, "%csub\n", prefix
);
622 push_expr(ctx
, fp
, oper
-> left
);
623 push_expr(ctx
, fp
, oper
-> right
);
624 fprintf(fp
, "%cmul\n", prefix
);
627 push_expr(ctx
, fp
, oper
-> left
);
628 push_expr(ctx
, fp
, oper
-> right
);
629 fprintf(fp
, "%cdiv\n", prefix
);
632 push_expr(ctx
, fp
, oper
-> left
);
633 push_expr(ctx
, fp
, oper
-> right
);
634 fprintf(fp
, "%crem\n", prefix
);
637 push_expr(ctx
, fp
, oper
-> left
);
638 push_expr(ctx
, fp
, oper
-> right
);
639 fprintf(fp
, "%cand\n", prefix
);
642 push_expr(ctx
, fp
, oper
-> left
);
643 push_expr(ctx
, fp
, oper
-> right
);
644 fprintf(fp
, "%cxor\n", prefix
);
647 push_expr(ctx
, fp
, oper
-> left
);
648 push_expr(ctx
, fp
, oper
-> right
);
649 fprintf(fp
, "%cor\n", prefix
);
660 oberon_error(ctx
, "push_oper: TODO op %i", oper
-> op
);
663 oberon_error(ctx
, "push_oper: unk op %i", oper
-> op
);
669 push_expr(oberon_context_t
* ctx
, FILE * fp
, oberon_expr_t
* expr
)
673 push_item(ctx
, fp
, (oberon_item_t
*) expr
);
677 push_operator(ctx
, fp
, (oberon_oper_t
*) expr
);
682 store_expr(oberon_context_t
* ctx
, FILE * fp
, oberon_expr_t
* expr
)
684 assert(expr
-> is_item
);
685 oberon_item_t
* item
= (oberon_item_t
*) expr
;
691 if(item
-> var
-> local
)
693 int reg
= item
-> var
-> gen_var
-> reg
;
694 prefix
= get_prefix(ctx
, item
-> result
);
695 fprintf(fp
, "%cstore %i\n", prefix
, reg
);
699 char * fullname
= get_field_full_name(ctx
, item
-> var
);
700 char * desc
= get_descriptor(ctx
, item
-> result
);
701 fprintf(fp
, "putstatic %s %s\n", fullname
, desc
);
705 oberon_error(ctx
, "store_expr: unk mode %i", item
-> mode
);
711 oberon_generate_assign(oberon_context_t
* ctx
, oberon_expr_t
* src
, oberon_expr_t
* dst
)
714 m
= ctx
-> mod
-> gen_mod
;
716 push_expr(ctx
, m
-> fp
, src
);
717 store_expr(ctx
, m
-> fp
, dst
);
721 oberon_generate_code(oberon_context_t
* ctx
)
723 printf("generate code\n");
727 oberon_generator_dump(oberon_context_t
* ctx
, char * path
)
729 printf("jit: dump code\n");
733 oberon_generator_get_procedure(oberon_context_t
* ctx
, const char * name
)
735 printf("jit: get pointer to procedure %s\n", name
);
740 oberon_generator_get_var(oberon_context_t
* ctx
, const char * name
)
742 printf("jit: get pointer to var %s\n", name
);