#include #include #include #include #include #include #include #include #include "../../oberon-internals.h" #include "generator-jvm.h" #include "generator-jvm-abi.h" #include "generator-jvm-asm.h" #include "generator-jvm-basic.h" gen_proc_t * jvm_create_proc(struct gen_class * class) { gen_proc_t * p = GC_MALLOC(sizeof *p); memset(p, 0, sizeof *p); struct gen_register_file * rf = GC_MALLOC(sizeof *rf); memset(rf, 0, sizeof *rf); struct gen_stack * stack = GC_MALLOC(sizeof *stack); memset(rf, 0, sizeof *stack); p -> rf = rf; p -> stack = stack; p -> class = class; p -> label_id = 0; return p; } void jvm_generate_function_header(gen_proc_t * p, char * access, char * name, char * signature) { struct gen_class * class; class = p -> class; /* Делаем процедуру текущей в этом классе */ assert(class -> p == NULL); class -> p = p; fprintf(class -> fp, ".method %s %s%s\n", access, name, signature); fprintf(class -> fp, " start:\n"); } void jvm_generate_function_end(gen_proc_t * p) { struct gen_class * class; class = p -> class; assert(class -> p); class -> p = NULL; int pointer = p -> stack -> pointer; int max_pointer = p -> stack -> max_pointer; int locals = p -> rf -> num_used; int max_locals = p -> rf -> max_used; fprintf(class -> fp, " .limit stack %i \t; current(%i)\n", max_pointer, pointer); fprintf(class -> fp, " .limit locals %i \t; current(%i)\n", max_locals, locals); fprintf(class -> fp, " end:\n"); fprintf(class -> fp, ".end method\n\n"); } struct gen_class * jvm_create_class(const char * dir, char * full_name) { struct gen_class * class = GC_MALLOC(sizeof *class); memset(class, 0, sizeof *class); char * fname = new_string("%s/%s.j", dir, full_name); class -> full_name = new_string(full_name); class -> fp = fopen(fname, "w"); class -> dir = new_string(dir); if(class -> fp == NULL) { gen_error("unable to create file %s", fname); } return class; } void jvm_destroy_class(struct gen_class * class) { assert(class -> p == NULL); fclose(class -> fp); } void jvm_stack_push(gen_proc_t * p, unsigned size) { p -> stack -> pointer += size; if(p -> stack -> pointer > p -> stack -> max_pointer) { p -> stack -> max_pointer = p -> stack -> pointer; } } void jvm_stack_pop(gen_proc_t * p, unsigned size) { p -> stack -> pointer -= size; if(p -> stack -> pointer < 0) { printf("WARING: stack pointer %i\n", p -> stack -> pointer); } } void jvm_generate(gen_proc_t * p, unsigned get, unsigned push, char * format, ...) { va_list ptr; va_start(ptr, format); jvm_stack_pop(p, get); fprintf(p -> class -> fp, " "); vfprintf(p -> class -> fp, format, ptr); jvm_stack_push(p, push); fprintf(p -> class -> fp, " \t ;>>>> %i -- %i : current_stack(%i)\n", get, push, p -> stack -> pointer); va_end(ptr); } void jvm_generate_comment(gen_proc_t * p, char * format, ...) { va_list ptr; va_start(ptr, format); fprintf(p -> class -> fp, " ;;;; "); vfprintf(p -> class -> fp, format, ptr); fprintf(p -> class -> fp, "\n"); va_end(ptr); } void jvm_generate_push_int(gen_proc_t * p, int64_t i) { if(i == -1) { jvm_generate(p, 0, 1, "iconst_m1"); } else if(i >= 0 && i <= 5) { jvm_generate(p, 0, 1, "iconst_%li", i); } else if(i >= -128 && i <= 127) { jvm_generate(p, 0, 1, "bipush %li", i); } else if(i >= -32768 && i <= 32767) { jvm_generate(p, 0, 1, "sipush %li", i); } else if(i >= -2147483648 && i <= 2147483647) { jvm_generate(p, 0, 1, "ldc %li", i); } else { jvm_generate(p, 0, 2, "ldc2_w %li", i); } } void jvm_generate_push_int_size(gen_proc_t * p, int64_t i, int size) { int pushed_cell = 1; if(i == -1) { jvm_generate(p, 0, 1, "iconst_m1"); } else if(i >= 0 && i <= 5) { jvm_generate(p, 0, 1, "iconst_%li", i); } else if(i >= -128 && i <= 127) { jvm_generate(p, 0, 1, "bipush %li", i); } else if(i >= -32768 && i <= 32767) { jvm_generate(p, 0, 1, "sipush %li", i); } else if(i >= -2147483648 && i <= 2147483647) { jvm_generate(p, 0, 1, "ldc %li", i); } else { pushed_cell = 2; jvm_generate(p, 0, 2, "ldc2_w %li", i); } assert(size <= 8); if(size > 4 && pushed_cell == 1) { jvm_generate(p, pushed_cell, 2, "i2l"); } else if(size <= 4) { if(pushed_cell > 1) { jvm_generate(p, 2, 1, "l2i"); } if(size == 2) { jvm_generate(p, 1, 1, "i2s"); } else if(size == 1) { jvm_generate(p, 1, 1, "i2b"); } } } void jvm_generate_push_float(gen_proc_t * p, double f, int size) { if(size <= 4) { if(f == 0.0) { jvm_generate(p, 0, 1, "fconst_0"); } if(f == 1.0) { jvm_generate(p, 0, 1, "fconst_1"); } if(f == 2.0) { jvm_generate(p, 0, 1, "fconst_2"); } else { jvm_generate(p, 0, 1, "ldc %lf", f); } } else { if(f == 0.0) { jvm_generate(p, 0, 2, "dconst_0"); } if(f == 1.0) { jvm_generate(p, 0, 2, "dconst_1"); } else { jvm_generate(p, 0, 2, "ldc2_w %lf", f); } } } void jvm_generate_push_string(gen_proc_t * p, char * str, int char_size) { assert(char_size == 1); int len = strlen(str); jvm_generate_push_int(p, len + 1); jvm_generate(p, 1, 1, "newarray byte"); for(int i = 0; i < len; i++) { jvm_generate(p, 1, 2, "dup"); jvm_generate_push_int(p, i); jvm_generate_push_int(p, str[i]); jvm_generate(p, 3, 0, "bastore"); } } int jvm_new_label_id(gen_proc_t * p) { int label_id = p -> label_id; p -> label_id += 1; return label_id; } void jvm_generate_label(gen_proc_t * p, int label_id) { jvm_generate(p, 0, 0, "L%i:", label_id); }