DEADSOFTWARE

aad9747f25cbf4d091e86db1f0ea9a3d098753dc
[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 switch(type -> size)
61 {
62 case 1:
63 return new_string("B");
64 break;
65 case 2:
66 return new_string("S");
67 break;
68 case 4:
69 return new_string("I");
70 break;
71 case 8:
72 return new_string("J");
73 break;
74 default:
75 gen_error("jvm_get_descriptor: unsupported int size %i", type -> size);
76 break;
77 }
78 break;
79 case OBERON_TYPE_REAL:
80 switch(type -> size)
81 {
82 case 4:
83 return new_string("F");
84 break;
85 case 8:
86 return new_string("D");
87 break;
88 default:
89 gen_error("jvm_get_descriptor: unsupported float size %i", type -> size);
90 break;
91 }
92 break;
93 case OBERON_TYPE_CHAR:
94 switch(type -> size)
95 {
96 case 1:
97 return new_string("B");
98 break;
99 case 2:
100 return new_string("C");
101 break;
102 case 4:
103 return new_string("I");
104 break;
105 case 8:
106 return new_string("J");
107 break;
108 default:
109 gen_error("jvm_get_descriptor: unsupported char size %i", type -> size);
110 break;
112 break;
113 case OBERON_TYPE_BOOLEAN:
114 return new_string("Z");
115 break;
116 case OBERON_TYPE_POINTER:
117 return jvm_get_descriptor(type -> base);
118 break;
119 case OBERON_TYPE_PROCEDURE:
120 case OBERON_TYPE_RECORD:
121 desc = jvm_get_class_full_name(type);
122 return new_string("L%s;", desc);
123 break;
124 case OBERON_TYPE_ARRAY:
125 desc = jvm_get_descriptor(type -> base);
126 return new_string("[%s", desc);
127 break;
128 default:
129 gen_error("jvm_get_descriptor: unsupported type class %i", type -> class);
130 break;
133 return NULL;
136 char
137 jvm_get_prefix(oberon_type_t * type)
139 int size = type -> size;
140 switch(type -> class)
142 case OBERON_TYPE_BOOLEAN:
143 case OBERON_TYPE_INTEGER:
144 case OBERON_TYPE_CHAR:
145 return (size <= 4) ? ('i') : ('l');
146 break;
147 case OBERON_TYPE_PROCEDURE:
148 case OBERON_TYPE_ARRAY:
149 case OBERON_TYPE_RECORD:
150 case OBERON_TYPE_POINTER:
151 return 'a';
152 break;
153 case OBERON_TYPE_REAL:
154 return (size <= 4) ? ('f') : ('d');
155 break;
156 default:
157 gen_error("jvm_get_prefix: wat");
158 return '!';
159 break;
163 char
164 jvm_get_postfix(oberon_type_t * type)
166 int size = type -> size;
167 switch(type -> class)
169 case OBERON_TYPE_BOOLEAN:
170 return 'b';
171 break;
172 case OBERON_TYPE_INTEGER:
173 switch(size)
175 case 1:
176 return 'b';
177 break;
178 case 2:
179 return 's';
180 break;
181 case 4:
182 return 'i';
183 break;
184 case 8:
185 return 'l';
186 break;
187 default:
188 gen_error("jvm_get_postfix: int wat");
189 break;
191 break;
192 case OBERON_TYPE_CHAR:
193 switch(size)
195 case 1:
196 return 'b';
197 break;
198 case 2:
199 return 'c';
200 break;
201 case 4:
202 return 'i';
203 break;
204 case 8:
205 return 'l';
206 break;
207 default:
208 gen_error("jvm_get_postfix: char wat");
209 break;
211 break;
212 case OBERON_TYPE_PROCEDURE:
213 case OBERON_TYPE_ARRAY:
214 case OBERON_TYPE_RECORD:
215 case OBERON_TYPE_POINTER:
216 return 'a';
217 break;
218 case OBERON_TYPE_REAL:
219 return (size <= 4) ? ('f') : ('d');
220 break;
221 default:
222 gen_error("jvm_get_postfix: wat");
223 break;
226 return '!';
229 char *
230 jvm_get_field_full_name(oberon_object_t * x)
232 switch(x -> class)
234 case OBERON_CLASS_VAR:
235 case OBERON_CLASS_PROC:
236 return new_string("%s/%s", x -> module -> name, x -> name);
237 case OBERON_CLASS_FIELD:;
238 char * rec_name = jvm_get_class_full_name(x -> parent_type);
239 return new_string("%s/%s", rec_name, x -> name);
240 case OBERON_CLASS_MODULE:
241 return new_string(x -> module -> name);
242 default:
243 gen_error("jvm_get_field_full_name: wat");
244 break;
247 return NULL;
250 char *
251 jvm_get_field_full_name_safe(oberon_object_t * x)
253 switch(x -> class)
255 case OBERON_CLASS_VAR:
256 case OBERON_CLASS_PROC:
257 return new_string("%s$%s", x -> module -> name, x -> name);
258 case OBERON_CLASS_FIELD:;
259 char * rec_name = jvm_get_class_full_name(x -> parent_type);
260 return new_string("%s$%s", rec_name, x -> name);
261 case OBERON_CLASS_MODULE:
262 return new_string(x -> module -> name);
263 default:
264 gen_error("jvm_get_field_full_name: wat");
265 break;
268 return NULL;
271 char *
272 jvm_get_class_full_name(oberon_type_t * type)
274 int rec_id;
275 char * name = NULL;
277 switch(type -> class)
279 case OBERON_TYPE_POINTER:
280 name = jvm_get_class_full_name(type -> base);
281 break;
282 case OBERON_TYPE_PROCEDURE:
283 name = new_string("SYSTEM$PROCEDURE");
285 char * desc;
286 desc = jvm_get_descriptor(type -> base);
287 name = new_string("%s$%s", name, desc);
289 int num = type -> num_decl;
290 oberon_object_t * arg = type -> decl;
291 for(int i = 0; i < num; i++)
293 desc = jvm_get_descriptor(arg -> type);
294 name = new_string("%s%s", name, desc);
295 arg = arg -> next;
298 break;
299 case OBERON_TYPE_RECORD:
300 rec_id = type -> gen_type -> rec_id;
301 name = new_string("%s$RECORD%i", type -> module -> name, rec_id);
302 break;
303 default:
304 gen_error("jvm_get_class_full_name: unk type class %i", type -> class);
305 break;
308 return name;
311 char *
312 jvm_get_procedure_signature(oberon_type_t * proc)
314 char * signature;
315 char * desc;
317 signature = new_string("(");
319 int num = proc -> num_decl;
320 oberon_object_t * arg = proc -> decl;
321 for(int i = 0; i < num; i++)
323 desc = jvm_get_descriptor(arg -> type);
324 signature = new_string("%s%s", signature, desc);
325 arg = arg -> next;
328 desc = jvm_get_descriptor(proc -> base);
329 signature = new_string("%s)%s", signature, desc);
331 return signature;
334 int
335 jvm_cell_size_for_type(oberon_type_t * type)
337 if(type -> class == OBERON_TYPE_INTEGER
338 || type -> class == OBERON_TYPE_REAL)
340 if(type -> size > 4)
342 return 2;
346 return 1;
349 int
350 jvm_cell_size_for_postfix(char postfix)
352 switch(postfix)
354 case 'a':
355 case 'b':
356 case 's':
357 case 'i':
358 case 'f':
359 return 1;
360 case 'l':
361 case 'd':
362 return 2;
363 default:
364 gen_error("jvm_cell_size_for_postfix: unk postfix %c", postfix);
367 return -666;
370 bool
371 jvm_is_wide_type(oberon_type_t * type)
373 int cell;
374 cell = jvm_cell_size_for_type(type);
375 assert(cell <= 2);
376 return (cell == 2);
379 bool
380 jvm_is_free_register(struct gen_register_file * rf, int i, bool wide)
382 if(wide)
384 assert(i + 1 < MAX_REGISTERS);
385 return !(rf -> reg[i].used || rf -> reg[i + 1].used);
387 else
389 assert(i < MAX_REGISTERS);
390 return !(rf -> reg[i].used);
394 int
395 jvm_alloc_register_untyped(struct gen_register_file * rf, bool wide)
397 int i = 0;
398 while(i < MAX_REGISTERS && !jvm_is_free_register(rf, i, wide))
400 i += 1;
403 if(wide)
405 assert(i + 1 <= MAX_REGISTERS);
406 rf -> num_used += 2;
407 rf -> reg[i].used = true;
408 rf -> reg[i + 1].used = true;
409 rf -> reg[i].used = true;
410 rf -> reg[i + 1].wide = false;
412 else
414 assert(i <= MAX_REGISTERS);
415 rf -> num_used += 1;
416 rf -> reg[i].used = true;
417 rf -> reg[i].wide = false;
420 if(rf -> num_used > rf -> max_used)
422 rf -> max_used = rf -> num_used;
425 return i;
428 int
429 jvm_alloc_register(struct gen_register_file * rf, oberon_type_t * type)
431 bool wide;
432 wide = jvm_is_wide_type(type);
433 return jvm_alloc_register_untyped(rf, wide);
436 char
437 jvm_get_type_of_prefix(char prefix)
439 switch(prefix)
441 case 'b':
442 return 'B';
443 case 'c':
444 return 'C';
445 case 'd':
446 return 'D';
447 case 'f':
448 return 'F';
449 case 'i':
450 return 'I';
451 case 'l':
452 return 'J';
455 assert(0);