Precoloring of stackslot holding the return value to the return register(s) implemented.
[cacao.git] / src / vm / jit / stack.h
1 /* vm/jit/stack.h - stack analysis header
2
3    Copyright (C) 1996-2005 R. Grafl, A. Krall, C. Kruegel, C. Oates,
4    R. Obermaisser, M. Platter, M. Probst, S. Ring, E. Steiner,
5    C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich, J. Wenninger,
6    Institut f. Computersprachen - TU Wien
7
8    This file is part of CACAO.
9
10    This program is free software; you can redistribute it and/or
11    modify it under the terms of the GNU General Public License as
12    published by the Free Software Foundation; either version 2, or (at
13    your option) any later version.
14
15    This program is distributed in the hope that it will be useful, but
16    WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18    General Public License for more details.
19
20    You should have received a copy of the GNU General Public License
21    along with this program; if not, write to the Free Software
22    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
23    02111-1307, USA.
24
25    Contact: cacao@complang.tuwien.ac.at
26
27    Authors: Christian Thalinger
28
29    $Id: stack.h 2870 2005-06-29 12:39:31Z christian $
30
31 */
32
33
34 #ifndef _STACK_H
35 #define _STACK_H
36
37 #include "vm/global.h"
38 #include "vm/exceptions.h"
39 #include "vm/jit/reg.h"
40
41
42 /**********************************************************************/
43 /* Macros used internally by analyse_stack                            */
44 /**********************************************************************/
45
46 #ifdef STATISTICS
47 #define COUNT(cnt) cnt++
48 #else
49 #define COUNT(cnt)
50 #endif
51  
52 /* convenient abbreviations */
53 #define CURKIND    curstack->varkind
54 #define CURTYPE    curstack->type
55
56 /*--------------------------------------------------*/
57 /* SIGNALING ERRORS                                 */
58 /*--------------------------------------------------*/
59
60 #define TYPE_VERIFYERROR(t) \
61     do { \
62         char *type; \
63         switch ((t)) { \
64         case TYPE_INT: \
65                         type = "integer"; \
66                         break; \
67                 case TYPE_LNG: \
68                         type = "long"; \
69                         break; \
70                 case TYPE_FLT: \
71                         type = "float"; \
72                         break; \
73                 case TYPE_DBL: \
74                         type = "double"; \
75                         break; \
76                 case TYPE_ADR: \
77                         type = "object/array"; \
78                         break; \
79                 } \
80         *exceptionptr = new_verifyerror(m, \
81                                                                                 "Expecting to find %s on stack", \
82                                                                                 type); \
83         return NULL; \
84     } while (0)
85
86
87 /*--------------------------------------------------*/
88 /* STACK UNDERFLOW/OVERFLOW CHECKS                  */
89 /*--------------------------------------------------*/
90
91 /* underflow checks */
92
93 #define REQUIRE(num) \
94     do { \
95         if (stackdepth < (num)) { \
96             *exceptionptr = \
97                 new_verifyerror(m, "Unable to pop operand off an empty stack"); \
98             return NULL; \
99         } \
100     } while(0)
101
102 #define REQUIRE_1     REQUIRE(1)
103 #define REQUIRE_2     REQUIRE(2)
104 #define REQUIRE_3     REQUIRE(3)
105 #define REQUIRE_4     REQUIRE(4)
106
107
108 /* overflow check */
109 /* We allow ACONST instructions inserted as arguments to builtin
110  * functions to exceed the maximum stack depth.  Maybe we should check
111  * against maximum stack depth only at block boundaries?
112  */
113
114 #define CHECKOVERFLOW \
115         do { \
116                 if (stackdepth > m->maxstack) { \
117                         if (iptr[0].opc != ICMD_ACONST || iptr[0].op1 == 0) { \
118                 *exceptionptr = new_verifyerror(m, "Stack size too large"); \
119                 return NULL; \
120             } \
121                 } \
122         } while(0)
123
124
125 /*--------------------------------------------------*/
126 /* ALLOCATING STACK SLOTS                           */
127 /*--------------------------------------------------*/
128
129 #define NEWSTACK_(s,v,n) {new->prev=curstack;new->type=s;new->flags=0;  \
130                                   new->varkind=v;new->varnum=n;curstack=new;new++;}
131                                                 /* Initialize regoff, so -sia can show regnames even before reg.inc */ 
132                         /* regs[rd->intregargnum has to be set for this */ 
133                                                 /* new->regoff = (IS_FLT_DBL_TYPE(s))?-1:rd->intreg_argnum; }*/
134 #ifdef LSRA
135     #define NEWSTACK(s,v,n) {NEWSTACK_(s,v,n); m->maxlifetimes++;}
136 #else
137     #define NEWSTACK(s,v,n) NEWSTACK_(s,v,n)
138 #endif
139
140 #define NEWSTACKn(s,n)  NEWSTACK(s,UNDEFVAR,n)
141 #define NEWSTACK0(s)    NEWSTACK(s,UNDEFVAR,0)
142
143 /* allocate the input stack for an exception handler */
144 #define NEWXSTACK   {NEWSTACK(TYPE_ADR,STACKVAR,0);curstack=0;}
145
146
147 /*--------------------------------------------------*/
148 /* STACK MANIPULATION                               */
149 /*--------------------------------------------------*/
150
151 /* resetting to an empty operand stack */
152
153 #define STACKRESET \
154     do { \
155         curstack = 0; \
156         stackdepth = 0; \
157     } while (0)
158
159
160 /* set the output stack of the current instruction */
161
162 #define SETDST    iptr->dst = curstack;
163
164
165 /* The following macros do NOT check stackdepth, set stackdepth or iptr->dst */
166
167 #define POP(s) \
168     do { \
169         if ((s) != curstack->type) { \
170             TYPE_VERIFYERROR((s)); \
171         } \
172         if (curstack->varkind == UNDEFVAR) \
173             curstack->varkind = TEMPVAR; \
174         curstack = curstack->prev; \
175     } while (0)
176
177 #define POPANY \
178     do { \
179         if (curstack->varkind == UNDEFVAR) \
180             curstack->varkind = TEMPVAR; \
181         curstack = curstack->prev; \
182     } while (0)
183
184 #define COPY(s,d) \
185     do { \
186         (d)->flags = 0; \
187         (d)->type = (s)->type; \
188         (d)->varkind = (s)->varkind; \
189         (d)->varnum = (s)->varnum; \
190     } while (0)
191
192
193 /*--------------------------------------------------*/
194 /* STACK OPERATIONS MODELING                        */
195 /*--------------------------------------------------*/
196
197 /* The following macros are used to model the stack manipulations of
198  * different kinds of instructions.
199  *
200  * These macros check the input stackdepth and they set the output
201  * stackdepth and the output stack of the instruction (iptr->dst).
202  *
203  * These macros do *not* check for stack overflows!
204  */
205    
206 #define PUSHCONST(s){NEWSTACKn(s,stackdepth);SETDST;stackdepth++;}
207 #define LOAD(s,v,n) {NEWSTACK(s,v,n);SETDST;stackdepth++;}
208 #define STORE(s)    {REQUIRE_1;POP(s);SETDST;stackdepth--;}
209 #define OP1_0(s)    {REQUIRE_1;POP(s);SETDST;stackdepth--;}
210 #define OP1_0ANY    {REQUIRE_1;POPANY;SETDST;stackdepth--;}
211
212 #define OP0_1(s) \
213     do { \
214         NEWSTACKn((s),stackdepth); \
215         SETDST; \
216         stackdepth++; \
217     } while (0)
218
219 #define OP1_1(s,d) \
220     do { \
221         REQUIRE_1; \
222         POP((s)); \
223         NEWSTACKn((d),stackdepth - 1);\
224         SETDST; \
225     } while (0)
226
227 #define OP2_0(s)    {REQUIRE_2;POP(s);POP(s);SETDST;stackdepth-=2;}
228 #define OPTT2_0(t,b){REQUIRE_2;POP(t);POP(b);SETDST;stackdepth-=2;}
229 #define OP2_1(s)    {REQUIRE_2;POP(s);POP(s);NEWSTACKn(s,stackdepth-2);SETDST;stackdepth--;}
230 #define OP2IAT_1(s) {REQUIRE_2;POP(TYPE_INT);POP(TYPE_ADR);NEWSTACKn(s,stackdepth-2);\
231                      SETDST;stackdepth--;}
232 #define OP2IT_1(s)  {REQUIRE_2;POP(TYPE_INT);POP(s);NEWSTACKn(s,stackdepth-2);\
233                      SETDST;stackdepth--;}
234 #define OPTT2_1(s,d){REQUIRE_2;POP(s);POP(s);NEWSTACKn(d,stackdepth-2);SETDST;stackdepth--;}
235 #define OP2_2(s)    {REQUIRE_2;POP(s);POP(s);NEWSTACKn(s,stackdepth-2);\
236                      NEWSTACKn(s,stackdepth-1);SETDST;}
237 #define OP3TIA_0(s) {REQUIRE_3;POP(s);POP(TYPE_INT);POP(TYPE_ADR);SETDST;stackdepth-=3;}
238 #define OP3_0(s)    {REQUIRE_3;POP(s);POP(s);POP(s);SETDST;stackdepth-=3;}
239
240 #define POPMANY(i) \
241     do { \
242         REQUIRE((i)); \
243         stackdepth -= (i); \
244         while(--(i) >= 0) { \
245             POPANY; \
246         } \
247         SETDST; \
248     } while (0)
249
250 #define DUP         {REQUIRE_1;NEWSTACK(CURTYPE,CURKIND,curstack->varnum);SETDST; \
251                     stackdepth++;}
252 #define SWAP        {REQUIRE_2;COPY(curstack,new);POPANY;COPY(curstack,new+1);POPANY;\
253                     new[0].prev=curstack;new[1].prev=new;\
254                     curstack=new+1;new+=2;SETDST;}
255 #define DUP_X1      {REQUIRE_2;COPY(curstack,new);COPY(curstack,new+2);POPANY;\
256                     COPY(curstack,new+1);POPANY;new[0].prev=curstack;\
257                     new[1].prev=new;new[2].prev=new+1;\
258                     curstack=new+2;new+=3;SETDST;stackdepth++;}
259 #define DUP2_X1     {REQUIRE_3;COPY(curstack,new+1);COPY(curstack,new+4);POPANY;\
260                     COPY(curstack,new);COPY(curstack,new+3);POPANY;\
261                     COPY(curstack,new+2);POPANY;new[0].prev=curstack;\
262                     new[1].prev=new;new[2].prev=new+1;\
263                     new[3].prev=new+2;new[4].prev=new+3;\
264                     curstack=new+4;new+=5;SETDST;stackdepth+=2;}
265 #define DUP_X2      {REQUIRE_3;COPY(curstack,new);COPY(curstack,new+3);POPANY;\
266                     COPY(curstack,new+2);POPANY;COPY(curstack,new+1);POPANY;\
267                     new[0].prev=curstack;new[1].prev=new;\
268                     new[2].prev=new+1;new[3].prev=new+2;\
269                     curstack=new+3;new+=4;SETDST;stackdepth++;}
270 #define DUP2_X2     {REQUIRE_4;COPY(curstack,new+1);COPY(curstack,new+5);POPANY;\
271                     COPY(curstack,new);COPY(curstack,new+4);POPANY;\
272                     COPY(curstack,new+3);POPANY;COPY(curstack,new+2);POPANY;\
273                     new[0].prev=curstack;new[1].prev=new;\
274                     new[2].prev=new+1;new[3].prev=new+2;\
275                     new[4].prev=new+3;new[5].prev=new+4;\
276                     curstack=new+5;new+=6;SETDST;stackdepth+=2;}
277
278
279 /*--------------------------------------------------*/
280 /* MACROS FOR HANDLING BASIC BLOCKS                 */
281 /*--------------------------------------------------*/
282
283 /* COPYCURSTACK makes a copy of the current operand stack (curstack)
284  * and returns it in the variable copy.
285  *
286  * This macro is used to propagate the operand stack from one basic
287  * block to another. The destination block receives the copy as its
288  * input stack.
289  */
290 #define COPYCURSTACK(copy) {\
291         int d;\
292         stackptr s;\
293         if(curstack){\
294                 s=curstack;\
295                 new+=stackdepth;\
296                 d=stackdepth;\
297                 copy=new;\
298                 while(s){\
299                         copy--;d--;\
300                         copy->prev=copy-1;\
301                         copy->type=s->type;\
302                         copy->flags=0;\
303                         copy->varkind=STACKVAR;\
304                         copy->varnum=d;\
305                         s=s->prev;\
306                         }\
307                 copy->prev=NULL;\
308                 copy=new-1;\
309                 }\
310         else\
311                 copy=NULL;\
312 }
313
314 /* BBEND is called at the end of each basic block (after the last
315  * instruction of the block has been processed).
316  */
317
318 #define BBEND(s,i) { \
319         (i) = stackdepth - 1; \
320         copy = (s); \
321         while (copy) { \
322                 if ((copy->varkind == STACKVAR) && (copy->varnum > (i))) \
323                         copy->varkind = TEMPVAR; \
324                 else { \
325                         copy->varkind = STACKVAR; \
326                         copy->varnum = (i);\
327                 } \
328                 rd->interfaces[(i)][copy->type].type = copy->type; \
329                 rd->interfaces[(i)][copy->type].flags |= copy->flags; \
330                 (i)--; copy = copy->prev; \
331         } \
332         (i) = bptr->indepth - 1; \
333         copy = bptr->instack; \
334         while (copy) { \
335                 rd->interfaces[(i)][copy->type].type = copy->type; \
336                 if (copy->varkind == STACKVAR) { \
337                         if (copy->flags & SAVEDVAR) \
338                                 rd->interfaces[(i)][copy->type].flags |= SAVEDVAR; \
339                 } \
340                 (i)--; copy = copy->prev; \
341         } \
342 }
343
344
345 /* MARKREACHED marks the destination block <b> as reached. If this
346  * block has been reached before we check if stack depth and types
347  * match. Otherwise the destination block receives a copy of the
348  * current stack as its input stack.
349  *
350  * b...destination block
351  * c...current stack
352  */
353
354 #define MARKREACHED(b,c) \
355     do { \
356             if ((b)->flags < 0) { \
357                     COPYCURSTACK((c)); \
358             (b)->flags = 0; \
359             (b)->instack = (c); \
360             (b)->indepth = stackdepth; \
361         } else { \
362             stackptr s = curstack; \
363             stackptr t = (b)->instack; \
364                     if ((b)->indepth != stackdepth) { \
365                             show_icmd_method(m, cd, rd); \
366                 log_text("Stack depth mismatch"); \
367                 assert(0); \
368             } \
369                     while (s) { \
370                 if (s->type != t->type) \
371                                     TYPE_VERIFYERROR(t->type); \
372                             s = s->prev; \
373                 t = t->prev; \
374                         } \
375                 } \
376     } while (0)
377
378
379 /* function prototypes ********************************************************/
380
381 methodinfo *analyse_stack(methodinfo *m, codegendata *cd, registerdata *rd);
382
383 void icmd_print_stack(codegendata *cd, stackptr s);
384 void show_icmd_method(methodinfo *m, codegendata *cd, registerdata *rd);
385 void show_icmd_block(methodinfo *m, codegendata *cd, basicblock *bptr);
386 void show_icmd(instruction *iptr, bool deadcode);
387
388 /* machine dependent return value handling function */
389 void md_return_alloc(methodinfo *m, registerdata *rd, s4 return_type,
390                                          stackptr stackslot);
391
392 #endif /* _STACK_H */
393
394
395 /*
396  * These are local overrides for various environment variables in Emacs.
397  * Please do not remove this and leave it at the end of the file, where
398  * Emacs will automagically detect them.
399  * ---------------------------------------------------------------------
400  * Local variables:
401  * mode: c
402  * indent-tabs-mode: t
403  * c-basic-offset: 4
404  * tab-width: 4
405  * End:
406  */