DEADSOFTWARE

JVM: Добавлено сравнение строк
[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>
7
8 #include <gc.h>
9
10 #include "../../../include/oberon.h"
11 #include "../../oberon-internals.h"
12 #include "generator-jvm.h"
13 #include "generator-jvm-basic.h"
14
15 char *
16 new_string(const char * format, ...)
17 {
18 va_list ptr;
19 va_start(ptr, format);
20
21 char buf[1024];
22 vsnprintf(buf, 1024, format, ptr);
23
24 va_end(ptr);
25
26 char * result;
27 int size;
28
29 size = strlen(buf);
30 result = GC_MALLOC(size + 1);
31 memset(result, 0, size);
32 strncpy(result, buf, size);
33
34 return result;
35 }
36
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 }
48
49 char *
50 jvm_get_descriptor(oberon_type_t * type)
51 {
52 char * desc;
53
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;
112 }
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)
131 {
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;
147 }
148 break;
149 default:
150 gen_error("jvm_get_descriptor: unsupported type class %i", type -> class);
151 break;
152 }
153
154 return NULL;
155 }
156
157 char *
158 jvm_get_descriptor_safe(oberon_type_t * type)
159 {
160 switch(type -> class)
161 {
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;
175 }
176
177 return NULL;
178 }
179
180 char
181 jvm_get_prefix(oberon_type_t * type)
182 {
183 int size = type -> size;
184 switch(type -> class)
185 {
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;
207 }
208 }
209
210 char
211 jvm_get_postfix(oberon_type_t * type)
212 {
213 int size = type -> size;
214 switch(type -> class)
215 {
216 case OBERON_TYPE_BOOLEAN:
217 return 'b';
218 break;
219 case OBERON_TYPE_INTEGER:
220 case OBERON_TYPE_SET:
221 switch(size)
222 {
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;
238 }
239 break;
240 case OBERON_TYPE_CHAR:
241 switch(size)
242 {
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;
258 }
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;
274 }
275
276 return '!';
277 }
278
279 char *
280 jvm_get_name(oberon_object_t * x)
281 {
282 switch(x -> class)
283 {
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)
291 {
292 return new_string("%s$%s", jvm_get_name(x -> parent), x -> name);
293 }
294 else
295 {
296 return new_string(x -> name);
297 }
298 default:
299 gen_error("jvm_get_name: wat");
300 }
301
302 return NULL;
303 }
304
305 char *
306 jvm_get_field_full_name(oberon_object_t * x)
307 {
308 char * parent;
309 switch(x -> class)
310 {
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;
323 }
324
325 return NULL;
326 }
327
328 char *
329 jvm_get_field_full_name_safe(oberon_object_t * x)
330 {
331 switch(x -> class)
332 {
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;
344 }
345
346 return NULL;
347 }
348
349 char *
350 jvm_get_class_full_name(oberon_type_t * type)
351 {
352 int rec_id;
353 char * name = NULL;
354
355 switch(type -> class)
356 {
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");
362
363 char * desc;
364 desc = jvm_get_descriptor_safe(type -> base);
365 name = new_string("%s$%s", name, desc);
366
367 int num = type -> num_decl;
368 oberon_object_t * arg = type -> decl;
369 for(int i = 0; i < num; i++)
370 {
371 desc = jvm_get_descriptor_safe(arg -> type);
372 name = new_string("%s%s", name, desc);
373 arg = arg -> next;
374 }
375
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;
384 }
385
386 return name;
387 }
388
389 int
390 jvm_cell_size_for_type(oberon_type_t * type)
391 {
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)
396 {
397 if(type -> size > 4)
398 {
399 return 2;
400 }
401 }
402 else if(type -> class == OBERON_TYPE_NOTYPE)
403 {
404 return 0;
405 }
406
407 return 1;
408 }
409
410 int
411 jvm_cell_size_for_postfix(char postfix)
412 {
413 switch(postfix)
414 {
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);
426 }
427
428 return -666;
429 }
430
431 bool
432 jvm_is_wide_type(oberon_type_t * type)
433 {
434 int cell;
435 cell = jvm_cell_size_for_type(type);
436 assert(cell <= 2);
437 return (cell == 2);
438 }
439
440 bool
441 jvm_is_free_register(struct gen_register_file * rf, int i, bool wide)
442 {
443 if(wide)
444 {
445 assert(i + 1 < MAX_REGISTERS);
446 return !(rf -> reg[i].used || rf -> reg[i + 1].used);
447 }
448 else
449 {
450 assert(i < MAX_REGISTERS);
451 return !(rf -> reg[i].used);
452 }
453 }
454
455 int
456 jvm_alloc_register_untyped(struct gen_register_file * rf, bool wide)
457 {
458 int i = 0;
459 while(i < MAX_REGISTERS && !jvm_is_free_register(rf, i, wide))
460 {
461 i += 1;
462 }
463
464 if(wide)
465 {
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;
472 }
473 else
474 {
475 assert(i <= MAX_REGISTERS);
476 rf -> num_used += 1;
477 rf -> reg[i].used = true;
478 rf -> reg[i].wide = false;
479 }
480
481 if(rf -> num_used > rf -> max_used)
482 {
483 rf -> max_used = rf -> num_used;
484 }
485
486 return i;
487 }
488
489 int
490 jvm_alloc_register(struct gen_register_file * rf, oberon_type_t * type)
491 {
492 bool wide;
493 wide = jvm_is_wide_type(type);
494 return jvm_alloc_register_untyped(rf, wide);
495 }
496
497 char
498 jvm_get_type_of_prefix(char prefix)
499 {
500 switch(prefix)
501 {
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';
514 }
515
516 assert(0);
517 }