1 /******************************* comp/reg.c ************************************
3 Copyright (c) 1997 A. Krall, R. Grafl, M. Gschwind, M. Probst
5 See file COPYRIGHT for information on usage and disclaimer of warranties
9 Authors: Andreas Krall EMAIL: cacao@complang.tuwien.ac.at
10 Reinhard Grafl EMAIL: cacao@complang.tuwien.ac.at
12 Last Change: 1997/10/23
14 *******************************************************************************/
16 static varinfo5 *locals;
17 static varinfo5 *interfaces;
19 static int intregsnum; /* absolute number of integer registers */
20 static int floatregsnum; /* absolute number of float registers */
22 static int intreg_ret; /* register to return integer values */
23 static int intreg_argnum; /* number of integer argument registers */
25 static int floatreg_ret; /* register for return float values */
26 static int fltreg_argnum; /* number of float argument registers */
29 static int *argintregs; /* scratch integer registers */
30 static int *tmpintregs = NULL; /* scratch integer registers */
31 static int *savintregs; /* saved integer registers */
32 static int *argfltregs; /* scratch float registers */
33 static int *tmpfltregs; /* scratch float registers */
34 static int *savfltregs; /* saved float registers */
35 static int *freetmpintregs; /* free scratch integer registers */
36 static int *freesavintregs; /* free saved integer registers */
37 static int *freetmpfltregs; /* free scratch float registers */
38 static int *freesavfltregs; /* free saved float registers */
40 static int *freemem; /* free scratch memory */
41 static int memuse; /* used memory count */
42 static int ifmemuse; /* interface used memory count */
43 static int maxmemuse; /* maximal used memory count (spills) */
44 static int freememtop; /* free memory count */
46 static int tmpintregcnt; /* scratch integer register count */
47 static int savintregcnt; /* saved integer register count */
48 static int tmpfltregcnt; /* scratch float register count */
49 static int savfltregcnt; /* saved float register count */
51 static int iftmpintregcnt; /* iface scratch integer register count */
52 static int ifsavintregcnt; /* iface saved integer register count */
53 static int iftmpfltregcnt; /* iface scratch float register count */
54 static int ifsavfltregcnt; /* iface saved float register count */
56 static int tmpintreguse; /* used scratch integer register count */
57 static int savintreguse; /* used saved integer register count */
58 static int tmpfltreguse; /* used scratch float register count */
59 static int savfltreguse; /* used saved float register count */
61 static int maxtmpintreguse; /* max used scratch int register count */
62 static int maxsavintreguse; /* max used saved int register count */
63 static int maxtmpfltreguse; /* max used scratch float register count */
64 static int maxsavfltreguse; /* max used saved float register count */
66 static int freetmpinttop; /* free scratch integer register count */
67 static int freesavinttop; /* free saved integer register count */
68 static int freetmpflttop; /* free scratch float register count */
69 static int freesavflttop; /* free saved float register count */
71 static int savedregs_num; /* total number of registers to be saved */
72 static int arguments_num; /* size of parameter field in the stackframe */
76 /****************** function reg_init ******************************************
78 initialises the register-allocator
80 *******************************************************************************/
82 static void reg_init()
88 if (TYPE_INT != 0 || TYPE_ADR != 4)
89 panic ("JAVA-Basictypes have been changed");
95 for (intregsnum = 0; nregdescint[intregsnum] != REG_END; intregsnum++) {
96 switch (nregdescint[intregsnum]) {
97 case REG_SAV: savintregcnt++;
99 case REG_TMP: tmpintregcnt++;
101 case REG_ARG: intreg_argnum++;
105 argintregs = MNEW (int, intreg_argnum);
106 tmpintregs = MNEW (int, tmpintregcnt);
107 savintregs = MNEW (int, savintregcnt);
108 freetmpintregs = MNEW (int, tmpintregcnt);
109 freesavintregs = MNEW (int, savintregcnt);
115 for (n = 0; n < intregsnum; n++) {
116 switch (nregdescint[n]) {
117 case REG_RET: intreg_ret = n;
119 case REG_SAV: savintregs[savintreguse++] = n;
121 case REG_TMP: tmpintregs[tmpintreguse++] = n;
123 case REG_ARG: argintregs[intreg_argnum++] = n;
133 for (floatregsnum = 0; nregdescfloat[floatregsnum] != REG_END; floatregsnum++) {
134 switch (nregdescfloat[floatregsnum]) {
135 case REG_SAV: savfltregcnt++;
137 case REG_TMP: tmpfltregcnt++;
139 case REG_ARG: fltreg_argnum++;
144 argfltregs = MNEW (int, fltreg_argnum);
145 tmpfltregs = MNEW (int, tmpfltregcnt);
146 savfltregs = MNEW (int, savfltregcnt);
147 freetmpfltregs = MNEW (int, tmpfltregcnt);
148 freesavfltregs = MNEW (int, savfltregcnt);
154 for (n = 0; n < floatregsnum; n++) {
155 switch (nregdescfloat[n]) {
156 case REG_RET: floatreg_ret = n;
158 case REG_SAV: savfltregs[savfltreguse++] = n;
160 case REG_TMP: tmpfltregs[tmpfltreguse++] = n;
162 case REG_ARG: argfltregs[fltreg_argnum++] = n;
172 /********************** function reg_close *************************************
174 releases all allocated space for registers
176 *******************************************************************************/
178 static void reg_close ()
180 if (argintregs) MFREE (argintregs, int, intreg_argnum);
181 if (argfltregs) MFREE (argfltregs, int, fltreg_argnum);
182 if (tmpintregs) MFREE (tmpintregs, int, tmpintregcnt);
183 if (savintregs) MFREE (savintregs, int, savintregcnt);
184 if (tmpfltregs) MFREE (tmpfltregs, int, tmpfltregcnt);
185 if (savfltregs) MFREE (savfltregs, int, savfltregcnt);
187 if (freetmpintregs) MFREE (freetmpintregs, int, tmpintregcnt);
188 if (freesavintregs) MFREE (freesavintregs, int, savintregcnt);
189 if (freetmpfltregs) MFREE (freetmpfltregs, int, tmpfltregcnt);
190 if (freesavfltregs) MFREE (freesavfltregs, int, savfltregcnt);
194 /****************** function local_init ****************************************
196 initialises the local variable and interfaces table
198 *******************************************************************************/
200 static void local_init()
205 freemem = DMNEW(int, maxstack);
206 locals = DMNEW(varinfo5, maxlocals);
207 interfaces = DMNEW(varinfo5, maxstack);
209 for (v = locals, i = maxlocals; i > 0; v++, i--) {
210 v[0][TYPE_INT].type = -1;
211 v[0][TYPE_LNG].type = -1;
212 v[0][TYPE_FLT].type = -1;
213 v[0][TYPE_DBL].type = -1;
214 v[0][TYPE_ADR].type = -1;
217 for (v = interfaces, i = maxstack; i > 0; v++, i--) {
218 v[0][TYPE_INT].type = -1;
219 v[0][TYPE_INT].flags = 0;
220 v[0][TYPE_LNG].type = -1;
221 v[0][TYPE_LNG].flags = 0;
222 v[0][TYPE_FLT].type = -1;
223 v[0][TYPE_FLT].flags = 0;
224 v[0][TYPE_DBL].type = -1;
225 v[0][TYPE_DBL].flags = 0;
226 v[0][TYPE_ADR].type = -1;
227 v[0][TYPE_ADR].flags = 0;
232 /************************* function interface_regalloc *****************************
234 allocates registers for all interface variables
236 *******************************************************************************/
238 static void interface_regalloc ()
241 int intalloc, fltalloc;
244 /* allocate stack space for passing arguments to called methods */
246 if (arguments_num > intreg_argnum)
247 ifmemuse = arguments_num - intreg_argnum;
251 iftmpintregcnt = tmpintregcnt;
252 ifsavintregcnt = savintregcnt;
253 iftmpfltregcnt = tmpfltregcnt;
254 ifsavfltregcnt = savfltregcnt;
256 for (s = 0; s < maxstack; s++) {
257 intalloc = -1; fltalloc = -1;
258 saved = (interfaces[s][TYPE_INT].flags | interfaces[s][TYPE_LNG].flags |
259 interfaces[s][TYPE_FLT].flags | interfaces[s][TYPE_DBL].flags |
260 interfaces[s][TYPE_ADR].flags) & SAVEDVAR;
261 for (t = TYPE_INT; t <= TYPE_ADR; t++) {
262 v = &interfaces[s][t];
265 if (IS_FLT_DBL_TYPE(t)) {
267 v->flags |= interfaces[s][fltalloc].flags & INMEMORY;
268 v->regoff = interfaces[s][fltalloc].regoff;
270 else if (iftmpfltregcnt > 0) {
272 v->regoff = tmpfltregs[iftmpfltregcnt];
274 else if (ifsavfltregcnt > 0) {
276 v->regoff = savfltregs[ifsavfltregcnt];
279 v->flags |= INMEMORY;
280 v->regoff = ifmemuse++;
286 v->flags |= interfaces[s][intalloc].flags & INMEMORY;
287 v->regoff = interfaces[s][intalloc].regoff;
289 else if (iftmpintregcnt > 0) {
291 v->regoff = tmpintregs[iftmpintregcnt];
293 else if (ifsavintregcnt > 0) {
295 v->regoff = savintregs[ifsavintregcnt];
298 v->flags |= INMEMORY;
299 v->regoff = ifmemuse++;
305 if (IS_FLT_DBL_TYPE(t)) {
307 v->flags |= interfaces[s][fltalloc].flags & INMEMORY;
308 v->regoff = interfaces[s][fltalloc].regoff;
310 else if (ifsavfltregcnt > 0) {
312 v->regoff = savfltregs[ifsavfltregcnt];
315 v->flags |= INMEMORY;
316 v->regoff = ifmemuse++;
322 v->flags |= interfaces[s][intalloc].flags & INMEMORY;
323 v->regoff = interfaces[s][intalloc].regoff;
325 else if (ifsavintregcnt > 0) {
327 v->regoff = savintregs[ifsavintregcnt];
330 v->flags |= INMEMORY;
331 v->regoff = ifmemuse++;
336 } /* if (type >= 0) */
339 maxmemuse = ifmemuse;
340 maxtmpintreguse = iftmpintregcnt;
341 maxsavintreguse = ifsavintregcnt;
342 maxtmpfltreguse = iftmpfltregcnt;
343 maxsavfltreguse = ifsavfltregcnt;
347 /************************* function local_regalloc *****************************
349 allocates registers for all local variables
351 *******************************************************************************/
353 static void local_regalloc ()
356 int intalloc, fltalloc;
360 for (s = 0; s < maxlocals; s++) {
361 intalloc = -1; fltalloc = -1;
362 for (t = TYPE_INT; t <= TYPE_ADR; t++) {
365 if (IS_FLT_DBL_TYPE(t)) {
367 v->flags = locals[s][fltalloc].flags;
368 v->regoff = locals[s][fltalloc].regoff;
370 else if (s < fltreg_argnum) {
372 v->regoff = argfltregs[s];
374 else if (maxtmpfltreguse > 0) {
377 v->regoff = tmpfltregs[maxtmpfltreguse];
379 else if (maxsavfltreguse > 0) {
382 v->regoff = savfltregs[maxsavfltreguse];
386 v->regoff = maxmemuse++;
392 v->flags = locals[s][intalloc].flags;
393 v->regoff = locals[s][intalloc].regoff;
395 else if (s < intreg_argnum) {
397 v->regoff = argintregs[s];
399 else if (maxtmpintreguse > 0) {
402 v->regoff = tmpintregs[maxtmpintreguse];
404 else if (maxsavintreguse > 0) {
407 v->regoff = savintregs[maxsavintreguse];
411 v->regoff = maxmemuse++;
420 for (s = 0; s < maxlocals; s++) {
421 intalloc = -1; fltalloc = -1;
422 for (t=TYPE_INT; t<=TYPE_ADR; t++) {
425 if (IS_FLT_DBL_TYPE(t)) {
427 v->flags = locals[s][fltalloc].flags;
428 v->regoff = locals[s][fltalloc].regoff;
430 else if (maxsavfltreguse > 0) {
433 v->regoff = savfltregs[maxsavfltreguse];
437 v->regoff = maxmemuse++;
443 v->flags = locals[s][intalloc].flags;
444 v->regoff = locals[s][intalloc].regoff;
446 else if (maxsavintreguse > 0) {
449 v->regoff = savintregs[maxsavintreguse];
453 v->regoff = maxmemuse++;
463 static void reg_init_temp()
472 tmpintreguse = iftmpintregcnt;
473 savintreguse = ifsavintregcnt;
474 tmpfltreguse = iftmpfltregcnt;
475 savfltreguse = ifsavfltregcnt;
479 #define reg_new_temp(s) if(s->varkind==TEMPVAR)reg_new_temp_func(s)
481 static void reg_new_temp_func(stackptr s)
483 if (s->flags & SAVEDVAR) {
484 if (IS_FLT_DBL_TYPE(s->type)) {
485 if (freesavflttop > 0) {
487 s->regoff = freesavfltregs[freesavflttop];
490 else if (savfltreguse > 0) {
492 if (savfltreguse < maxsavfltreguse)
493 maxsavfltreguse = savfltreguse;
494 s->regoff = savfltregs[savfltreguse];
499 if (freesavinttop > 0) {
501 s->regoff = freesavintregs[freesavinttop];
504 else if (savintreguse > 0) {
506 if (savintreguse < maxsavintreguse)
507 maxsavintreguse = savintreguse;
508 s->regoff = savintregs[savintreguse];
514 if (IS_FLT_DBL_TYPE(s->type)) {
515 if (freetmpflttop > 0) {
517 s->regoff = freetmpfltregs[freetmpflttop];
520 else if (tmpfltreguse > 0) {
522 if (tmpfltreguse < maxtmpfltreguse)
523 maxtmpfltreguse = tmpfltreguse;
524 s->regoff = tmpfltregs[tmpfltreguse];
529 if (freetmpinttop > 0) {
531 s->regoff = freetmpintregs[freetmpinttop];
534 else if (tmpintreguse > 0) {
536 if (tmpintreguse < maxtmpintreguse)
537 maxtmpintreguse = tmpintreguse;
538 s->regoff = tmpintregs[tmpintreguse];
543 if (freememtop > 0) {
545 s->regoff = freemem[freememtop];
548 s->regoff = memuse++;
549 if (memuse > maxmemuse)
552 s->flags |= INMEMORY;
556 #define reg_free_temp(s) if(s->varkind==TEMPVAR)reg_free_temp_func(s)
558 static void reg_free_temp_func(stackptr s)
560 if (s->flags & INMEMORY)
561 freemem[freememtop++] = s->regoff;
562 else if (IS_FLT_DBL_TYPE(s->type)) {
563 if (s->flags & SAVEDVAR)
564 freesavfltregs[freesavflttop++] = s->regoff;
566 freetmpfltregs[freetmpflttop++] = s->regoff;
569 if (s->flags & SAVEDVAR)
570 freesavintregs[freesavinttop++] = s->regoff;
572 freetmpintregs[freetmpinttop++] = s->regoff;
576 static void allocate_scratch_registers()
581 instruction *iptr = instr;
584 b_count = block_count;
586 while (--b_count >= 0) {
587 if (bptr->flags >= BBREACHED) {
591 len = bptr[1].ipc - i;
602 case ICMD_CHECKASIZE:
610 /* pop 0 push 1 const */
618 /* pop 0 push 1 load */
640 reg_free_temp(src->prev);
656 reg_free_temp(src->prev);
657 reg_free_temp(src->prev->prev);
660 /* pop 1 push 0 store */
682 /* pop 1 push 0 branch */
701 /* pop 1 push 0 table branch */
703 case ICMD_TABLESWITCH:
704 case ICMD_LOOKUPSWITCH:
706 case ICMD_NULLCHECKPOP:
707 case ICMD_MONITORENTER:
708 case ICMD_MONITOREXIT:
712 /* pop 2 push 0 branch */
737 reg_free_temp(src->prev);
740 /* pop 0 push 1 dup */
746 /* pop 0 push 2 dup */
749 reg_new_temp(dst->prev);
753 /* pop 2 push 3 dup */
756 reg_new_temp(dst->prev->prev);
757 reg_new_temp(dst->prev);
760 reg_free_temp(src->prev);
763 /* pop 3 push 4 dup */
766 reg_new_temp(dst->prev->prev->prev);
767 reg_new_temp(dst->prev->prev);
768 reg_new_temp(dst->prev);
771 reg_free_temp(src->prev);
772 reg_free_temp(src->prev->prev);
775 /* pop 3 push 5 dup */
778 reg_new_temp(dst->prev->prev->prev->prev);
779 reg_new_temp(dst->prev->prev->prev);
780 reg_new_temp(dst->prev->prev);
781 reg_new_temp(dst->prev);
784 reg_free_temp(src->prev);
785 reg_free_temp(src->prev->prev);
788 /* pop 4 push 6 dup */
791 reg_new_temp(dst->prev->prev->prev->prev->prev);
792 reg_new_temp(dst->prev->prev->prev->prev);
793 reg_new_temp(dst->prev->prev->prev);
794 reg_new_temp(dst->prev->prev);
795 reg_new_temp(dst->prev);
798 reg_free_temp(src->prev);
799 reg_free_temp(src->prev->prev);
800 reg_free_temp(src->prev->prev->prev);
803 /* pop 2 push 2 swap */
806 reg_new_temp(dst->prev);
809 reg_free_temp(src->prev);
859 reg_free_temp(src->prev);
873 case ICMD_IUSHRCONST:
883 case ICMD_LUSHRCONST:
908 case ICMD_ARRAYLENGTH:
909 case ICMD_INSTANCEOF:
928 /* pop many push any */
930 case ICMD_INVOKEVIRTUAL:
931 case ICMD_INVOKESPECIAL:
932 case ICMD_INVOKESTATIC:
933 case ICMD_INVOKEINTERFACE:
940 if (((methodinfo*)iptr->val.a)->returntype != TYPE_VOID)
954 if (iptr->op1 != TYPE_VOID)
958 case ICMD_MULTIANEWARRAY:
968 printf("ICMD %d at %d\n", iptr->opc, (int)(iptr-instr));
969 panic("Missing ICMD code during register allocation");
972 } /* while instructions */