* show_icmd_method: use a monitor since the binutils disassembler is not
[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 3007 2005-07-12 20:58:01Z twisti $
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) \
130     do { \
131         new->prev = curstack; \
132         new->type = (s); \
133         new->flags = 0; \
134         new->varkind = (v); \
135         new->varnum = (n); \
136         curstack = new; \
137         new++; \
138     } while (0)
139
140
141 /* Initialize regoff, so -sia can show regnames even before reg.inc */ 
142 /* regs[rd->intregargnum has to be set for this */ 
143 /* new->regoff = (IS_FLT_DBL_TYPE(s))?-1:rd->intreg_argnum; }*/
144
145 #ifdef LSRA
146 # define NEWSTACK(s,v,n) {NEWSTACK_(s,v,n); m->maxlifetimes++;}
147 #else
148 # define NEWSTACK(s,v,n) NEWSTACK_(s,v,n)
149 #endif
150
151 #define NEWSTACKn(s,n)  NEWSTACK(s,UNDEFVAR,n)
152 #define NEWSTACK0(s)    NEWSTACK(s,UNDEFVAR,0)
153
154 /* allocate the input stack for an exception handler */
155 #define NEWXSTACK   {NEWSTACK(TYPE_ADR,STACKVAR,0);curstack=0;}
156
157
158 /*--------------------------------------------------*/
159 /* STACK MANIPULATION                               */
160 /*--------------------------------------------------*/
161
162 /* resetting to an empty operand stack */
163
164 #define STACKRESET \
165     do { \
166         curstack = 0; \
167         stackdepth = 0; \
168     } while (0)
169
170
171 /* set the output stack of the current instruction */
172
173 #define SETDST    iptr->dst = curstack;
174
175
176 /* The following macros do NOT check stackdepth, set stackdepth or iptr->dst */
177
178 #define POP(s) \
179     do { \
180         if ((s) != curstack->type) { \
181             TYPE_VERIFYERROR((s)); \
182         } \
183         if (curstack->varkind == UNDEFVAR) \
184             curstack->varkind = TEMPVAR; \
185         curstack = curstack->prev; \
186     } while (0)
187
188 #define POPANY \
189     do { \
190         if (curstack->varkind == UNDEFVAR) \
191             curstack->varkind = TEMPVAR; \
192         curstack = curstack->prev; \
193     } while (0)
194
195 #define COPY(s,d) \
196     do { \
197         (d)->flags = 0; \
198         (d)->type = (s)->type; \
199         (d)->varkind = (s)->varkind; \
200         (d)->varnum = (s)->varnum; \
201     } while (0)
202
203
204 /*--------------------------------------------------*/
205 /* STACK OPERATIONS MODELING                        */
206 /*--------------------------------------------------*/
207
208 /* The following macros are used to model the stack manipulations of
209  * different kinds of instructions.
210  *
211  * These macros check the input stackdepth and they set the output
212  * stackdepth and the output stack of the instruction (iptr->dst).
213  *
214  * These macros do *not* check for stack overflows!
215  */
216    
217 #define PUSHCONST(s){NEWSTACKn(s,stackdepth);SETDST;stackdepth++;}
218 #define LOAD(s,v,n) {NEWSTACK(s,v,n);SETDST;stackdepth++;}
219 #define STORE(s)    {REQUIRE_1;POP(s);SETDST;stackdepth--;}
220 #define OP1_0(s)    {REQUIRE_1;POP(s);SETDST;stackdepth--;}
221 #define OP1_0ANY    {REQUIRE_1;POPANY;SETDST;stackdepth--;}
222
223 #define OP0_1(s) \
224     do { \
225         NEWSTACKn((s),stackdepth); \
226         SETDST; \
227         stackdepth++; \
228     } while (0)
229
230 #define OP1_1(s,d) \
231     do { \
232         REQUIRE_1; \
233         POP((s)); \
234         NEWSTACKn((d),stackdepth - 1);\
235         SETDST; \
236     } while (0)
237
238 #define OP2_0(s)    {REQUIRE_2;POP(s);POP(s);SETDST;stackdepth-=2;}
239 #define OPTT2_0(t,b){REQUIRE_2;POP(t);POP(b);SETDST;stackdepth-=2;}
240 #define OP2_1(s)    {REQUIRE_2;POP(s);POP(s);NEWSTACKn(s,stackdepth-2);SETDST;stackdepth--;}
241 #define OP2IAT_1(s) {REQUIRE_2;POP(TYPE_INT);POP(TYPE_ADR);NEWSTACKn(s,stackdepth-2);\
242                      SETDST;stackdepth--;}
243 #define OP2IT_1(s)  {REQUIRE_2;POP(TYPE_INT);POP(s);NEWSTACKn(s,stackdepth-2);\
244                      SETDST;stackdepth--;}
245 #define OPTT2_1(s,d){REQUIRE_2;POP(s);POP(s);NEWSTACKn(d,stackdepth-2);SETDST;stackdepth--;}
246 #define OP2_2(s)    {REQUIRE_2;POP(s);POP(s);NEWSTACKn(s,stackdepth-2);\
247                      NEWSTACKn(s,stackdepth-1);SETDST;}
248 #define OP3TIA_0(s) {REQUIRE_3;POP(s);POP(TYPE_INT);POP(TYPE_ADR);SETDST;stackdepth-=3;}
249 #define OP3_0(s)    {REQUIRE_3;POP(s);POP(s);POP(s);SETDST;stackdepth-=3;}
250
251 #define POPMANY(i) \
252     do { \
253         REQUIRE((i)); \
254         stackdepth -= (i); \
255         while(--(i) >= 0) { \
256             POPANY; \
257         } \
258         SETDST; \
259     } while (0)
260
261 #define DUP         {REQUIRE_1;NEWSTACK(CURTYPE,CURKIND,curstack->varnum);SETDST; \
262                     stackdepth++;}
263 #define SWAP        {REQUIRE_2;COPY(curstack,new);POPANY;COPY(curstack,new+1);POPANY;\
264                     new[0].prev=curstack;new[1].prev=new;\
265                     curstack=new+1;new+=2;SETDST;}
266 #define DUP_X1      {REQUIRE_2;COPY(curstack,new);COPY(curstack,new+2);POPANY;\
267                     COPY(curstack,new+1);POPANY;new[0].prev=curstack;\
268                     new[1].prev=new;new[2].prev=new+1;\
269                     curstack=new+2;new+=3;SETDST;stackdepth++;}
270 #define DUP2_X1     {REQUIRE_3;COPY(curstack,new+1);COPY(curstack,new+4);POPANY;\
271                     COPY(curstack,new);COPY(curstack,new+3);POPANY;\
272                     COPY(curstack,new+2);POPANY;new[0].prev=curstack;\
273                     new[1].prev=new;new[2].prev=new+1;\
274                     new[3].prev=new+2;new[4].prev=new+3;\
275                     curstack=new+4;new+=5;SETDST;stackdepth+=2;}
276 #define DUP_X2      {REQUIRE_3;COPY(curstack,new);COPY(curstack,new+3);POPANY;\
277                     COPY(curstack,new+2);POPANY;COPY(curstack,new+1);POPANY;\
278                     new[0].prev=curstack;new[1].prev=new;\
279                     new[2].prev=new+1;new[3].prev=new+2;\
280                     curstack=new+3;new+=4;SETDST;stackdepth++;}
281 #define DUP2_X2     {REQUIRE_4;COPY(curstack,new+1);COPY(curstack,new+5);POPANY;\
282                     COPY(curstack,new);COPY(curstack,new+4);POPANY;\
283                     COPY(curstack,new+3);POPANY;COPY(curstack,new+2);POPANY;\
284                     new[0].prev=curstack;new[1].prev=new;\
285                     new[2].prev=new+1;new[3].prev=new+2;\
286                     new[4].prev=new+3;new[5].prev=new+4;\
287                     curstack=new+5;new+=6;SETDST;stackdepth+=2;}
288
289
290 /*--------------------------------------------------*/
291 /* MACROS FOR HANDLING BASIC BLOCKS                 */
292 /*--------------------------------------------------*/
293
294 /* COPYCURSTACK makes a copy of the current operand stack (curstack)
295  * and returns it in the variable copy.
296  *
297  * This macro is used to propagate the operand stack from one basic
298  * block to another. The destination block receives the copy as its
299  * input stack.
300  */
301 #define COPYCURSTACK(copy) {\
302         int d;\
303         stackptr s;\
304         if(curstack){\
305                 s=curstack;\
306                 new+=stackdepth;\
307                 d=stackdepth;\
308                 copy=new;\
309                 while(s){\
310                         copy--;d--;\
311                         copy->prev=copy-1;\
312                         copy->type=s->type;\
313                         copy->flags=0;\
314                         copy->varkind=STACKVAR;\
315                         copy->varnum=d;\
316                         s=s->prev;\
317                         }\
318                 copy->prev=NULL;\
319                 copy=new-1;\
320                 }\
321         else\
322                 copy=NULL;\
323 }
324
325 /* BBEND is called at the end of each basic block (after the last
326  * instruction of the block has been processed).
327  */
328
329 #define BBEND(s,i) { \
330         (i) = stackdepth - 1; \
331         copy = (s); \
332         while (copy) { \
333                 if ((copy->varkind == STACKVAR) && (copy->varnum > (i))) \
334                         copy->varkind = TEMPVAR; \
335                 else { \
336                         copy->varkind = STACKVAR; \
337                         copy->varnum = (i);\
338                 } \
339                 rd->interfaces[(i)][copy->type].type = copy->type; \
340                 rd->interfaces[(i)][copy->type].flags |= copy->flags; \
341                 (i)--; copy = copy->prev; \
342         } \
343         (i) = bptr->indepth - 1; \
344         copy = bptr->instack; \
345         while (copy) { \
346                 rd->interfaces[(i)][copy->type].type = copy->type; \
347                 if (copy->varkind == STACKVAR) { \
348                         if (copy->flags & SAVEDVAR) \
349                                 rd->interfaces[(i)][copy->type].flags |= SAVEDVAR; \
350                 } \
351                 (i)--; copy = copy->prev; \
352         } \
353 }
354
355
356 /* MARKREACHED marks the destination block <b> as reached. If this
357  * block has been reached before we check if stack depth and types
358  * match. Otherwise the destination block receives a copy of the
359  * current stack as its input stack.
360  *
361  * b...destination block
362  * c...current stack
363  */
364
365 #define MARKREACHED(b,c) \
366     do { \
367             if ((b)->flags < 0) { \
368                     COPYCURSTACK((c)); \
369             (b)->flags = 0; \
370             (b)->instack = (c); \
371             (b)->indepth = stackdepth; \
372         } else { \
373             stackptr s = curstack; \
374             stackptr t = (b)->instack; \
375                     if ((b)->indepth != stackdepth) { \
376                             show_icmd_method(m, cd, rd); \
377                 log_text("Stack depth mismatch"); \
378                 assert(0); \
379             } \
380                     while (s) { \
381                 if (s->type != t->type) \
382                                     TYPE_VERIFYERROR(t->type); \
383                             s = s->prev; \
384                 t = t->prev; \
385                         } \
386                 } \
387     } while (0)
388
389
390 /* function prototypes ********************************************************/
391
392 bool stack_init(void);
393
394 methodinfo *analyse_stack(methodinfo *m, codegendata *cd, registerdata *rd);
395
396 void icmd_print_stack(codegendata *cd, stackptr s);
397 void show_icmd_method(methodinfo *m, codegendata *cd, registerdata *rd);
398 void show_icmd_block(methodinfo *m, codegendata *cd, basicblock *bptr);
399 void show_icmd(instruction *iptr, bool deadcode);
400
401 /* machine dependent return value handling function */
402 void md_return_alloc(methodinfo *m, registerdata *rd, s4 return_type,
403                                          stackptr stackslot);
404
405 #endif /* _STACK_H */
406
407
408 /*
409  * These are local overrides for various environment variables in Emacs.
410  * Please do not remove this and leave it at the end of the file, where
411  * Emacs will automagically detect them.
412  * ---------------------------------------------------------------------
413  * Local variables:
414  * mode: c
415  * indent-tabs-mode: t
416  * c-basic-offset: 4
417  * tab-width: 4
418  * End:
419  */