DEADSOFTWARE

Теперь можно указывать куда сгружать высер кодогенератора
[dsw-obn.git] / src / backends / jvm / generator-jvm-asm.c
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <stdarg.h>
4 #include <stdint.h>
5 #include <stdbool.h>
6 #include <string.h>
7 #include <assert.h>
9 #include <gc.h>
11 #include "../../../include/oberon.h"
12 #include "../../oberon-internals.h"
13 #include "generator-jvm.h"
14 #include "generator-jvm-abi.h"
15 #include "generator-jvm-asm.h"
16 #include "generator-jvm-basic.h"
18 gen_proc_t *
19 jvm_create_proc(struct gen_class * class)
20 {
21 gen_proc_t * p = GC_MALLOC(sizeof *p);
22 memset(p, 0, sizeof *p);
24 struct gen_register_file * rf = GC_MALLOC(sizeof *rf);
25 memset(rf, 0, sizeof *rf);
27 struct gen_stack * stack = GC_MALLOC(sizeof *stack);
28 memset(rf, 0, sizeof *stack);
30 p -> rf = rf;
31 p -> stack = stack;
32 p -> class = class;
33 p -> label_id = 0;
35 return p;
36 }
38 void
39 jvm_generate_function_header(gen_proc_t * p, char * access, char * name, char * signature)
40 {
41 struct gen_class * class;
42 class = p -> class;
44 /* Делаем процедуру текущей в этом классе */
45 assert(class -> p == NULL);
46 class -> p = p;
48 fprintf(class -> fp, ".method %s %s%s\n", access, name, signature);
49 fprintf(class -> fp, " start:\n");
50 }
52 void
53 jvm_generate_function_end(gen_proc_t * p)
54 {
55 struct gen_class * class;
56 class = p -> class;
58 assert(class -> p);
59 class -> p = NULL;
61 int pointer = p -> stack -> pointer;
62 int max_pointer = p -> stack -> max_pointer;
63 int locals = p -> rf -> num_used;
64 int max_locals = p -> rf -> max_used;
66 fprintf(class -> fp, " .limit stack %i \t; current(%i)\n", max_pointer, pointer);
67 fprintf(class -> fp, " .limit locals %i \t; current(%i)\n", max_locals, locals);
68 fprintf(class -> fp, " end:\n");
69 fprintf(class -> fp, ".end method\n\n");
70 }
72 struct gen_class *
73 jvm_create_class(const char * dir, char * full_name)
74 {
75 struct gen_class * class = GC_MALLOC(sizeof *class);
76 memset(class, 0, sizeof *class);
78 char * fname = new_string("%s/%s.j", dir, full_name);
79 class -> full_name = new_string(full_name);
80 class -> fp = fopen(fname, "w");
81 class -> dir = new_string(dir);
83 if(class -> fp == NULL)
84 {
85 gen_error("unable to create file %s", fname);
86 }
88 return class;
89 }
91 void
92 jvm_destroy_class(struct gen_class * class)
93 {
94 assert(class -> p == NULL);
95 fclose(class -> fp);
96 }
98 void
99 jvm_stack_push(gen_proc_t * p, unsigned size)
101 p -> stack -> pointer += size;
102 if(p -> stack -> pointer > p -> stack -> max_pointer)
104 p -> stack -> max_pointer = p -> stack -> pointer;
108 void
109 jvm_stack_pop(gen_proc_t * p, unsigned size)
111 p -> stack -> pointer -= size;
113 if(p -> stack -> pointer < 0)
115 printf("WARING: stack pointer %i\n", p -> stack -> pointer);
119 void
120 jvm_generate(gen_proc_t * p, unsigned get, unsigned push, char * format, ...)
122 va_list ptr;
123 va_start(ptr, format);
125 jvm_stack_pop(p, get);
126 fprintf(p -> class -> fp, " ");
127 vfprintf(p -> class -> fp, format, ptr);
128 jvm_stack_push(p, push);
129 fprintf(p -> class -> fp, " \t ;>>>> %i -- %i : current_stack(%i)\n", get, push, p -> stack -> pointer);
131 va_end(ptr);
134 void
135 jvm_generate_comment(gen_proc_t * p, char * format, ...)
137 va_list ptr;
138 va_start(ptr, format);
140 fprintf(p -> class -> fp, " ;;;; ");
141 vfprintf(p -> class -> fp, format, ptr);
142 fprintf(p -> class -> fp, "\n");
144 va_end(ptr);
147 void
148 jvm_generate_push_int(gen_proc_t * p, int64_t i)
150 if(i == -1)
152 jvm_generate(p, 0, 1, "iconst_m1");
154 else if(i >= 0 && i <= 5)
156 jvm_generate(p, 0, 1, "iconst_%li", i);
158 else if(i >= -128 && i <= 127)
160 jvm_generate(p, 0, 1, "bipush %li", i);
162 else if(i >= -32768 && i <= 32767)
164 jvm_generate(p, 0, 1, "sipush %li", i);
166 else if(i >= -2147483648 && i <= 2147483647)
168 jvm_generate(p, 0, 1, "ldc %li", i);
170 else
172 jvm_generate(p, 0, 2, "ldc2_w %li", i);
176 void
177 jvm_generate_push_int_size(gen_proc_t * p, int64_t i, int size)
179 int pushed_cell = 1;
181 if(i == -1)
183 jvm_generate(p, 0, 1, "iconst_m1");
185 else if(i >= 0 && i <= 5)
187 jvm_generate(p, 0, 1, "iconst_%li", i);
189 else if(i >= -128 && i <= 127)
191 jvm_generate(p, 0, 1, "bipush %li", i);
193 else if(i >= -32768 && i <= 32767)
195 jvm_generate(p, 0, 1, "sipush %li", i);
197 else if(i >= -2147483648 && i <= 2147483647)
199 jvm_generate(p, 0, 1, "ldc %li", i);
201 else
203 pushed_cell = 2;
204 jvm_generate(p, 0, 2, "ldc2_w %li", i);
207 assert(size <= 8);
208 if(size > 4 && pushed_cell == 1)
210 jvm_generate(p, pushed_cell, 2, "i2l");
212 else if(size <= 4)
214 if(pushed_cell > 1)
216 jvm_generate(p, 2, 1, "l2i");
219 if(size == 2)
221 jvm_generate(p, 1, 1, "i2s");
223 else if(size == 1)
225 jvm_generate(p, 1, 1, "i2b");
230 void
231 jvm_generate_push_float(gen_proc_t * p, double f, int size)
233 if(size <= 4)
235 if(f == 0.0)
237 jvm_generate(p, 0, 1, "fconst_0");
239 if(f == 1.0)
241 jvm_generate(p, 0, 1, "fconst_1");
243 if(f == 2.0)
245 jvm_generate(p, 0, 1, "fconst_2");
247 else
249 jvm_generate(p, 0, 1, "ldc %lf", f);
252 else
254 if(f == 0.0)
256 jvm_generate(p, 0, 2, "dconst_0");
258 if(f == 1.0)
260 jvm_generate(p, 0, 2, "dconst_1");
262 else
264 jvm_generate(p, 0, 2, "ldc2_w %lf", f);
269 void
270 jvm_generate_push_string(gen_proc_t * p, char * str, int char_size)
272 assert(char_size == 1);
273 int len = strlen(str);
275 jvm_generate_push_int(p, len + 1);
276 jvm_generate(p, 1, 1, "newarray byte");
278 for(int i = 0; i < len; i++)
280 jvm_generate(p, 1, 2, "dup");
281 jvm_generate_push_int(p, i);
282 jvm_generate_push_int(p, str[i]);
283 jvm_generate(p, 3, 0, "bastore");
287 int
288 jvm_new_label_id(gen_proc_t * p)
290 int label_id = p -> label_id;
291 p -> label_id += 1;
292 return label_id;
295 void
296 jvm_generate_label(gen_proc_t * p, int label_id)
298 jvm_generate(p, 0, 0, "L%i:", label_id);