DEADSOFTWARE

2b9b5483efa3b7b76050a4c105d3cb4b20dc655c
[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_BOOLEAN:
94 return new_string("Z");
95 break;
96 case OBERON_TYPE_POINTER:
97 return jvm_get_descriptor(type -> base);
98 break;
99 case OBERON_TYPE_PROCEDURE:
100 case OBERON_TYPE_RECORD:
101 desc = jvm_get_class_full_name(type);
102 return new_string("L%s;", desc);
103 break;
104 case OBERON_TYPE_ARRAY:
105 desc = jvm_get_descriptor(type -> base);
106 return new_string("[%s", desc);
107 break;
108 default:
109 gen_error("jvm_get_descriptor: unsupported type class %i", type -> class);
110 break;
113 return NULL;
116 char
117 jvm_get_prefix(oberon_type_t * type)
119 int size = type -> size;
120 switch(type -> class)
122 case OBERON_TYPE_BOOLEAN:
123 case OBERON_TYPE_INTEGER:
124 return (size <= 4) ? ('i') : ('l');
125 break;
126 case OBERON_TYPE_PROCEDURE:
127 case OBERON_TYPE_ARRAY:
128 case OBERON_TYPE_RECORD:
129 case OBERON_TYPE_POINTER:
130 return 'a';
131 break;
132 case OBERON_TYPE_REAL:
133 return (size <= 4) ? ('f') : ('d');
134 break;
137 gen_error("jvm_get_prefix: wat");
138 return '!';
141 char
142 jvm_get_postfix(oberon_type_t * type)
144 int size = type -> size;
145 switch(type -> class)
147 case OBERON_TYPE_BOOLEAN:
148 return 'b';
149 break;
150 case OBERON_TYPE_INTEGER:
151 switch(size)
153 case 1:
154 return 'b';
155 break;
156 case 2:
157 return 's';
158 break;
159 case 4:
160 return 'i';
161 break;
162 case 8:
163 return 'l';
164 break;
165 default:
166 gen_error("jvm_get_postfix: int wat");
167 break;
169 break;
170 case OBERON_TYPE_PROCEDURE:
171 case OBERON_TYPE_ARRAY:
172 case OBERON_TYPE_RECORD:
173 case OBERON_TYPE_POINTER:
174 return 'a';
175 break;
176 case OBERON_TYPE_REAL:
177 return (size <= 4) ? ('f') : ('d');
178 break;
179 default:
180 gen_error("jvm_get_postfix: wat");
181 break;
184 return '!';
187 char *
188 jvm_get_field_full_name(oberon_object_t * x)
190 switch(x -> class)
192 case OBERON_CLASS_VAR:
193 case OBERON_CLASS_PROC:
194 return new_string("%s/%s", x -> module -> name, x -> name);
195 case OBERON_CLASS_FIELD:;
196 char * rec_name = jvm_get_class_full_name(x -> parent_type);
197 return new_string("%s/%s", rec_name, x -> name);
198 case OBERON_CLASS_MODULE:
199 return new_string(x -> module -> name);
200 default:
201 gen_error("jvm_get_field_full_name: wat");
202 break;
205 return NULL;
208 char *
209 jvm_get_field_full_name_safe(oberon_object_t * x)
211 switch(x -> class)
213 case OBERON_CLASS_VAR:
214 case OBERON_CLASS_PROC:
215 return new_string("%s$%s", x -> module -> name, x -> name);
216 case OBERON_CLASS_FIELD:;
217 char * rec_name = jvm_get_class_full_name(x -> parent_type);
218 return new_string("%s$%s", rec_name, x -> name);
219 case OBERON_CLASS_MODULE:
220 return new_string(x -> module -> name);
221 default:
222 gen_error("jvm_get_field_full_name: wat");
223 break;
226 return NULL;
229 char *
230 jvm_get_class_full_name(oberon_type_t * type)
232 int rec_id;
233 char * name = NULL;
235 switch(type -> class)
237 case OBERON_TYPE_POINTER:
238 name = jvm_get_class_full_name(type -> base);
239 break;
240 case OBERON_TYPE_PROCEDURE:
241 name = new_string("SYSTEM$PROCEDURE");
243 char * desc;
244 desc = jvm_get_descriptor(type -> base);
245 name = new_string("%s$%s", name, desc);
247 int num = type -> num_decl;
248 oberon_object_t * arg = type -> decl;
249 for(int i = 0; i < num; i++)
251 desc = jvm_get_descriptor(arg -> type);
252 name = new_string("%s%s", name, desc);
253 arg = arg -> next;
256 break;
257 case OBERON_TYPE_RECORD:
258 rec_id = type -> gen_type -> rec_id;
259 name = new_string("%s$RECORD%i", type -> module -> name, rec_id);
260 break;
261 default:
262 gen_error("jvm_get_class_full_name: unk type class %i", type -> class);
263 break;
266 return name;
269 char *
270 jvm_get_procedure_signature(oberon_type_t * proc)
272 char * signature;
273 char * desc;
275 signature = new_string("(");
277 int num = proc -> num_decl;
278 oberon_object_t * arg = proc -> decl;
279 for(int i = 0; i < num; i++)
281 desc = jvm_get_descriptor(arg -> type);
282 signature = new_string("%s%s", signature, desc);
283 arg = arg -> next;
286 desc = jvm_get_descriptor(proc -> base);
287 signature = new_string("%s)%s", signature, desc);
289 return signature;
292 int
293 jvm_cell_size_for_type(oberon_type_t * type)
295 if(type -> class == OBERON_TYPE_INTEGER
296 || type -> class == OBERON_TYPE_REAL)
298 if(type -> size > 4)
300 return 2;
304 return 1;
307 int
308 jvm_cell_size_for_postfix(char postfix)
310 switch(postfix)
312 case 'a':
313 case 'b':
314 case 's':
315 case 'i':
316 case 'f':
317 return 1;
318 case 'l':
319 case 'd':
320 return 2;
321 default:
322 gen_error("jvm_cell_size_for_postfix: unk postfix %c", postfix);
325 return -666;
328 bool
329 jvm_is_wide_type(oberon_type_t * type)
331 int cell;
332 cell = jvm_cell_size_for_type(type);
333 assert(cell <= 2);
334 return (cell == 2);
337 bool
338 jvm_is_free_register(struct gen_register_file * rf, int i, bool wide)
340 if(wide)
342 assert(i + 1 < MAX_REGISTERS);
343 return !(rf -> reg[i].used || rf -> reg[i + 1].used);
345 else
347 assert(i < MAX_REGISTERS);
348 return !(rf -> reg[i].used);
352 int
353 jvm_alloc_register_untyped(struct gen_register_file * rf, bool wide)
355 int i = 0;
356 while(i < MAX_REGISTERS && !jvm_is_free_register(rf, i, wide))
358 i += 1;
361 if(wide)
363 assert(i + 1 <= MAX_REGISTERS);
364 rf -> num_used += 2;
365 rf -> reg[i].used = true;
366 rf -> reg[i + 1].used = true;
367 rf -> reg[i].used = true;
368 rf -> reg[i + 1].wide = false;
370 else
372 assert(i <= MAX_REGISTERS);
373 rf -> num_used += 1;
374 rf -> reg[i].used = true;
375 rf -> reg[i].wide = false;
378 if(rf -> num_used > rf -> max_used)
380 rf -> max_used = rf -> num_used;
383 return i;
386 int
387 jvm_alloc_register(struct gen_register_file * rf, oberon_type_t * type)
389 bool wide;
390 wide = jvm_is_wide_type(type);
391 return jvm_alloc_register_untyped(rf, wide);
394 char
395 jvm_get_type_of_prefix(char prefix)
397 switch(prefix)
399 case 'b':
400 return 'B';
401 case 'c':
402 return 'C';
403 case 'd':
404 return 'D';
405 case 'f':
406 return 'F';
407 case 'i':
408 return 'I';
409 case 'l':
410 return 'J';
413 assert(0);