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: Reinhard Grafl EMAIL: cacao@complang.tuwien.ac.at
10 Andreas Krall EMAIL: cacao@complang.tuwien.ac.at
12 Last Change: 1997/10/23
14 *******************************************************************************/
16 /*********************** Structure of a register info *************************/
18 #define REG_TYPE_FLT 1 /* integer or floating point type */
19 #define REG_SIZE_DBL 2 /* int/single or long/double */
20 #define REG_INMEMORY 4 /* true if register is in memory */
21 #define REG_ISFREE 8 /* true if register is currently free */
22 #define REG_ISUNUSED 16 /* true if register never has been used */
23 #define REG_ISFREEUNUSED 24
25 #define IS_INT_LNG_REG(a) (!((a)®_TYPE_FLT))
26 #define IS_FLT_DBL_REG(a) ((a)®_TYPE_FLT)
33 #define REGTYPE(a) ((a) & 3)
35 typedef struct reginfo {
36 int typeflags; /* register type, size and flags */
37 int num; /* register number or stack offset */
38 list *waitlist; /* free list for register allocation */
44 static reginfo *intregs = NULL; /* table for the integer registers */
45 static reginfo *floatregs = NULL; /* table for the float registers */
46 static int intregsnum; /* absolute number of integer registers */
47 static int floatregsnum; /* absolute number of float registers */
49 static int intreg_ret; /* register to return integer values */
50 static int intreg_exc; /* register to return exception value */
51 static int intreg_arg1; /* register for first integer argument */
52 static int intreg_argnum; /* number of integer argument registers */
54 static int floatreg_ret; /* register for return float values */
55 static int floatreg_arg1; /* register for first float argument */
56 static int floatreg_argnum; /* number of float argument registers */
59 static list savedintslist; /* free saved int registers during allocation */
60 static list savedfloatslist; /* free saved float registers during allocation*/
61 static list scratchintslist; /* free temp int registers during allocation */
62 static list scratchfloatslist; /* free temp float registers during allocation */
63 static int *freeintregs; /* free int registers table */
64 static int *freefloatregs; /* free float registers table */
66 static int savedregs_num; /* total number of registers to be saved */
67 static int localvars_num; /* total number of variables to spilled */
68 static int arguments_num; /* size of parameter field in the stackframe */
72 /****************** function reg_init ******************************************
74 initialises the register-allocator
76 *******************************************************************************/
78 static void reg_init()
83 for (intregsnum=0; regdescint[intregsnum] != REG_END; intregsnum++);
84 intregs = MNEW (reginfo, intregsnum);
85 freeintregs = MNEW (int, intregsnum + 2);
87 freeintregs[intregsnum] = 0;
90 for (n=0; n<intregsnum; n++) {
91 intregs[n].typeflags = 0;
93 intregs[n].waitlist = NULL;
96 switch (regdescint[n]) {
98 case REG_RET: intreg_ret = n;
100 case REG_EXC: intreg_exc = n;
102 case REG_SAV: intregs[n].waitlist = &(savedintslist);
105 case REG_TMP: intregs[n].waitlist = &(scratchintslist);
108 case REG_ARG: if (intreg_arg1 < 0) intreg_arg1 = n;
115 for (floatregsnum=0; regdescfloat[floatregsnum] != REG_END; floatregsnum++);
116 floatregs = MNEW (reginfo, floatregsnum);
117 freefloatregs = MNEW (int, floatregsnum + 2);
118 *freefloatregs++ = 0;
119 freefloatregs[floatregsnum] = 0;
122 for (n=0; n<floatregsnum; n++) {
123 floatregs[n].typeflags = REG_TYPE_FLT;
124 floatregs[n].num = n;
125 floatregs[n].waitlist = NULL;
126 freefloatregs[n] = 0;
128 switch (regdescfloat[n]) {
130 case REG_RET: floatreg_ret = n;
132 case REG_EXC: panic ("can not use floating-reg as exception");
134 case REG_SAV: floatregs[n].waitlist = &(savedfloatslist);
135 freefloatregs[n] = 1;
137 case REG_TMP: floatregs[n].waitlist = &(scratchfloatslist);
138 freefloatregs[n] = 1;
140 case REG_ARG: if (floatreg_arg1 < 0) floatreg_arg1 = n;
149 list_init (&savedintslist, OFFSET(reginfo, linkage));
150 list_init (&savedfloatslist, OFFSET(reginfo, linkage));
151 list_init (&scratchintslist, OFFSET(reginfo, linkage));
152 list_init (&scratchfloatslist, OFFSET(reginfo, linkage));
154 for (n=0; n<intregsnum; n++) {
155 intregs[n].typeflags |= REG_ISFREE | REG_ISUNUSED;
156 if (intregs[n].waitlist)
157 list_addlast(intregs[n].waitlist, intregs+n);
159 for (n=0; n<floatregsnum; n++) {
160 floatregs[n].typeflags |= REG_ISFREE | REG_ISUNUSED;
161 if (floatregs[n].waitlist)
162 list_addlast(floatregs[n].waitlist, floatregs+n);
171 /********************** function reg_close *************************************
173 releases all allocated space for registers
175 *******************************************************************************/
177 static void reg_close ()
179 if (intregs) MFREE (intregs, reginfo, intregsnum);
180 if (floatregs) MFREE (floatregs, reginfo, floatregsnum);
184 /********************* function reg_free ***************************************
186 put back a register which has been allocated by reg_allocate into the
187 corresponding free list
189 *******************************************************************************/
191 static void reg_free (reginfo *ri)
193 ri -> typeflags |= REG_ISFREE;
196 if (ri->typeflags & REG_INMEMORY)
197 list_addlast (ri->waitlist, ri);
202 if (ri->typeflags & REG_TYPE_FLT) {
203 if (ri->typeflags & REG_SIZE_DBL) {
204 freefloatregs[ri->num] = 0;
205 freefloatregs[ri->num + 1] = 0;
206 ri1 = &floatregs[ri->num + 1];
207 list_addfirst (ri1->waitlist, ri1);
210 freefloatregs[ri->num] = 0;
213 if (ri->typeflags & REG_SIZE_DBL) {
214 freeintregs[ri->num] = 0;
215 freeintregs[ri->num + 1] = 0;
216 ri1 = &intregs[ri->num + 1];
217 list_addfirst (ri1->waitlist, ri1);
220 freeintregs[ri->num] = 0;
223 list_addfirst (ri->waitlist, ri);
229 /******************* internal function reg_suckregister ************************
231 searches for the first register of a list which fullfills the requirements:
232 if argument isunused is true ri->typeflags®_ISUNUSED has to be true too
233 if register pairs are required two adjacent register are searched
234 if a register can be found it is removed from the free list and the
235 fields 'isunused' and 'isfree' are set to false
237 *******************************************************************************/
239 static reginfo *reg_remove (list *l, int num) {
243 while (ri->num != num)
244 ri = list_next (l, ri);
245 if (ri->typeflags & REG_TYPE_FLT)
246 freefloatregs[num] = 0;
248 freeintregs[num] = 0;
250 ri -> typeflags &= ~REG_ISFREEUNUSED;
255 static reginfo *reg_suckregister (list *l, bool isunused)
262 if ( (!isunused) || (ri->typeflags & REG_ISUNUSED)) {
264 reginfo *retreg = NULL;
266 if (ri->typeflags & REG_SIZE_DBL) {
267 if (ri->typeflags & REG_TYPE_FLT)
269 if(freefloatregs[ri->num - 1]) {
270 freefloatregs[ri->num] = 0;
271 retreg = reg_remove(l, ri->num - 1);
275 if (freefloatregs[ri->num + 1]) {
276 freefloatregs[ri->num] = 0;
278 (void) reg_remove(l, ri->num + 1);
281 else if (freeintregs[ri->num + 1]) {
282 freeintregs[ri->num] = 0;
284 (void) reg_remove(l, ri->num + 1);
286 else if(freeintregs[ri->num - 1]) {
287 freeintregs[ri->num] = 0;
288 retreg = reg_remove(l, ri->num - 1);
292 ri -> typeflags &= ~REG_ISFREEUNUSED;
297 if (ri->typeflags & REG_TYPE_FLT)
298 freefloatregs[ri->num] = 0;
300 freeintregs[ri->num] = 0;
302 ri -> typeflags &= ~REG_ISFREEUNUSED;
307 ri -> typeflags &= ~REG_ISFREEUNUSED;
311 ri = list_next (l, ri);
317 /******************** Funktion: reg_allocate **********************************
319 versucht, ein Register zu belegen, das vom richtigen Typ ist, und
320 allen gew"unschten Anforderungen entspricht.
323 type .... JAVA-Grundtyp (INT,LONG,DOUBLE,FLOAT,ADDRESS)
324 saved ... Das Register soll bei Methodenaufrufen nicht zerst"ort werden
325 new ..... Das Register soll noch nie vorher verwendet worden sein
327 Wenn es (aus verschiedenen Gr"unden) kein geeignetes freies Register f"ur
328 den Zweck mehr gibt, dann erzeugt diese Funktion einen Verweis auf
329 einen Platz am aktuellen Stackframe (diese Stackframe-Eintr"age erf"ullen
330 auf jeden Fall alle obigen Forderungen)
332 *******************************************************************************/
334 static reginfo *reg_allocate (u2 type, bool saved, bool new)
350 t = REG_TYPE_FLT | REG_SIZE_DBL;
357 if (IS_INT_LNG_REG(t))
358 ri = reg_suckregister (&scratchintslist, new);
360 ri = reg_suckregister (&scratchfloatslist, new);
364 if (IS_INT_LNG_REG(t))
365 ri = reg_suckregister (&savedintslist, new);
367 ri = reg_suckregister (&savedfloatslist, new);
371 ri -> typeflags = t | REG_INMEMORY;
373 ri -> num = localvars_num;
374 if (t & REG_SIZE_DBL)
379 ri -> num = (localvars_num++);
381 ri -> waitlist = (IS_INT_LNG_REG(t)) ? &savedintslist : &savedfloatslist;
386 /********************* Funktion: reg_reallocate *******************************
388 versucht, ein schon einmal angefordertes (aber in der Zwischenzeit
389 wieder freigegebenens) Register neuerlich anzufordern.
390 Wenn das Register immer noch unbenutzt ist, dann ist alles OK
391 (R"uckgabewert true), sonst wird 'false' zur"uckgeben, und aus der
392 neuerlichen Belegung wird nichts.
394 ******************************************************************************/
396 static bool reg_reallocate (reginfo *ri)
398 if (!(ri->typeflags & REG_ISFREE)) return false;
400 ri->typeflags &= ~REG_ISFREEUNUSED;
402 if (ri->waitlist) list_remove (ri->waitlist, ri);
409 /****************** Funktion: reg_parlistresult *******************************
411 Erzeugt eine Registerreferenz auf das Register, das vom System zur
412 R"uckgabe von Werten aus Methoden verwendet wird.
414 type ... Der JAVA-Grundtyp des R"uckgabewertes
416 ******************************************************************************/
418 static reginfo *reg_parlistresult (u2 type)
420 if (type==TYPE_FLOAT || type==TYPE_DOUBLE) return &(floatregs[floatreg_ret]);
421 else return &(intregs[intreg_ret]);
426 /*************** Funktion: reg_parlistexception ******************************
428 Erzeugt eine Registerreferenz auf das Register, in dem das System die
429 Zeiger auf allf"allige Exception-Objekte bei Methodenaufrufen
432 ******************************************************************************/
434 static reginfo *reg_parlistexception ()
436 return &(intregs[intreg_exc]);
441 /************************ Funktion: reg_parlistpar ****************************
443 Erzeugt eine Registerreferenz auf ein Register, in dem das n"achste
444 Argument (in der Z"ahlung ab dem Zeitpunkt von Aufruf von 'reg_parlistinit')
445 bei Methodenaufrufen eingetragen wird.
446 Wenn es in Summe mehr als die m"oglichen Parameter-Register werden, dann
447 wird auch noch Platz am Stack f"ur die "uberz"ahligen Werte reserviert
449 ******************************************************************************/
451 static int usedintpar, usedfloatpar;
452 static int usedparoverflow;
454 static reginfo *reg_parlistpar (u2 type)
458 if (type == TYPE_FLOAT || type == TYPE_DOUBLE) {
460 if (reg_parammode == PARAMMODE_NUMBERED) usedintpar++;
462 if (usedfloatpar <= floatreg_argnum) {
463 f = &floatregs[floatreg_arg1 + (usedfloatpar - 1) ];
464 f->typeflags &= ~REG_ISUNUSED;
471 if (reg_parammode == PARAMMODE_NUMBERED) usedfloatpar++;
473 if (usedintpar <= intreg_argnum) {
474 f = &intregs[intreg_arg1 + (usedintpar - 1) ];
475 f->typeflags &= ~REG_ISUNUSED;
485 if (usedparoverflow > arguments_num) arguments_num = usedparoverflow;
490 /****************** Funktion: reg_parlistinit *********************************
492 initialisiert die Z"ahlung der Parameter-Register
494 *******************************************************************************/
496 static void reg_parlistinit()
507 /***************** Funktion: reg_display *************************************
509 gibt eine Register-Referenz in lesbarer Form auf 'stdout' aus.
511 ******************************************************************************/
513 static void reg_display (reginfo *ri)
515 if (ri->typeflags & REG_INMEMORY) {
516 printf ("[%d]", (int) (ri->num) );
520 (IS_INT_LNG_REG(ri->typeflags)) ? "$" : "f$",