DEADSOFTWARE

JVM: Реализованы VAR-параметры
[dsw-obn.git] / src / backends / jvm / generator-jvm-basic.c
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <stdarg.h>
4 #include <stdbool.h>
5 #include <string.h>
6 #include <assert.h>
8 #include <gc.h>
10 #include "../../../include/oberon.h"
11 #include "../../oberon-internals.h"
12 #include "generator-jvm.h"
13 #include "generator-jvm-basic.h"
15 char *
16 new_string(const char * format, ...)
17 {
18 va_list ptr;
19 va_start(ptr, format);
21 char buf[1024];
22 vsnprintf(buf, 1024, format, ptr);
24 va_end(ptr);
26 char * result;
27 int size;
29 size = strlen(buf);
30 result = GC_MALLOC(size + 1);
31 memset(result, 0, size);
32 strncpy(result, buf, size);
34 return result;
35 }
37 void
38 gen_error(const char * fmt, ...)
39 {
40 va_list ptr;
41 va_start(ptr, fmt);
42 fprintf(stderr, "generator: ");
43 vfprintf(stderr, fmt, ptr);
44 fprintf(stderr, "\n");
45 va_end(ptr);
46 exit(1);
47 }
49 char *
50 jvm_get_descriptor(oberon_type_t * type)
51 {
52 char * desc;
54 switch(type -> class)
55 {
56 case OBERON_TYPE_VOID:
57 return new_string("V");
58 break;
59 case OBERON_TYPE_INTEGER:
60 case OBERON_TYPE_SET:
61 switch(type -> size)
62 {
63 case 1:
64 return new_string("B");
65 break;
66 case 2:
67 return new_string("S");
68 break;
69 case 4:
70 return new_string("I");
71 break;
72 case 8:
73 return new_string("J");
74 break;
75 default:
76 gen_error("jvm_get_descriptor: unsupported int size %i", type -> size);
77 break;
78 }
79 break;
80 case OBERON_TYPE_REAL:
81 switch(type -> size)
82 {
83 case 4:
84 return new_string("F");
85 break;
86 case 8:
87 return new_string("D");
88 break;
89 default:
90 gen_error("jvm_get_descriptor: unsupported float size %i", type -> size);
91 break;
92 }
93 break;
94 case OBERON_TYPE_CHAR:
95 switch(type -> size)
96 {
97 case 1:
98 return new_string("B");
99 break;
100 case 2:
101 return new_string("C");
102 break;
103 case 4:
104 return new_string("I");
105 break;
106 case 8:
107 return new_string("J");
108 break;
109 default:
110 gen_error("jvm_get_descriptor: unsupported char size %i", type -> size);
111 break;
113 break;
114 case OBERON_TYPE_BOOLEAN:
115 return new_string("Z");
116 break;
117 case OBERON_TYPE_POINTER:
118 return jvm_get_descriptor(type -> base);
119 break;
120 case OBERON_TYPE_PROCEDURE:
121 case OBERON_TYPE_RECORD:
122 desc = jvm_get_class_full_name(type);
123 return new_string("L%s;", desc);
124 break;
125 case OBERON_TYPE_ARRAY:
126 desc = jvm_get_descriptor(type -> base);
127 return new_string("[%s", desc);
128 break;
129 case OBERON_TYPE_STRING:
130 switch(type -> size)
132 case 1:
133 return new_string("[B");
134 break;
135 case 2:
136 return new_string("[C");
137 break;
138 case 4:
139 return new_string("[I");
140 break;
141 case 8:
142 return new_string("[J");
143 break;
144 default:
145 gen_error("jvm_get_descriptor: unsupported string size %i", type -> size);
146 break;
148 break;
149 default:
150 gen_error("jvm_get_descriptor: unsupported type class %i", type -> class);
151 break;
154 return NULL;
157 char *
158 jvm_get_descriptor_safe(oberon_type_t * type)
160 switch(type -> class)
162 case OBERON_TYPE_POINTER:
163 return new_string("PTR%s", jvm_get_descriptor_safe(type -> base));
164 break;
165 case OBERON_TYPE_PROCEDURE:
166 case OBERON_TYPE_RECORD:
167 return jvm_get_class_full_name(type);
168 break;
169 case OBERON_TYPE_ARRAY:
170 return new_string("A%s", jvm_get_descriptor_safe(type -> base));
171 break;
172 default:
173 return jvm_get_descriptor(type);
174 break;
177 return NULL;
180 char
181 jvm_get_prefix(oberon_type_t * type)
183 int size = type -> size;
184 switch(type -> class)
186 case OBERON_TYPE_BOOLEAN:
187 case OBERON_TYPE_INTEGER:
188 case OBERON_TYPE_CHAR:
189 case OBERON_TYPE_SET:
190 return (size <= 4) ? ('i') : ('l');
191 break;
192 case OBERON_TYPE_PROCEDURE:
193 case OBERON_TYPE_ARRAY:
194 case OBERON_TYPE_RECORD:
195 case OBERON_TYPE_POINTER:
196 case OBERON_TYPE_STRING:
197 return 'a';
198 break;
199 case OBERON_TYPE_REAL:
200 return (size <= 4) ? ('f') : ('d');
201 break;
202 default:
203 gen_error("jvm_get_prefix: wat %i", type -> class);
204 return '!';
205 break;
209 char
210 jvm_get_postfix(oberon_type_t * type)
212 int size = type -> size;
213 switch(type -> class)
215 case OBERON_TYPE_BOOLEAN:
216 return 'b';
217 break;
218 case OBERON_TYPE_INTEGER:
219 case OBERON_TYPE_SET:
220 switch(size)
222 case 1:
223 return 'b';
224 break;
225 case 2:
226 return 's';
227 break;
228 case 4:
229 return 'i';
230 break;
231 case 8:
232 return 'l';
233 break;
234 default:
235 gen_error("jvm_get_postfix: int wat");
236 break;
238 break;
239 case OBERON_TYPE_CHAR:
240 switch(size)
242 case 1:
243 return 'b';
244 break;
245 case 2:
246 return 'c';
247 break;
248 case 4:
249 return 'i';
250 break;
251 case 8:
252 return 'l';
253 break;
254 default:
255 gen_error("jvm_get_postfix: char wat");
256 break;
258 break;
259 case OBERON_TYPE_PROCEDURE:
260 case OBERON_TYPE_ARRAY:
261 case OBERON_TYPE_RECORD:
262 case OBERON_TYPE_POINTER:
263 case OBERON_TYPE_STRING:
264 return 'a';
265 break;
266 case OBERON_TYPE_REAL:
267 return (size <= 4) ? ('f') : ('d');
268 break;
269 default:
270 gen_error("jvm_get_postfix: wat");
271 break;
274 return '!';
277 char *
278 jvm_get_field_full_name(oberon_object_t * x)
280 switch(x -> class)
282 case OBERON_CLASS_VAR:
283 case OBERON_CLASS_PROC:
284 return new_string("%s/%s", x -> module -> name, x -> name);
285 case OBERON_CLASS_FIELD:;
286 char * rec_name = jvm_get_class_full_name(x -> parent_type);
287 return new_string("%s/%s", rec_name, x -> name);
288 case OBERON_CLASS_MODULE:
289 return new_string(x -> module -> name);
290 default:
291 gen_error("jvm_get_field_full_name: wat");
292 break;
295 return NULL;
298 char *
299 jvm_get_field_full_name_safe(oberon_object_t * x)
301 switch(x -> class)
303 case OBERON_CLASS_VAR:
304 case OBERON_CLASS_PROC:
305 return new_string("%s$%s", x -> module -> name, x -> name);
306 case OBERON_CLASS_FIELD:;
307 char * rec_name = jvm_get_class_full_name(x -> parent_type);
308 return new_string("%s$%s", rec_name, x -> name);
309 case OBERON_CLASS_MODULE:
310 return new_string(x -> module -> name);
311 default:
312 gen_error("jvm_get_field_full_name: wat");
313 break;
316 return NULL;
319 char *
320 jvm_get_class_full_name(oberon_type_t * type)
322 int rec_id;
323 char * name = NULL;
325 switch(type -> class)
327 case OBERON_TYPE_POINTER:
328 name = jvm_get_class_full_name(type -> base);
329 break;
330 case OBERON_TYPE_PROCEDURE:
331 name = new_string("SYSTEM$PROCEDURE");
333 char * desc;
334 desc = jvm_get_descriptor_safe(type -> base);
335 name = new_string("%s$%s", name, desc);
337 int num = type -> num_decl;
338 oberon_object_t * arg = type -> decl;
339 for(int i = 0; i < num; i++)
341 desc = jvm_get_descriptor_safe(arg -> type);
342 name = new_string("%s%s", name, desc);
343 arg = arg -> next;
346 break;
347 case OBERON_TYPE_RECORD:
348 rec_id = type -> gen_type -> rec_id;
349 name = new_string("%s$RECORD%i", type -> module -> name, rec_id);
350 break;
351 default:
352 gen_error("jvm_get_class_full_name: unk type class %i", type -> class);
353 break;
356 return name;
359 char *
360 jvm_get_procedure_signature(oberon_type_t * proc)
362 char * signature;
363 char * desc;
365 signature = new_string("(");
367 int num = proc -> num_decl;
368 oberon_object_t * arg = proc -> decl;
369 for(int i = 0; i < num; i++)
371 desc = jvm_get_descriptor(arg -> type);
372 if(arg -> class == OBERON_CLASS_VAR_PARAM)
374 signature = new_string("%s[%sI", signature, desc);
376 else
378 signature = new_string("%s%s", signature, desc);
380 arg = arg -> next;
383 desc = jvm_get_descriptor(proc -> base);
384 signature = new_string("%s)%s", signature, desc);
386 return signature;
389 int
390 jvm_cell_size_for_type(oberon_type_t * type)
392 if(type -> class == OBERON_TYPE_INTEGER
393 || type -> class == OBERON_TYPE_REAL
394 || type -> class == OBERON_TYPE_CHAR
395 || type -> class == OBERON_TYPE_SET)
397 if(type -> size > 4)
399 return 2;
402 else if(type -> class == OBERON_TYPE_VOID)
404 return 0;
407 return 1;
410 int
411 jvm_cell_size_for_postfix(char postfix)
413 switch(postfix)
415 case 'a':
416 case 'b':
417 case 's':
418 case 'i':
419 case 'f':
420 return 1;
421 case 'l':
422 case 'd':
423 return 2;
424 default:
425 gen_error("jvm_cell_size_for_postfix: unk postfix %c", postfix);
428 return -666;
431 bool
432 jvm_is_wide_type(oberon_type_t * type)
434 int cell;
435 cell = jvm_cell_size_for_type(type);
436 assert(cell <= 2);
437 return (cell == 2);
440 bool
441 jvm_is_free_register(struct gen_register_file * rf, int i, bool wide)
443 if(wide)
445 assert(i + 1 < MAX_REGISTERS);
446 return !(rf -> reg[i].used || rf -> reg[i + 1].used);
448 else
450 assert(i < MAX_REGISTERS);
451 return !(rf -> reg[i].used);
455 int
456 jvm_alloc_register_untyped(struct gen_register_file * rf, bool wide)
458 int i = 0;
459 while(i < MAX_REGISTERS && !jvm_is_free_register(rf, i, wide))
461 i += 1;
464 if(wide)
466 assert(i + 1 <= MAX_REGISTERS);
467 rf -> num_used += 2;
468 rf -> reg[i].used = true;
469 rf -> reg[i + 1].used = true;
470 rf -> reg[i].used = true;
471 rf -> reg[i + 1].wide = false;
473 else
475 assert(i <= MAX_REGISTERS);
476 rf -> num_used += 1;
477 rf -> reg[i].used = true;
478 rf -> reg[i].wide = false;
481 if(rf -> num_used > rf -> max_used)
483 rf -> max_used = rf -> num_used;
486 return i;
489 int
490 jvm_alloc_register(struct gen_register_file * rf, oberon_type_t * type)
492 bool wide;
493 wide = jvm_is_wide_type(type);
494 return jvm_alloc_register_untyped(rf, wide);
497 char
498 jvm_get_type_of_prefix(char prefix)
500 switch(prefix)
502 case 'b':
503 return 'B';
504 case 'c':
505 return 'C';
506 case 'd':
507 return 'D';
508 case 'f':
509 return 'F';
510 case 'i':
511 return 'I';
512 case 'l':
513 return 'J';
516 assert(0);