DEADSOFTWARE

9c8b78c598e73aaacc9644309c4e5a654146ad44
[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_NOTYPE:
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 case OBERON_TYPE_NIL:
198 return 'a';
199 break;
200 case OBERON_TYPE_REAL:
201 return (size <= 4) ? ('f') : ('d');
202 break;
203 default:
204 gen_error("jvm_get_prefix: wat %i", type -> class);
205 return '!';
206 break;
210 char
211 jvm_get_postfix(oberon_type_t * type)
213 int size = type -> size;
214 switch(type -> class)
216 case OBERON_TYPE_BOOLEAN:
217 return 'b';
218 break;
219 case OBERON_TYPE_INTEGER:
220 case OBERON_TYPE_SET:
221 switch(size)
223 case 1:
224 return 'b';
225 break;
226 case 2:
227 return 's';
228 break;
229 case 4:
230 return 'i';
231 break;
232 case 8:
233 return 'l';
234 break;
235 default:
236 gen_error("jvm_get_postfix: int wat");
237 break;
239 break;
240 case OBERON_TYPE_CHAR:
241 switch(size)
243 case 1:
244 return 'b';
245 break;
246 case 2:
247 return 'c';
248 break;
249 case 4:
250 return 'i';
251 break;
252 case 8:
253 return 'l';
254 break;
255 default:
256 gen_error("jvm_get_postfix: char wat");
257 break;
259 break;
260 case OBERON_TYPE_PROCEDURE:
261 case OBERON_TYPE_ARRAY:
262 case OBERON_TYPE_RECORD:
263 case OBERON_TYPE_POINTER:
264 case OBERON_TYPE_STRING:
265 case OBERON_TYPE_NIL:
266 return 'a';
267 break;
268 case OBERON_TYPE_REAL:
269 return (size <= 4) ? ('f') : ('d');
270 break;
271 default:
272 gen_error("jvm_get_postfix: wat");
273 break;
276 return '!';
279 char *
280 jvm_get_name(oberon_object_t * x)
282 switch(x -> class)
284 case OBERON_CLASS_VAR:
285 case OBERON_CLASS_VAR_PARAM:
286 case OBERON_CLASS_PARAM:
287 case OBERON_CLASS_FIELD:
288 return new_string(x -> name);
289 case OBERON_CLASS_PROC:
290 if(x -> parent)
292 return new_string("%s$%s", jvm_get_name(x -> parent), x -> name);
294 else
296 return new_string(x -> name);
298 default:
299 gen_error("jvm_get_name: wat");
302 return NULL;
305 char *
306 jvm_get_field_full_name(oberon_object_t * x)
308 char * parent;
309 switch(x -> class)
311 case OBERON_CLASS_VAR:
312 return new_string("%s/%s", x -> module -> name, jvm_get_name(x));
313 case OBERON_CLASS_PROC:
314 return new_string("%s/%s", x -> module -> name, jvm_get_name(x));
315 case OBERON_CLASS_FIELD:
316 parent = jvm_get_class_full_name(x -> parent_type);
317 return new_string("%s/%s", parent, jvm_get_name(x));
318 case OBERON_CLASS_MODULE:
319 return new_string(x -> module -> name);
320 default:
321 gen_error("jvm_get_field_full_name: wat");
322 break;
325 return NULL;
328 char *
329 jvm_get_field_full_name_safe(oberon_object_t * x)
331 switch(x -> class)
333 case OBERON_CLASS_VAR:
334 case OBERON_CLASS_PROC:
335 return new_string("%s$%s", x -> module -> name, x -> name);
336 case OBERON_CLASS_FIELD:;
337 char * rec_name = jvm_get_class_full_name(x -> parent_type);
338 return new_string("%s$%s", rec_name, x -> name);
339 case OBERON_CLASS_MODULE:
340 return new_string(x -> module -> name);
341 default:
342 gen_error("jvm_get_field_full_name: wat");
343 break;
346 return NULL;
349 char *
350 jvm_get_class_full_name(oberon_type_t * type)
352 int rec_id;
353 char * name = NULL;
355 switch(type -> class)
357 case OBERON_TYPE_POINTER:
358 name = jvm_get_class_full_name(type -> base);
359 break;
360 case OBERON_TYPE_PROCEDURE:
361 name = new_string("SYSTEM$PROCEDURE");
363 char * desc;
364 desc = jvm_get_descriptor_safe(type -> base);
365 name = new_string("%s$%s", name, desc);
367 int num = type -> num_decl;
368 oberon_object_t * arg = type -> decl;
369 for(int i = 0; i < num; i++)
371 desc = jvm_get_descriptor_safe(arg -> type);
372 name = new_string("%s%s", name, desc);
373 arg = arg -> next;
376 break;
377 case OBERON_TYPE_RECORD:
378 rec_id = type -> gen_type -> rec_id;
379 name = new_string("%s$RECORD%i", type -> module -> name, rec_id);
380 break;
381 default:
382 gen_error("jvm_get_class_full_name: unk type class %i", type -> class);
383 break;
386 return name;
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_NOTYPE)
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);