DEADSOFTWARE

fac9e0bc0def269786de76b60734d24cceb2fc6e
[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_name(oberon_object_t * x)
280 switch(x -> class)
282 case OBERON_CLASS_VAR:
283 case OBERON_CLASS_VAR_PARAM:
284 case OBERON_CLASS_PARAM:
285 case OBERON_CLASS_FIELD:
286 return new_string(x -> name);
287 case OBERON_CLASS_PROC:
288 if(x -> parent)
290 return new_string("%s$%s", jvm_get_name(x -> parent), x -> name);
292 else
294 return new_string(x -> name);
296 default:
297 gen_error("jvm_get_name: wat");
300 return NULL;
303 char *
304 jvm_get_field_full_name(oberon_object_t * x)
306 char * parent;
307 switch(x -> class)
309 case OBERON_CLASS_VAR:
310 return new_string("%s/%s", x -> module -> name, jvm_get_name(x));
311 case OBERON_CLASS_PROC:
312 return new_string("%s/%s", x -> module -> name, jvm_get_name(x));
313 case OBERON_CLASS_FIELD:
314 parent = jvm_get_class_full_name(x -> parent_type);
315 return new_string("%s/%s", parent, jvm_get_name(x));
316 case OBERON_CLASS_MODULE:
317 return new_string(x -> module -> name);
318 default:
319 gen_error("jvm_get_field_full_name: wat");
320 break;
323 return NULL;
326 char *
327 jvm_get_field_full_name_safe(oberon_object_t * x)
329 switch(x -> class)
331 case OBERON_CLASS_VAR:
332 case OBERON_CLASS_PROC:
333 return new_string("%s$%s", x -> module -> name, x -> name);
334 case OBERON_CLASS_FIELD:;
335 char * rec_name = jvm_get_class_full_name(x -> parent_type);
336 return new_string("%s$%s", rec_name, x -> name);
337 case OBERON_CLASS_MODULE:
338 return new_string(x -> module -> name);
339 default:
340 gen_error("jvm_get_field_full_name: wat");
341 break;
344 return NULL;
347 char *
348 jvm_get_class_full_name(oberon_type_t * type)
350 int rec_id;
351 char * name = NULL;
353 switch(type -> class)
355 case OBERON_TYPE_POINTER:
356 name = jvm_get_class_full_name(type -> base);
357 break;
358 case OBERON_TYPE_PROCEDURE:
359 name = new_string("SYSTEM$PROCEDURE");
361 char * desc;
362 desc = jvm_get_descriptor_safe(type -> base);
363 name = new_string("%s$%s", name, desc);
365 int num = type -> num_decl;
366 oberon_object_t * arg = type -> decl;
367 for(int i = 0; i < num; i++)
369 desc = jvm_get_descriptor_safe(arg -> type);
370 name = new_string("%s%s", name, desc);
371 arg = arg -> next;
374 break;
375 case OBERON_TYPE_RECORD:
376 rec_id = type -> gen_type -> rec_id;
377 name = new_string("%s$RECORD%i", type -> module -> name, rec_id);
378 break;
379 default:
380 gen_error("jvm_get_class_full_name: unk type class %i", type -> class);
381 break;
384 return name;
387 int
388 jvm_cell_size_for_type(oberon_type_t * type)
390 if(type -> class == OBERON_TYPE_INTEGER
391 || type -> class == OBERON_TYPE_REAL
392 || type -> class == OBERON_TYPE_CHAR
393 || type -> class == OBERON_TYPE_SET)
395 if(type -> size > 4)
397 return 2;
400 else if(type -> class == OBERON_TYPE_VOID)
402 return 0;
405 return 1;
408 int
409 jvm_cell_size_for_postfix(char postfix)
411 switch(postfix)
413 case 'a':
414 case 'b':
415 case 's':
416 case 'i':
417 case 'f':
418 return 1;
419 case 'l':
420 case 'd':
421 return 2;
422 default:
423 gen_error("jvm_cell_size_for_postfix: unk postfix %c", postfix);
426 return -666;
429 bool
430 jvm_is_wide_type(oberon_type_t * type)
432 int cell;
433 cell = jvm_cell_size_for_type(type);
434 assert(cell <= 2);
435 return (cell == 2);
438 bool
439 jvm_is_free_register(struct gen_register_file * rf, int i, bool wide)
441 if(wide)
443 assert(i + 1 < MAX_REGISTERS);
444 return !(rf -> reg[i].used || rf -> reg[i + 1].used);
446 else
448 assert(i < MAX_REGISTERS);
449 return !(rf -> reg[i].used);
453 int
454 jvm_alloc_register_untyped(struct gen_register_file * rf, bool wide)
456 int i = 0;
457 while(i < MAX_REGISTERS && !jvm_is_free_register(rf, i, wide))
459 i += 1;
462 if(wide)
464 assert(i + 1 <= MAX_REGISTERS);
465 rf -> num_used += 2;
466 rf -> reg[i].used = true;
467 rf -> reg[i + 1].used = true;
468 rf -> reg[i].used = true;
469 rf -> reg[i + 1].wide = false;
471 else
473 assert(i <= MAX_REGISTERS);
474 rf -> num_used += 1;
475 rf -> reg[i].used = true;
476 rf -> reg[i].wide = false;
479 if(rf -> num_used > rf -> max_used)
481 rf -> max_used = rf -> num_used;
484 return i;
487 int
488 jvm_alloc_register(struct gen_register_file * rf, oberon_type_t * type)
490 bool wide;
491 wide = jvm_is_wide_type(type);
492 return jvm_alloc_register_untyped(rf, wide);
495 char
496 jvm_get_type_of_prefix(char prefix)
498 switch(prefix)
500 case 'b':
501 return 'B';
502 case 'c':
503 return 'C';
504 case 'd':
505 return 'D';
506 case 'f':
507 return 'F';
508 case 'i':
509 return 'I';
510 case 'l':
511 return 'J';
514 assert(0);